# API reference Base URL (local): `http://localhost:8080`. All responses are JSON with camelCase fields. All endpoints require `Authorization` (Basic) and `X-Tenant` headers **except** the two marked public. | Method | Path | Purpose | | ------ | ---- | ------- | | GET | `/api/health` | Liveness (**public**) | | GET | `/api/tenants` | Agency list for the sign-in picker (**public**) | | GET | `/api/session` | Current user + tenant; validates credentials | | GET | `/api/flights` | Search inventory (see parameters) | | GET | `/api/flights/{id}` | One flight | | GET | `/api/airports` | Airports in this tenant's network | | GET | `/api/airlines` | Carriers in this tenant's inventory | | GET | `/api/bookings` | List bookings (`?status=confirmed|cancelled`) | | POST | `/api/bookings` | Create a booking | | GET | `/api/bookings/{id}` | One booking with passengers | | POST | `/api/bookings/{id}/cancel` | Cancel; returns seats to inventory | | GET | `/api/dashboard` | Agency totals, top routes, recent bookings | ## Flight search parameters `GET /api/flights` accepts: `origin`, `destination` (IATA codes), `date` (`YYYY-MM-DD`), `cabin` (`economy|premium_economy|business|first`), `passengers` (min seats free), `sort` (`price|duration|departure`), `limit`, `offset`. Only future, non-cancelled flights with enough seats are returned. ```bash curl -u agent@skyline.test:demo1234 -H 'X-Tenant: skyline' \ 'http://localhost:8080/api/flights?origin=JFK&destination=LHR&sort=price&limit=5' ``` ## Create a booking `POST /api/bookings` ```json { "flightId": "uuid", "contactEmail": "ops@example.com", "contactPhone": "+1-555-0100", "passengers": [ { "firstName": "Dana", "lastName": "Whitfield", "dateOfBirth": "1988-04-12", "passportNumber": "X1234567" } ] } ``` Server-controlled (never trust the client for these): the tenant, the fare, the total, and the PNR. Unknown fields are rejected (`400`). ## Status codes & contracts | Code | When | | ---- | ---- | | 200 / 201 | success (201 on create) | | 400 | invalid input (bad date/cabin, malformed JSON, unknown field, validation) | | 401 | missing/invalid credentials, or credentials for the wrong tenant | | 403 | admin-only route refused to an agent | | 404 | not found **or** belongs to another tenant (existence is hidden) | | 409 | not enough seats (oversell prevented) | | 500 | server error (generic message; no internals leaked) | The full request/response of each call is captured in the e2e evidence report (with the `Authorization` header redacted). Types are defined in [`backend/internal/models`](../../backend/internal/models/models.go).