Skip to main content
Once you have a bearer token, calling the API is plain HTTP against the /v1 surface.

Base URL

The spec declares a single server relative to the backend’s deployed origin, so all paths are under that origin:
GET /openapi.json serves the live spec and GET /docs serves Swagger UI over it.

The success envelope

Domain routes return their payload as raw JSON — there is no { data: … } wrapper. A read returns the read model (an object, or a page for a list); a create returns 201 with the created resource.
The one exception is GET /v1/auth/whoami, a newer route that does wrap its payload in { data: … }. Unifying every success response under a single { data } envelope is deliberately out of scope — it would be a breaking change to the API client and both apps.

The error envelope

Every non-2xx response returns the same failure envelope:
  • code — a machine-readable kernel ResultCode. Branch on this, not on message.
  • message — a human-readable explanation, safe to surface; it never leaks server internals.
  • statusCode — the HTTP status, mirrored into the body so you need not read the headers.
A validation failure (VALIDATION_FAILED) adds a fieldErrors array, one entry per rejected field:
See Error codes for the full code → status map.

Pagination

List operations page with page and pageSize query parameters and return a page read model. Request the next page by incrementing page:

Validation

Request bodies, path params and query params are validated at runtime from the same schemas that generate the spec, so a request that does not match the documented shape is rejected with the standard VALIDATION_FAILED envelope — the documentation and the validator can never drift apart.