Endpoint index
Every route the server mounts, in one table, with what it takes to reach it.
The paths assume the default basePath of /api; REBASE_BASE_PATH moves all
of them together. /health, /livez and /metrics sit outside it on purpose,
because an orchestrator probes /health and should not have to know the base
path. /health is also mounted under it, so /api/health answers the same
way rather than 404ing at the one moment someone is checking whether the server
is alive.
A gate — tooling/scripts/docs-verify/check-endpoint-index.mjs — compares this
table to the routes the source registers, so a new surface cannot be added
without appearing here.
| Gate | Means |
|---|---|
| none | Unauthenticated. Anyone who can reach the host can call it |
| session | A signed-in caller: an access token, or an API key scoped to the operation |
resource:action |
A caller holding that scope: an admin, a person whose role declares it, an API key created with it, or the service key |
| RLS | Authenticated, and then the database decides row by row — see Security Rules |
| dev | Mounted only outside production |
Generated per collection, so the paths carry your slugs rather than a fixed
list. :slug is a collection’s slug.
| Method | Path | Gate | More |
|---|---|---|---|
GET |
/api/data/collections |
session | REST API |
GET |
/api/data/:slug |
RLS | Querying |
POST |
/api/data/:slug |
RLS | REST API |
POST |
/api/data/:slug/query |
RLS | The listing, query parameters in the body — Queries too long for a URL |
GET |
/api/data/:slug/count |
RLS | Querying |
POST |
/api/data/:slug/count |
RLS | The count, query parameters in the body — Queries too long for a URL |
GET |
/api/data/:slug/aggregate |
RLS | REST API |
GET |
/api/data/:slug/:id |
RLS | REST API |
PATCH |
/api/data/:slug/:id |
RLS | REST API |
PUT |
/api/data/:slug/:id |
RLS | Deprecated alias of PATCH — same partial write, answers Deprecation: true |
DELETE |
/api/data/:slug/:id |
RLS | REST API |
POST |
/api/data/:slug/bulk |
RLS | Insert many rows, optionally upserting — REST API |
PATCH |
/api/data/:slug/bulk |
RLS | Update many rows by id — REST API |
POST |
/api/data/:slug/bulk/delete |
RLS | Delete many rows by id — REST API |
POST |
/api/data/_batch |
RLS | Write across collections in one transaction — Writing over REST |
GET |
/api/data/:slug/:id/history |
RLS | Entity History |
POST |
/api/data/:slug/:id/history/:historyId/revert |
RLS | Entity History |
Counting and aggregation are routes of their own, registered before /:id so
that aggregate is not read as an entity id. ?select= and ?groupBy= are
their parameters, and select is required on /aggregate.
Text search, vector search, relation inclusion and field selection are query
parameters on GET /api/data/:slug rather than routes — search,
vector_search, include, fields. See REST API.
A project that declares no collections and introspects none serves this prefix
as a single 404 NO_COLLECTIONS. See Backend only.
| Method | Path | Gate | More |
|---|---|---|---|
GET |
/api/auth/config |
none | What the login screen can offer: registration, password reset, magic link, email codes, guest sign-in, OAuth providers, and whether first-admin setup is pending |
POST |
/api/auth/register |
none | Authentication |
POST |
/api/auth/login |
none | Auth endpoints |
POST |
/api/auth/refresh |
none (a refresh token) | Auth endpoints |
POST |
/api/auth/logout |
session | Auth endpoints |
GET |
/api/auth/me |
session | Auth endpoints |
PATCH |
/api/auth/me |
session | Auth endpoints |
GET |
/api/auth/sessions |
session | Auth endpoints |
DELETE |
/api/auth/sessions |
session | Revokes every other session |
DELETE |
/api/auth/sessions/:id |
session | Revokes one |
POST |
/api/auth/forgot-password |
none | Authentication |
POST |
/api/auth/reset-password |
none (a reset token) | Authentication |
POST |
/api/auth/change-password |
session | Authentication |
POST |
/api/auth/send-verification |
session | Authentication |
GET |
/api/auth/verify-email |
none (a verification token) | Authentication |
POST |
/api/auth/verify-email |
none (a verification token, and a session or the password to keep it) | Email verification |
POST |
/api/auth/magic-link |
none | Authentication |
POST |
/api/auth/magic-link/verify |
none (a link token) | Authentication |
POST |
/api/auth/otp |
none | One-time codes by email |
POST |
/api/auth/otp/verify |
none (a code) | One-time codes by email |
POST |
/api/auth/anonymous |
none | Guest sessions. Off unless ALLOW_ANONYMOUS |
POST |
/api/auth/anonymous/link |
session (a guest) | Turns a guest into an account |
POST |
/api/auth/find-user |
session | Off unless AUTH_ALLOW_USER_LOOKUP — it is an enumeration surface |
POST |
/api/auth/:provider |
none | One per configured OAuth/OIDC provider |
POST |
/api/auth/link/:provider |
session | Links a provider to the signed-in account |
POST |
/api/auth/mfa/enroll |
session | MFA |
POST |
/api/auth/mfa/verify |
session | MFA |
GET |
/api/auth/mfa/factors |
session | MFA |
DELETE |
/api/auth/mfa/unenroll |
session | MFA |
POST |
/api/auth/mfa/recovery-codes |
session (aal2) |
MFA |
POST |
/api/auth/mfa/challenge |
none (a login in progress) | MFA |
POST |
/api/auth/mfa/challenge/verify |
none (a challenge id) | MFA |
GET |
/api/auth/scopes |
session | Every scope this backend knows, and the ones the caller holds — Roles and scopes |
GET |
/api/auth/keys |
session (an account) | The caller’s own personal keys |
POST |
/api/auth/keys |
session (an account) | The plaintext key is returned once. 403 PERSONAL_KEYS_DISABLED unless the users collection sets auth.personalKeys |
DELETE |
/api/auth/keys/:id |
session (an account) | Revokes one of the caller’s own keys |
GET |
/.well-known/jwks.json |
none | The public JWKS, when asymmetric signing is configured |
Everything under /api/admin needs a scope from the admin plane, and each
surface names its own: users:read lists accounts, cron:write triggers a job.
An admin holds all of them, and so does the service key. A person holds the ones
their roles declare, and an API key the ones it was created with. A key scoped to
a collection reaches none of this. See Roles and scopes.
| Method | Path | Gate | More |
|---|---|---|---|
POST |
/api/admin/bootstrap |
none, and only while no admin exists | Refused in production — see First User Bootstrap |
GET |
/api/admin/users |
users:read |
User management |
POST |
/api/admin/users |
users:write |
User management. Roles beyond the caller’s own are refused |
GET |
/api/admin/users/pick |
users:read, or write access to a collection with a userSelect field |
The user picker’s read: id, name, email and avatar only. A collection whose write rules are raw SQL does not count |
GET |
/api/admin/users/:uid |
users:read |
User management |
PUT |
/api/admin/users/:uid |
users:write |
Refused for an account that holds more than the caller |
DELETE |
/api/admin/users/:uid |
users:write |
Refused for an account that holds more than the caller |
POST |
/api/admin/users/:uid/reset-password |
users:write |
Issues a temporary password |
DELETE |
/api/admin/users/:uid/mfa |
users:write |
Removes the account’s second factors and recovery codes, ends its sessions |
GET |
/api/admin/roles |
users:read |
admin and the roles the project declares, with their scopes |
GET |
/api/admin/api-keys |
keys:read |
API keys. Never an API key |
POST |
/api/admin/api-keys |
keys:write |
The plaintext key is returned once, on creation |
GET |
/api/admin/api-keys/:id |
keys:read |
API keys |
PUT |
/api/admin/api-keys/:id |
keys:write |
API keys |
DELETE |
/api/admin/api-keys/:id |
keys:write |
API keys |
GET |
/api/admin/cron |
cron:read |
Cron Jobs |
GET |
/api/admin/cron/:id |
cron:read |
Cron Jobs |
PUT |
/api/admin/cron/:id |
cron:write |
Enable or disable a job |
GET |
/api/admin/cron/:id/logs |
cron:read |
Cron Jobs |
POST |
/api/admin/cron/:id/trigger |
cron:write |
Run a job now. Since 0.25 ?async=1 answers 202 once it has started — Cron Jobs API |
GET |
/api/admin/backups |
backups:read |
Backup inventory |
GET |
/api/admin/backups/download |
backups:read |
Streams one backup. With ?token= from a download link, no header is needed, for that backup only |
POST |
/api/admin/backups/download-url |
backups:read |
Since 0.25 A link to one backup, { key } → { url, token, expiresIn }, good for 60 seconds — Backups |
GET |
/api/admin/storage/orphans |
database:read |
Since 0.25 Stored files no row names, ?storageId=&olderThanHours= — what rebase storage orphans prints |
DELETE |
/api/admin/storage/orphans |
database:write |
Since 0.25 Finds them again and deletes them; 409 STORAGE_SCAN_INCOMPLETE when a collection could not be read |
POST |
/api/admin/storage/move |
database:write |
Since 0.25 Copies a folder to another source under the same keys, a page per call — what rebase storage move sends |
GET |
/api/admin/logs |
logs:read |
The recent log buffer |
GET |
/api/admin/logs/latest |
logs:read |
The most recent entries |
GET |
/api/admin/logs/stream |
logs:read |
Server-sent events |
GET |
/api/admin/rls-audit |
schema:read |
The scheduled audit’s latest result |
POST |
/api/admin/sql/csv |
database:write |
Since 0.25 Streams one read-only query’s whole result as CSV — Studio’s “Download full result as CSV” |
GET |
/api/admin/schema/status |
schema:read |
Live schema editing |
POST |
/api/admin/schema/plan |
schema:read |
Plans a change; never applies one |
POST |
/api/admin/schema/apply |
schema:write |
A person only, unless REBASE_LIVE_SCHEMA_ALLOW_MACHINE_APPLY |
GET |
/api/admin/schema-editor/status |
schema:read |
Whether the editor is available, and the reason when it is not |
POST |
/api/admin/schema-editor/collection/save |
schema:write |
Studio — rewrites collection source |
POST |
/api/admin/schema-editor/collection/delete |
schema:write |
Studio |
POST |
/api/admin/schema-editor/property/save |
schema:write |
Studio |
POST |
/api/admin/schema-editor/property/delete |
schema:write |
Studio |
GET |
/api/admin/dev/emails |
dev + users:write |
Mail the development transport captured instead of sending |
DELETE |
/api/admin/dev/emails |
dev + users:write |
Empties the captured mailbox |
/api/admin/cron, /api/admin/logs and /api/admin/schema-editor are also
served at their pre-0.17 paths without the /admin segment. Those aliases are
for projects that have not moved; write new code against the canonical path.
Storage
Section titled “Storage”| Method | Path | Gate | More |
|---|---|---|---|
POST |
/api/storage/upload |
session + storageAuthorize |
Storage |
GET |
/api/storage/file/* |
session + storageAuthorize |
Storage |
DELETE |
/api/storage/file/* |
session + storageAuthorize |
Storage |
GET |
/api/storage/metadata/* |
session + storageAuthorize |
Storage |
POST |
/api/storage/metadata |
session + storageAuthorize, per key |
Since 0.25 Storage: metadata for up to 100 objects |
GET |
/api/storage/list |
session + storageAuthorize |
Storage |
POST |
/api/storage/folder |
session + storageAuthorize |
Storage |
GET |
/api/storage/sources |
session | The named storage sources this backend serves |
OPTIONS |
/api/storage/tus |
none | Resumable uploads: the TUS versions and extensions this server supports |
POST |
/api/storage/tus |
session + storageAuthorize |
Resumable uploads: creation |
GET |
/api/storage/tus/:id |
the upload’s owner | Resumable uploads: offset |
PATCH |
/api/storage/tus/:id |
the upload’s owner | Resumable uploads: append |
DELETE |
/api/storage/tus/:id |
the upload’s owner | Resumable uploads: cancel |
A deployment with no storage configured serves this prefix as a 501 naming the
variable it needs, rather than 404ing as if the feature did not exist.
Functions
Section titled “Functions”| Method | Path | Gate | More |
|---|---|---|---|
| any | /api/functions/<name> |
whatever the function declares. An API key also needs functions:invoke |
Custom Functions |
One route per file under backend/functions/, so the paths come from your
project. GET /api/functions does not list them: an inventory of a
deployment’s custom endpoints is not public.
Meta and operations
Section titled “Meta and operations”| Method | Path | Gate | More |
|---|---|---|---|
GET |
/livez |
none | Liveness alone: is this process running. Does not touch the database, which is why it is the probe path a container should use — RUNTIME_LIVENESS_PATH |
GET |
/health, /api/health |
none | Liveness and readiness. Reports every configured data source, not only the default |
GET |
/api/docs |
none (schema:read in production) |
The OpenAPI 3.0 document |
GET |
/api/swagger |
none | Swagger UI. Development only unless REBASE_ENABLE_SWAGGER |
GET |
/api/meta/schema-version |
none | The schema hash this backend was built from, and nothing else |
GET |
/api/meta/contract |
schema:read |
The full collection contract, for rebase generate-sdk --from. 404 when no auth is configured |
GET |
/metrics |
REBASE_METRICS_TOKEN when set |
Prometheus metrics, when REBASE_METRICS=true |
GET |
/metrics/history |
REBASE_METRICS_TOKEN when set |
The recorded series behind the Studio charts. 501 on a runtime with no backend |
WebSocket connections arrive as an HTTP upgrade on the same server rather than at a path of their own — see Realtime.
MCP surface
Section titled “MCP surface”Mounted only when REBASE_MCP_ENABLED=true, which also requires
REBASE_PUBLIC_URL — see
Configuration. Off by
default: no REBASE_ROLE turns this on, because it hands project access to
third-party software and that is a decision for a person to make.
The .well-known documents sit at the origin, not under basePath: RFC 8414
and RFC 9728 define those paths relative to the origin, and a client fetches them
before it holds any token.
| Method | Path | Gate | More |
|---|---|---|---|
GET |
/.well-known/oauth-protected-resource |
none | RFC 9728 metadata naming this resource and its authorization server. Served at the path-suffixed form as well |
GET |
/.well-known/oauth-authorization-server |
none | RFC 8414 metadata: the endpoints, grant types and PKCE methods this deployment supports |
POST |
/mcp |
OAuth bearer, or an API key | The MCP protocol endpoint. Acts as the signed-in user (or as whoever the key acts as), so every read and write is subject to the same RLS. The data:* scopes decide which tools are offered |
GET |
/mcp |
OAuth bearer, or an API key | Answers 405 with Allow: POST, DELETE: this server opens no server-initiated stream. The token is checked first, so a missing or stale one gets the 401 challenge instead |
DELETE |
/mcp |
none | Answers 204. The endpoint keeps no session, so there is nothing to end |
POST |
/api/oauth/register |
rate-limited | RFC 7591 dynamic client registration. Refused when REBASE_MCP_OPEN_REGISTRATION=false |
GET |
/api/oauth/authorize |
session | The consent screen a client is redirected to |
POST |
/api/oauth/authorize/decision |
session | The person’s answer to it — approve or deny |
POST |
/api/oauth/token |
client credentials + PKCE | Exchanges an authorization code, or refreshes |
POST |
/api/oauth/revoke |
client credentials | RFC 7009 token revocation |
GET |
/api/oauth/grants |
session | Which clients this user has approved |
DELETE |
/api/oauth/grants/:clientId |
session | Withdraws one, so a person can undo a consent without an admin |
Related
Section titled “Related”- REST API — the data routes in full: filters, sorting, pagination, errors
- Auth endpoints — request and response shapes for the auth table above
- Environment & Configuration — the variables that decide which of these are mounted