Docs/Reference
HTTP API
Every route a GoLocomotive app serves, with its body and its answer; PocketBase's wire shape throughout.
An app speaks PocketBase's REST wire. Any PocketBase client works against it.
Conventions#
- Auth:
Authorization: <token>. A Bearer prefix is accepted. An invalid or expired token makes the caller a guest, never an error. - Errors: every error is
{ status, message, data }. data is { <field>: { code, message } } for a validation error, else {}. - Unknown failures: a throw that is not an
ApiError answers 400 Something went wrong while processing your request. and is logged. - Dates: UTC text,
YYYY-MM-DD HH:MM:SS.sssZ. Ids: 15 characters [a-z0-9].
Health#
| route | answer |
|---|
GET /api/health | { code: 200, message: 'API is healthy.', data: {} }. A superuser also gets data: { canBackup, realIP, possibleProxyHeader } |
Records#
| route | body or query | answer |
|---|
GET /api/collections/:c/records | page perPage sort filter expand fields skipTotal | { page, perPage, totalItems, totalPages, items }; totals are -1 under skipTotal |
GET /api/collections/:c/records/:id | expand fields | the record |
POST /api/collections/:c/records | JSON, or multipart with files (the JSON part in @jsonPayload) | the record |
PATCH /api/collections/:c/records/:id | the same | the record |
DELETE /api/collections/:c/records/:id | | 204 |
POST /api/batch | { requests: [{ method, url, body }] }, at most 50 | [{ status, body }] in one transaction. A failure rolls back all: 400 Batch transaction failed. with data.requests.<i> |
perPage defaults to 30 and stops at 1000.sort: a comma list of fields, - for descending, @random, @rowid.expand: a comma list of relation fields, one level deep. The target's viewRule applies.fields: a comma list, *, or expand.x.y paths.- A record carries
collectionId and collectionName. Hidden fields show to superusers only. email shows to its owner, to a superuser, or when emailVisibility is true. field+ and field- keys add and remove values on file, select, relation, and add and subtract on number.
Status codes of the rules#
| case | status |
|---|
the action's rule is null, the caller is not a superuser | 403 Only superusers can perform this action. |
| list, a record fails the rule | left out of the page |
| view, update, delete, the record fails the rule | 404 |
| create, the new record fails the rule | 400 Failed to create record. |
| a field fails validation | 400 with data.<field> |
| a unique index is violated | 400, validation_not_unique on its fields |
Auth#
All under /api/collections/:c/ for an auth collection :c.
| route | body | answer |
|---|
POST auth-with-password | { identity, password, identityField? }, mfaId in the query or the body | { token, record }, or 401 { mfaId } when a second factor is due |
POST request-otp | { email } | { otpId }, also for an unknown email |
POST auth-with-otp | { otpId, password, mfaId? } (the code is password) | { token, record }, or 401 { mfaId } |
POST auth-refresh | the auth header of that collection | { token, record } |
POST request-password-reset | { email } | 204, also for an unknown email. One mail per 2 minutes |
POST confirm-password-reset | { token, password, passwordConfirm } | 204; every token of the record dies |
POST request-email-change | { newEmail }, signed in to :c | 204; mails a link to the new address |
POST confirm-email-change | { token, password } | 204; sets email and verified, every token of the record dies |
- Superusers sign in on
/api/collections/_superusers/auth-with-password. - Sign ins are limited to 5 per 3 s per client IP: 429
Too Many Requests. Code attempts: 5 per 180 s per account. authRule failing after the factors: 403.
Files#
| route | answer |
|---|
POST /api/files/token | { token }, valid 180 s. Any signed in caller |
GET /api/files/:c/:id/:filename | the bytes, under a sandboxing CSP. ?token= for a protected field, ?download=1 for an attachment |
Collections#
Superuser only. Read only: schema.ts owns the collections.
| route | answer |
|---|
GET /api/collections | a page of collections; page perPage sort filter skipTotal over id created updated name system type |
GET /api/collections/:c | one collection in PocketBase's JSON: rules, fields, indexes, its auth options flat (every token secret blank), its viewQuery |
Backups#
Superuser only.
| route | body | answer |
|---|
GET /api/backups | | [{ key, size, modified }] |
POST /api/backups | { name? }, ^[a-z0-9_-]+\.zip$, unique | 204 |
POST /api/backups/upload | multipart file, a zip, streamed, no size limit | 204 |
GET /api/backups/:key | ?token= a superuser's file token | the zip as an attachment |
DELETE /api/backups/:key | | 204; 400 while that backup is being made or restored |
POST /api/backups/:key/restore | | 204, then the restore and a restart |
A second backup or restore while one runs: 400 Try again later - another backup/restore process has already been started.
App system routes#
| route | body | answer |
|---|
GET /api/_/changelog | since (optional) | { version, seen, releases }. Signed in |
POST /api/_/seen | { version? } | { version, seen }. Signed in |
GET /api/_/logo | | the logo of loco.config.ts |
POST /api/_/users/copy-in | { collection?, records: [{ email, passwordHash, name?, role?, verified?, disabled? }] } | { created, updated, items }. Superuser only: upserts accounts by email with their bcrypt hash, used to copy users from one copy of an app to another |
MCP and OAuth#
Only with createApp({ mcp }). The details: MCP protocol and OAuth.
| route | what |
|---|
POST /mcp | one JSON-RPC 2.0 message, Authorization: Bearer. GET and DELETE answer 405 |
GET /.well-known/oauth-protected-resource[/mcp] | RFC 9728 metadata |
GET /.well-known/oauth-authorization-server | RFC 8414 metadata |
POST /oauth/register | RFC 7591 dynamic client registration |
GET /oauth/authorize, POST /oauth/authorize | the consent page and its decision |
POST /oauth/token | the code and refresh grants, PKCE S256 |
Body limits#
| route | limit |
|---|
| every route | 32 MB |
| record create and update | 32 MB plus each file field's maxSize (5 MB when unset) times its maxSelect |
/api/batch | 128 MB |
| backup upload | none |
Over the limit: 413 Request entity too large, before the handler runs. A custom route sets its own with bodyLimit(bytes).
Custom routes#
An app adds its own routes with app.route(method, path, handler, ...middlewares). They answer whatever the handler returns. See Server: hooks, routes, crons.
This page as markdown