API
API Overview
The backend surface at a glance
Base URL in dev: http://localhost:3001. The live, always-accurate reference is the API's own Scalar page at /docs (spec at /openapi.json, auth endpoints at /api/auth/reference). These pages explain the concepts and flows instead.
Surface
| Route | Auth | What |
|---|---|---|
GET /health | — | Liveness |
POST /api/wishlist | — | Join the wishlist (details) |
GET /api/wishlist/count | — | Signup total |
/api/auth/* | — | Sign-up / sign-in / sessions (details) |
GET /api/me | optional | Current user or null |
/api/invites… | mostly ✓ | Invitations (details) |
/api/achievements… | mostly ✓ | Achievements (details) |
Conventions
- Validation: every body/param is validated with a Zod schema from
@repo/shared; failures return400 { error: "Validation failed", issues: [...] }. - Errors: always
{ error: string }with a meaningful status. Unhandled errors become a logged500. - Rate limiting:
/api/wishlist/*is limited to 10 req/min/IP (in-memory — swap for Redis when the API runs on more than one instance). - CORS: only origins in
CORS_ORIGINSmay call/api/*with credentials. - Sessions: better-auth cookie, sent with
credentials: "include".
Adding an endpoint
- Add/extend schemas in
packages/shared/src/. - Define a
createRoute+ handler in the route file (or a new factory inapps/api/src/routes/, mounted inapp.ts). - Write a test in
apps/api/test/usingmakeTestApp()— it exercises the real app against in-memory Postgres. - The Scalar docs update themselves from the route definition.