Keys Please Valet API
v1.0 · Express + JWT · matches platform spec
Auth
POST /auth/login public — staff login, returns JWT
GET /auth/me jwt — current user
Tickets (Staff)
GET /tickets?status=requested jwt — list active tickets
POST /tickets jwt — create check-in
POST /tickets/:id/video/sign jwt — phase 1: Cloudinary signed upload preset
POST /tickets/:id/video jwt — phase 2: confirm walk-around video uploaded
POST /tickets/:id/park jwt — assign stall & park (requires video)
POST /tickets/:id/complete-retrieval jwt — mark delivered
GET /tickets/:id/timeline jwt — full event log
Parking
GET /parking/map jwt — full stall layout
GET /parking/occupancy jwt — live occupancy stats
Reports (Manager / Operator)
GET /reports/summary?days=7 mgr/op — KPIs + deltas
GET /reports/revenue?days=7 mgr/op — daily revenue timeseries
GET /reports/hourly?days=14 mgr/op — hour-of-day check-in heatmap
GET /reports/staff?days=7 mgr/op — attendant leaderboard
GET /reports/activity?limit=30 mgr/op — recent events feed
GET /reports/videos?limit=50 mgr/op — uploaded walk-around audit
GET /reports/venues?days=7 operator — per-venue rollup for switcher
Public (Guest PWA)
GET /public/venue?org_id=… org_id — venue info from QR
POST /public/tickets org_id — guest self check-in
GET /public/tickets/:token org_id — poll ticket status
GET /public/tickets/:token/timeline org_id — guest timeline
POST /public/tickets/:token/request-retrieval org_id — "Request My Car"
GET /public/tickets/:token/quote org_id — current fare
POST /public/tickets/:token/pay org_id — settle & pay
Platform (Network-wide)
GET /platform/operators?days=30 platform — list operators with rollup
GET /platform/operators/:id platform — single operator detail
GET /platform/summary?days=30 platform — network totals
GET /platform/activity?limit=40 platform — network event stream
POST /platform/onboard platform — create operator + first venue + first manager
Incidents (Damage / Theft / Disputes)
GET /incidents?status=open&severity=damage mgr/op — list with filters
GET /incidents/:id mgr/op — single incident detail
POST /incidents jwt — flag from a ticket
POST /incidents/:id/review mgr/op — begin investigation
POST /incidents/:id/resolve mgr/op — close with outcome
GET /incidents/ticket/:ticket_id jwt — all incidents on a ticket
Health
GET /health public
GET /realtime/stats public — active socket count
Realtime (WebSocket)
WS /realtime?token=<jwt> jwt — staff/manager event stream
WS /realtime?org_id=<id>&ticket_token=<n> org_id — guest event stream (per ticket)
Demo creds (password "demo" for all — stored as bcrypt hashes)
Platform admin: morgan@keysplease.dev — entire network (both operators)
SF Operator: alex@keysplease.dev — 3 SF venues
LA Operator: sasha@keysplease.dev — 3 LA venues
Venue Manager: dani@keysplease.dev (Sable), devon@keysplease.dev (Chateau)
Attendants: mauricio@, priya@, omar@, jin@, carlos@, mia@, tomas@, rachel@