Agapi Platform Documentation
Central Backend Engine

Symfony Backend

Why the api repository exists, which business responsibilities it owns, and how admin and member requests share data.

The api repository provides the newer server-side part of Agapi. It gives staff, member clients, and approved integrations a consistent way to work with bookings, fleet, members, payments, messages, files, and reports.

Its purpose is to protect business rules at the server boundary. A screen can hide an invalid choice, but the backend must still reject an unauthorized user, an overlapping booking, a missing company, or an invalid payment request.

Two API applications, one business data model

The Symfony code starts in two contexts:

ContextWho it servesWhy it is separate
Admin APIStaff portal and approved service users.Staff can search broadly, manage settings, run reports, and perform operational changes.
Member APICurrent member clients.Members should receive only their own profile/trips and public fleet or support information.

They share entities, repositories, services, and the same business vocabulary. The member API is deliberately smaller; staff capability must not become member capability just because the underlying code is shared.

flowchart TD
    Staff[Staff portal] --> Admin[Admin API /api/v1]
    Member[Member client] --> Mobile[Member API /api]
    Partner[Approved external system] --> Public[Integration-specific public API]
    Admin --> Rules[Shared business rules]
    Mobile --> Rules
    Public --> Rules
    Rules --> Data[(PostgreSQL records)]
    Rules --> External[Stripe, messages, files, FMP]

What the repository contributes to the product

Business areaSymfony responsibility
AccessAuthenticate staff, members, and service/integration callers and apply role, account, region, and location scope.
MembersCreate and update members, show booking/request context, manage balances, ratings, activity, and newsletter audiences.
FleetManage boats, models, places, facilities, checklists, issue categories, issues, service visits, and availability.
BookingsCreate and change bookings, protect state changes, record history, serve dashboards, service requests, and linked issues.
Booking requestsKeep unresolved demand separate from confirmed reservations and control allowed states.
PaymentsCreate/cancel invoices and subscriptions, select the correct company Stripe account, and apply later webhook results.
CommunicationPrepare email, SMS, and push work and preserve delivery information.
ReportsAnswer specific operational and financial questions and create matching exports.
IntegrationsExchange booking/availability data with approved external callers and send check-in/out status to fleet monitoring.

How a request becomes a business change

sequenceDiagram
    actor Caller
    participant Access as Access check
    participant Endpoint as Feature endpoint
    participant Rules as Repository/service rules
    participant DB as PostgreSQL
    participant Provider as Optional external provider

    Caller->>Access: identity and request
    Access->>Endpoint: allowed caller and scope
    Endpoint->>Rules: validated business input
    Rules->>DB: read or save current state
    opt payment, message, or fleet update
        Rules->>Provider: provider request
    end
    Endpoint-->>Caller: result or clear error

The order matters. If a database save succeeds and a provider request fails—or the other way around—the operation may need reconciliation rather than a full retry.

Company, account, and location scope

Most shared records carry an account_id, and staff users can also be limited to regions or locations. Financial operations additionally choose a company.

These scopes solve different problems:

  • account keeps tenants and their configuration separate;
  • region/location limits operational visibility;
  • company selects the legal and payment context.

They should not be substituted for one another.

Access roles

The server recognizes viewer, manager, admin, service, and customer contexts. Admin inherits manager capability; manager inherits viewer and selected service capability. The exact endpoint rule comes from server security and feature code, not from whether a button is visible in the browser.

Data storage in plain language

PostgreSQL stores Agapi's operational history. Many records use normal identity and account columns plus flexible JSON sections called data and meta.

This supports older and newer code reading the same records, but it also means a number written inside JSON is not automatically a protected database link. When changing stored data, developers must preserve the meaning expected by both repositories.

See Business Data Dictionary for every entity and its purpose.

Feature references

Technical reference

The source is under api/symfony. Admin controllers live in apps/admin/src/Controller, member controllers in apps/mobile/src/Controller, and shared entities/repositories/services in src. Locally, the admin context is served on port 80, the member context on 8080, and PostgreSQL on host port 5435 with the checked-in Compose mappings.

On this page