API Reference
Base URL: https://tee-api.<account>.workers.dev/api/v1. All routes are
Authorization: Bearer <JWT> protected unless listed under Public.
This is a hand-maintained overview grouped by route mount (see
apps/api/src/index.ts for the exact mount order) — not an
auto-generated OpenAPI spec. Adding one (hono-openapi + a schema per
route) is straightforward but wasn't pulled in as a runtime dependency
just for documentation generation; each route file already documents its
own request/response shape inline as TypeScript types, which is the
source of truth.
Public (no JWT)
| Mount | Purpose |
|---|---|
/auth/* | PIN login, SA email+PIN+2FA login, forgot-PIN/reset-PIN |
/public/* | Branch list, customer wallet lookup, public menu, tracking config |
/payments/khqr/webhook, /payments/aba/callback | PSP webhooks — HMAC/hash verified inside the route, not by JWT |
/delivery/grab/webhook, /delivery/nham24/webhook | Delivery partner webhooks — same pattern |
/kds/feed | WebSocket — token passed as a query param (a browser WS handshake can't carry a header) |
Staff-authenticated (branch-scoped JWT)
| Mount | Covers |
|---|---|
/menu | Categories, products, variants, per-branch price/availability overrides, delete |
/orders | Create (idempotent), list, refund, payments |
/payments | Cash tender, KHQR create/status, ABA PayWay create/status |
/members | Lookup, create, points, tier |
/reports | Dashboard, cross-branch aggregate + audit log (reports:global), sales |
/shifts | Open/close, cash reconciliation |
/payroll | Runs, approval |
/branches | List, edit |
/promotions | CRUD, validation |
/inventory | Stock, movements, purchase orders, forecasting |
/gift-cards | Issue, redeem, balance |
/users | Staff CRUD, PIN reset (users:manage — OWNER, or a BRANCH_MANAGER for their own branch's subordinates) |
/rates | KHR/USD exchange rate |
/scheduling | Shift templates, timeclock |
/royalty | Franchise royalty invoices |
/experiments | A/B test CRUD + results (HQ_MANAGER/MARKETING/OWNER) |
Platform-authenticated (/sa/*, Super Admin JWT + 2FA)
Tenants, users, impersonation, integrations (credential CRUD + test),
config, audit log, D1 backups, analytics export, TOTP setup, delivery
simulation. Every /sa/* route requires is_super_admin on the JWT —
see lib/auth-mw.ts's requireSuperAdmin.
Conventions
- Idempotency:
POST /ordersaccepts anIdempotency-Keyheader — retries return the original response instead of creating a duplicate. - Errors:
{ error: { code: string, message?: string } }. - Money: KHR as a plain integer (no cents); USD conversion happens at
render time via
/rates, never stored as the source of truth. - Roles: 9 roles with real separation of duties (not a linear
hierarchy) — OWNER, HQ_MANAGER, BRANCH_MANAGER, CASHIER, BARISTA,
INVENTORY_KEEPER, MARKETING, ACCOUNTANT, AUDITOR (read-only everywhere).
Checked with
requirePermission('resource:action')against a per-role permission-string list inlib/auth-mw.ts— see the main README's Roles & permissions section for the full table and the branch-scoping rules that go with it.