backend/apps/core-api. src/app.ts builds the app and src/modules/index.ts (buildV1Router) mounts every domain router under /v1. The same process also serves the better-auth handler and the oRPC API under /api, an MCP endpoint under /mcp, and three operational endpoints.
Base URLs
All examples in this reference use the production host. Paths are always shown in full, including the
/v1 prefix and the lane prefix.
Versioning
There is one version,/v1. Nothing in the code negotiates a version through headers. Endpoints outside /v1 are not versioned: /healthz, /readyz, /metrics, /api/* and /mcp.
The trainee app is shipped to stores, so old builds keep calling old shapes. The API handles that inside /v1 by keeping legacy fields on the wire instead of adding a /v2. Examples are called out on the pages where they matter, such as the retired POST /v1/trainee/health/samples and the null heart-rate keys on GET /v1/trainee/health/summary.
Lanes
A lane is a group of mounts that share one way of authenticating the caller. The lane decides which principal ends up on the request.
How each credential is checked, with example requests, is on Authentication.
Older notes describe
/v1/<module> as “the bearer lane for the mobile app”. That is no longer true. The mobile app only calls /v1/trainee/* with its own token. The bearer lane still exists in modules/index.ts but covers three routers only.Mount map
Everyrouter.use in buildV1Router, in registration order. Order matters in two places: the specific /trainee/<module> mounts come before the catch-all /trainee router, and /web/studios/current/api-keys comes before /web/studios.
Webhook, internal and admin
Trainee
Partner, automation and public
Web gateway
Every row below runsrequireServiceAuth, then webUserContext, then the web rate limiter. Role guards inside each router are documented on that router’s page.
Bearer
Registered last, afterrouter.use(replay). Replay protection therefore only applies to these three mounts.
Mounted outside /v1
These come from src/app.ts.
None of the operational endpoints use the JSON envelope, and none of them are authenticated by the app itself.
Request pipeline
Every request passes through this chain before it reaches a router:helmet()andcors()with origins fromCORS_ORIGIN(comma separated, or*).requestIdMiddleware, which setsreq.requestIdand theX-Request-Idresponse header.- Body parsers. JSON up to
24mbby default,48mbon/v1/web/plan-import/analyzeand/v1/web/forms-ai/analyze,4mbon/v1/public/sign. Rawapplication/octet-streambodies up to12mb. Each parser keeps the raw bytes onreq.rawBodyso signatures can be verified over them. cookieParser()and the HTTP logger.- The route’s own rate limiter and lane middleware.
notFoundMiddlewareanderrorMiddlewarefrom@perform/errors.
app.set('trust proxy', 1) is set first, so req.ip is the client address forwarded by the one reverse proxy in front of the container. The rate limiters depend on that.
How to read the reference
Each page covers one router or one slice of a large router. It opens with the mount path, the router factory and the guards, then lists every endpoint in the routes file:- Heading: method and full path, for example
GET /v1/trainee/workouts. - Auth: the lane and any extra guard.
- Parameters: taken from the Zod schema in the module’s
*.schema.ts, with types, defaults and limits. - Response: the HTTP status and a JSON example with the real field names. Ids and values in examples are invented.
- Errors: the
AppErrorcodes the service throws. Every authenticated endpoint can also return the lane errors listed on Authentication and the generic ones on Conventions, so pages do not repeat those.
- Partner API returns bare JSON objects.
- Automation API returns
{ success, message, data }. - The public signing lane and
POST /v1/public/waitlist-leadsreturn their own small shapes. See Public endpoints.
Authentication
Signing steps and example requests for every lane.
Conventions
Envelope, error codes, pagination, dates, ids and rate limits.
Trainee sign-in
The WhatsApp OTP flow and the trainee token.
Automation API
The studio API key lane used by Make.com.