REST API
This reference is hand-authored directly from
openapi.yaml
(the repository’s source of truth — 54 documented paths), one page per
route group, rather than generated by a Starlight OpenAPI integration.
That was a deliberate call for this pass: hand-authoring lets every page
carry the same prose/example density as the rest of these docs (the
why, not just the shape), and avoids depending on a third-party
Starlight plugin’s own compatibility with this project’s Starlight/Astro
versions on a deadline. If openapi.yaml and this reference ever drift,
openapi.yaml is correct — it’s checked directly by CI-style tooling
against the route definitions, this page isn’t.
Base URL and auth
Section titled “Base URL and auth”Every path below is relative to /api (e.g. GET /api/health), with one
exception noted on its own page: GET /metrics
is mounted at the server root. Authenticate with
Authorization: Bearer <token> — either a superuser token, an
auth-collection record’s token, or a dashboard-minted API key.
Endpoints marked unauthenticated below accept no bearer token at all
(they’re either public by design, like /health, or authenticate a
different way, like /webhooks/stripe’s signature header).
Error shape
Section titled “Error shape”Every error response is:
{ "code": 400, "message": "Failed to create record.", "data": { "title": { "code": "validation_required", "message": "Cannot be blank." } } }data is populated with per-field validation errors when code is
400; it’s an empty object for other error codes. See
Error responses for the full shape,
including why a rule-denied record and a nonexistent one are both a
404, never a 403.
Route groups
Section titled “Route groups”| Group | Covers |
|---|---|
| Health & setup | /health, /setup/status, /setup |
| Collections | CRUD, import, scaffolds, truncate |
| Records | Generic list/view/create/update/delete |
| Auth | Password, refresh, verification, reset, email change, OTP, impersonation |
| Files | Download, file tokens |
| Realtime | SSE connect + subscribe |
| Batch | POST /api/batch |
| Settings | Get/patch settings, S3/email/Apple test endpoints |
| Logs | Search, view, stats |
| Backups | List, create, upload, download, restore |
| Crons | List, run-now |
| Functions | Read-only pb_hooks inspection |
| Schema | Diff-and-apply schema-as-code |
| API keys | Mint an API key |
| Push | Send a push notification |
| LLM | Chat gateway |
| MCP | Model Context Protocol JSON-RPC dispatch |
| Tool schema | Function-calling schema for one collection |
| SQL console | Ad-hoc SQL |
| File manager | Raw object-store browsing |
| Utils | Avatar and QR code generation |
| Metrics | Prometheus exposition |
Several system collections have no dedicated REST surface at all —
they’re reached through the generic Records API
(/collections/{name}/records) documented on the
Records page, gated end to end by
that collection’s own rules: _webhooks (outgoing webhook config),
_teams/_team_members (workspace membership), _audit_log
(append-only action history), and _push_subscriptions (registered push
targets). _cron_jobs and _api_keys are listed read-only through
GET /crons and created through
POST /api-keys respectively, but
otherwise managed the same generic way.
Shared schemas
Section titled “Shared schemas”Record — every record has id, created, updated,
collectionId, collectionName, plus its collection’s own schema
fields.
Collection — id, name, type (base/auth/view), schema
(array of field definitions), listRule/viewRule/createRule/
updateRule/deleteRule (nullable strings — null means superuser-only,
not “no rule”), authOptions (auth collections only), created,
updated.
FieldSchema — id, name, type, required, unique, options
(shape depends on type; see Field types).