Skip to main content

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)

MountPurpose
/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/callbackPSP webhooks — HMAC/hash verified inside the route, not by JWT
/delivery/grab/webhook, /delivery/nham24/webhookDelivery partner webhooks — same pattern
/kds/feedWebSocket — token passed as a query param (a browser WS handshake can't carry a header)

Staff-authenticated (branch-scoped JWT)

MountCovers
/menuCategories, products, variants, per-branch price/availability overrides, delete
/ordersCreate (idempotent), list, refund, payments
/paymentsCash tender, KHQR create/status, ABA PayWay create/status
/membersLookup, create, points, tier
/reportsDashboard, cross-branch aggregate + audit log (reports:global), sales
/shiftsOpen/close, cash reconciliation
/payrollRuns, approval
/branchesList, edit
/promotionsCRUD, validation
/inventoryStock, movements, purchase orders, forecasting
/gift-cardsIssue, redeem, balance
/usersStaff CRUD, PIN reset (users:manage — OWNER, or a BRANCH_MANAGER for their own branch's subordinates)
/ratesKHR/USD exchange rate
/schedulingShift templates, timeclock
/royaltyFranchise royalty invoices
/experimentsA/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 /orders accepts an Idempotency-Key header — 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 in lib/auth-mw.ts — see the main README's Roles & permissions section for the full table and the branch-scoping rules that go with it.