Surface
HTTP & sockets
Versioned under /api/v1. Sockets share the same ingest, chat, and SOS services.
| Route | Auth | Loop | Demo vs production |
|---|---|---|---|
| POST/api/v1/pvsp/leases Open PVSP lease app/api/v1/pvsp/leases/route.ts | signed-in renter | PVSP per-trip binder | Memory lease + hold-harmless hash. Prisma PvspLease. Same FSM. |
| POST/api/v1/pvsp/leases/:id/transitions CRT transition / bind app/api/v1/pvsp/leases/[id]/transitions/route.ts | signed-in | PVSP per-trip binder | Simulated Lula/Tint/ABI binder. INSURANCE_API_URL. Driver named insured. |
| POST/api/v1/telemetry Browser snapshot app/api/v1/telemetry/route.ts | public (session attached if present) | — | Writes last 200 snapshots to .data/telemetry.json. Same shape; store moves to Postgres. No card data, no GPS prompt. |
| GET/api/v1/listings/photos Listing JPEG app/api/v1/listings/photos/route.ts | public URL (UUID) | — | Reads .data/listings/{carId}/{id}.jpg. Supabase Storage / R2 signed GET. |
| GET/api/v1/health Health app/api/v1/health/route.ts | public | — | Returns region + memory adapters. Same JSON; adapters flip to postgres/redis/amqp when env is set. |
| GET/api/v1/platform/status Go-live status app/api/v1/platform/status/route.ts | public (no secrets) | — | mode=demo, billsTodayUsd=0, checklist. blockers listed if GO_LIVE=true but gates fail. |
| POST/api/v1/platform/demo Investor demo loop app/api/v1/platform/demo/route.ts | public, rate-limited | Trip lifecycle | Runs the full in-memory marketplace loop. Still isolated memory — never charges cards. |
| GET/api/v1/metrics Prometheus app/api/v1/metrics/route.ts | public scrape | — | Counters from this process. Same text format for Grafana. |
| GET/api/v1/fleet/telematics Latest vehicle ping app/api/v1/fleet/telematics/route.ts | signed-in | Telematics hook-in | Simulated Temescal ping. Hosts omit lat/lng. Same shape from TELEMATICS_PROVIDER. |
| POST/api/v1/fleet/telematics Telematics webhook app/api/v1/fleet/telematics/route.ts | desk or x-telematics-secret | Telematics hook-in | Secret defaults to demo. TELEMATICS_WEBHOOK_SECRET + vendor keys. |
| POST/api/v1/auth/token Issue access + refresh app/api/v1/auth/token/route.ts | signed-in session | — | HS256 with demo secret. Requires non-default JWT_SECRET. |
| POST/api/v1/auth/refresh Rotate refresh app/api/v1/auth/refresh/route.ts | refresh token | — | Reuse detection revokes the family. Same algorithm; store moves to Postgres later. |
| POST/api/v1/geo/pings GPS ping app/api/v1/geo/pings/route.ts | driver | GPS ingest | Memory presence, 2 rps bucket. Redis GEO/H3 sets. |
| GET/api/v1/geo/drivers H3 driver lookup app/api/v1/geo/drivers/route.ts | driver/staff/admin | Proximity lookup | Haversine ETA. Mapbox/Google if keyed. |
| POST/api/v1/trips Request trip app/api/v1/trips/route.ts | rider | Trip lifecycle | Idempotency-Key required. Same + durable trips. |
| GET/api/v1/trips List my trips app/api/v1/trips/route.ts | signed-in | — | Filters to principal. Same. |
| GET/api/v1/trips/:id Get trip app/api/v1/trips/[id]/route.ts | owner or staff | — | 404/403 as expected. Same. |
| POST/api/v1/trips/:id/transitions FSM transition app/api/v1/trips/[id]/transitions/route.ts | actor-checked | Trip lifecycle | Idempotency-Key required. Same. |
| POST/api/v1/dispatch/match Run match tick app/api/v1/dispatch/match/route.ts | staff/admin | Batch matching | Hungarian over memory presence. Same code, Redis presence. |
| POST/api/v1/payments/holds Authorize hold app/api/v1/payments/holds/route.ts | rider | Escrow & ledger | Ledger only, processor=demo. Blocked unless go-live checklist is green + Stripe. |
| POST/api/v1/payments/payouts Instant cash-out app/api/v1/payments/payouts/route.ts | host/driver | Escrow & ledger | Journal to stripe_pending. Connect transfer after 1099 switch. |
| POST/api/v1/uploads/sign Signed upload app/api/v1/uploads/sign/route.ts | signed-in | — | Memory PUT target. R2/S3 when UPLOAD_DRIVER=s3. |
| POST/api/v1/fleet/inspections Inspection app/api/v1/fleet/inspections/route.ts | driver/host | Keyless access & inspection | Four photo ids minimum. Same + object store. |
| POST/api/v1/fleet/unlock Unlock vehicle app/api/v1/fleet/unlock/route.ts | matched driver/rider | Keyless access & inspection | Simulated IoT accept. IOT_UNLOCK_WEBHOOK. |
| POST/api/v1/safety/sos SOS app/api/v1/safety/sos/route.ts | trip participant | SOS & telemetry | Log + share URL. Push + dispatch. |
| POST/api/v1/comms/chat Masked chat app/api/v1/comms/chat/route.ts | signed-in | — | Phones/emails redacted. Same + socket fan-out. |
| POST/api/v1/trust/webhooks Persona/SumSub/Checkr app/api/v1/trust/webhooks/route.ts | x-webhook-secret | — | Accepts status updates. Set TRUST_WEBHOOK_SECRET. |
| GET/docs This documentation app/docs/page.tsx | public | — | Live status + loops. Same site, mode badge flips. |
Auth is a Bearer access token or the existing session cookie. Dispatch and auth sit behind token buckets. Trip writes require Idempotency-Key.
driver:ping → LocationIngest (3–5s)
trip:subscribe → room trip:{id}
chat:message → MaskedChat (PII stripped)
sos:trigger → SafetyService + broadcast