# InterCity — API guide for agents > Carpooling marketplace for Namibia (`NA`), South Africa (`ZA`), and Botswana (`BW`). Passengers book seats or parcel space on driver-published trips. Website: https://intercity.com.na API base: `https://servercity.azurewebsites.net` Index: https://intercity.com.na/llms.txt All paths below are relative to the API base. Send `Accept: application/json`. Authenticated requests use `Authorization: Bearer `. --- ## 1. Overview - **Public (no auth):** list upcoming trips, fetch a public trip, list towns, top routes, health. - **Firebase Bearer:** `/authorize`, `/register/passenger`, `/register/driver` — use a Firebase ID token. - **API JWT:** everything else after login (bookings, full trip details, user profile). Obtained from `/authorize` or register responses as `token`. Towns have numeric `id` values and human `name` strings. Prefer filtering by town `id`. Country scope with `countryId=NA|ZA|BW`. Human deep links (SPA): | Flow | URL | |------|-----| | Search | `https://intercity.com.na/search?from=&to=&date=YYYY-MM-DD` | | Trip detail | `https://intercity.com.na/trips/` | | Sign in | `https://intercity.com.na/login` | | My bookings | `https://intercity.com.na/account/bookings` | --- ## 2. Authentication InterCity uses **two tokens**: 1. **Firebase ID token** — from Firebase Auth (Google, Apple, or email/password). 2. **API JWT** — from InterCity after authorize/register. Use this for bookings and other app APIs. ### 2.1 Obtain a Firebase ID token Sign the user in with Firebase Auth (web SDK, REST, or Admin-issued custom tokens are out of scope here). Then call `user.getIdToken()` (or the equivalent) to get a short-lived Firebase ID token. Firebase project (production): `servercity-aba6d` (auth domain `servercity-aba6d.firebaseapp.com`). ### 2.2 Exchange for an API JWT ```http GET /authorize Authorization: Bearer ``` Success `200`: ```json { "token": "", "user": { "id": "...", "firstName": "...", "type": "passenger", "countryId": "NA" } } ``` The API JWT may also appear in the `X-token` response header. Store `token` and send it as `Authorization: Bearer ` on subsequent calls. If the Firebase user is not registered in InterCity (`401` or `404`), complete passenger registration (below) then retry authorize or use the token from the register response. Optional country hint: ```http POST /authorize Authorization: Bearer Content-Type: application/json { "user": { "countryId": "NA" } } ``` ### 2.3 Register a passenger (first-time users) ```http POST /register/passenger Authorization: Bearer Content-Type: application/json { "user": { "firstName": "Jon", "lastName": "Manga", "mobile": "+264811234567", "gender": "male", "dob": "1980-01-01T00:00:00.000Z", "type": "passenger", "countryId": "NA", "platform": "web" } } ``` Required on `user`: `firstName`, `lastName`, `gender`, `dob`, `type`, `mobile`. Response includes `token` (API JWT) and `user`, same shape as authorize. Driver registration is `POST /register/driver` (driver-specific profile fields; drivers typically need an active subscription to publish trips — error code `105`). ### 2.4 Curl: authorize ```bash curl -sS "https://servercity.azurewebsites.net/authorize" \ -H "Authorization: Bearer ${FIREBASE_ID_TOKEN}" ``` --- ## 3. Upcoming trips (public) No authentication required. Returns **active, future** trips with redacted driver/vehicle fields (no mobile, last name, registration, Firebase UID). Booking still requires an API JWT. ### 3.1 List ```http GET /trips/public?countryId=NA&limit=20&skip=0 ``` | Query | Required | Notes | |-------|----------|--------| | `countryId` | no | `NA`, `ZA`, or `BW` — **this is the main server-side filter today** | | `from` | no | Departure town ID (documented in OpenAPI; **not applied by the current server** — filter client-side) | | `to` | no | Destination town ID (same caveat) | | `date` | no | ISO 8601 start date (same caveat; server defaults to “now” via `tripDate > now`) | | `limit` | no | Page size | | `skip` | no | Offset | **Important:** Today the backend filters by `countryId` + active + `tripDate > now` only. To search Windhoek → Oshakati, fetch public trips for `countryId=NA`, resolve town IDs from `/towns`, then filter where `departure.id` / `destination.id` (or names) and `tripDate` match. Example response item (shape abbreviated): ```json { "id": 46900, "tripDate": "2028-02-01T02:27:00.000Z", "price": 1500, "type": "driver", "countryId": "NA", "seatsAvailable": 3, "seatsTotal": 4, "departure": { "id": 1, "name": "Windhoek", "countryId": "NA" }, "destination": { "id": 26, "name": "Oshakati", "countryId": "NA" }, "driver": { "name": "Nyoncé" }, "vehicle": { "manufacturer": "TOYOTA", "model": "Corolla", "year": 2019, "seats": 4 } } ``` Envelope: `{ "data": [ ... ], "meta": { "total": N } }`. ### 3.2 Single public trip ```http GET /trips/public/{id} ``` ### 3.3 Authenticated trip list (richer) ```http GET /trips Authorization: Bearer ``` Returns full trip payloads for the authenticated context (not redacted like public). ### 3.4 Curl: upcoming trips ```bash curl -sS "https://servercity.azurewebsites.net/trips/public?countryId=NA&limit=20" ``` --- ## 4. Towns and popular routes ### 4.1 Towns ```http GET /towns?countryId=NA ``` Returns `{ "data": [ { "id": 1, "name": "Windhoek", "countryId": "NA", ... }, ... ] }`. Use `id` values when filtering trips locally (`departure.id`, `destination.id`). Also available: `GET /countries` and `GET /countries/{id}/towns`. ### 4.2 Top routes ```http GET /routes/top?countryId=NA&limit=10 ``` Popular departure/destination pairs with counts and optional fare hints. ### 4.3 Curl: towns ```bash curl -sS "https://servercity.azurewebsites.net/towns?countryId=NA" ``` --- ## 5. Booking Requires **API JWT** (not the Firebase ID token). ### 5.1 Create a booking ```http POST /bookings Authorization: Bearer Content-Type: application/json { "tripId": "46900" } ``` `tripId` is a string. Success `200` returns the `Booking` object. ### 5.2 List my bookings ```http GET /bookings Authorization: Bearer ``` ### 5.3 Get one booking ```http GET /bookings/{id} Authorization: Bearer ``` ### 5.4 Cancel a booking ```http PATCH /bookings/{id}/cancel Authorization: Bearer ``` ### 5.5 Curl: book a trip ```bash # 1) List public trips and pick an id curl -sS "https://servercity.azurewebsites.net/trips/public?countryId=NA&limit=5" # 2) Authorize (Firebase ID token → API JWT) API_JWT=$(curl -sS "https://servercity.azurewebsites.net/authorize" \ -H "Authorization: Bearer ${FIREBASE_ID_TOKEN}" | jq -r .token) # 3) Book curl -sS "https://servercity.azurewebsites.net/bookings" \ -H "Authorization: Bearer ${API_JWT}" \ -H "Content-Type: application/json" \ -d '{"tripId":"46900"}' ``` --- ## 6. Errors agents should handle | Signal | Meaning | |--------|---------| | HTTP `401` | Missing/invalid token, or Firebase user not registered — authorize or register | | HTTP `403` | Authenticated but not allowed for this resource | | HTTP `404` | Trip/booking/user not found | | HTTP `422` | Validation failed (check body/query) | | Body `code: 105` | Subscription required (typical for driver publish/create-trip flows) — message often in `response.data.body.message` | | Network / 5xx | Retry with backoff; do not invent trip data | Public trip payloads omit contact details; do not expect phone numbers from `/trips/public`. --- ## 7. Quick reference | Action | Method | Path | Auth | |--------|--------|------|------| | Health | `GET` | `/` or `/health-checks` | none | | Upcoming trips | `GET` | `/trips/public` | none | | Public trip | `GET` | `/trips/public/{id}` | none | | Towns | `GET` | `/towns` | none | | Top routes | `GET` | `/routes/top` | none | | Authorize | `GET` | `/authorize` | Firebase Bearer | | Register passenger | `POST` | `/register/passenger` | Firebase Bearer | | Trips (full) | `GET` | `/trips` | API JWT | | Create booking | `POST` | `/bookings` | API JWT | | List bookings | `GET` | `/bookings` | API JWT | | Cancel booking | `PATCH` | `/bookings/{id}/cancel` | API JWT | --- ## 8. Suggested agent workflow 1. `GET /towns?countryId=NA` — map names ↔ IDs. 2. `GET /trips/public?countryId=NA` — load upcoming trips; filter by `departure` / `destination` / `tripDate` locally. 3. Present options to the user (price, seats, date, route). 4. If booking: ensure Firebase sign-in → `GET /authorize` (or register) → `POST /bookings` with `tripId`. 5. Confirm with `GET /bookings` or deep-link `https://intercity.com.na/trips/{id}`.