Skip to content

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/: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 — searchString, 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/change-email session Mails a confirmation link to the new address — Changing an email address
POST /api/auth/confirm-email-change none (a link token) Moves the account onto the new address — Changing an email address
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/guests users:read Guests, last seen longest ago first. ?lastSeenBefore= narrows them to what the delete below would take, and total counts them
DELETE /api/admin/guests users:write Deletes one batch of the guests last seen before ?lastSeenBefore=, which is required. Answers { deleted, skipped, remaining }. Repeat while remaining is not 0, with ?offset= set to how many have been skipped. Accounts cannot be reached
DELETE /api/admin/guests/:uid users:write Deletes one guest. An account is refused with NOT_ANONYMOUS
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. ?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 A link to one backup, { key } → { url, token, expiresIn }, good for 60 seconds — Backups
POST /api/admin/storage/orphans/scans database:write Starts a scan for the stored files no row names, ?storageId=&olderThanHours=, in the background. Answers 202 with the scan’s record: id, status (queued), and runner (worker when it is a storage.orphans job on the job queue, in-process when the server runs it itself). Its record is written into the source, under the reserved _rebase/maintenance/
GET /api/admin/storage/orphans/scans/:id database:read The scan’s record, ?storageId=. While it runs: progress (filesScanned, rowsScanned, collectionsScanned of collectionsTotal, unscanned). Once completed: result, the report the old GET /orphans answered. A run that stopped reporting for 10 minutes is answered as failed. 404 STORAGE_SCAN_NOT_FOUND when the source holds no such scan
DELETE /api/admin/storage/orphans?scan=:id database:write Deletes a completed scan’s orphans in the background, 202. Each one is checked against every row and history entry again, and asked for again right before it is deleted. The outcome is the scan record’s deletion. 409 with STORAGE_SCAN_NOT_COMPLETE, STORAGE_SCAN_INCOMPLETE, STORAGE_SCAN_EXPIRED or STORAGE_SCAN_DELETION_STARTED
GET /api/admin/storage/orphans database:read Deprecated: the scan inside the request, ?storageId=&olderThanHours=. Answers with Deprecation: true. Use POST /orphans/scans
DELETE /api/admin/storage/orphans database:write Deprecated, without ?scan=: scans again and deletes inside the request. 409 STORAGE_SCAN_INCOMPLETE when a collection could not be read
POST /api/admin/storage/move database:write Copies a folder to another source under the same keys, a page per call — what rebase storage move sends; 400 STORAGE_SAME_LOCATION for deleteSource between two sources that store in the same place
POST /api/admin/storage/move/verify database:write Lists the source again after a move, with the same body, a page per call: { checked, notMoved: [{ key, reason }], cursor? } — every file still in the source with deleteSource, every file the target has no copy of without it. rebase storage move asks it when the move is done
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
GET /api/admin/rls-simulator/options schema:read Roles, users’ rule roles and live service keys an administrator can simulate
POST /api/admin/rls-simulator/preview schema:read Each collection as { role?, userId?, apiKeyId? } reaches it: visible rows against the caller’s, hidden by scope or RLS, masked fields. Administrator’s session only
POST /api/admin/sql/csv database:write Streams one read-only query’s whole result as CSV — Studio’s “Download full result as CSV”
GET /api/admin/branches/:name/diff database:write What a branch changed: schema, policies and rows, ?sampleLimit=&schemas=&maxRowsPerTable=
POST /api/admin/branches/:name/merge database:write Writes the branch’s rows to its parent, { expectedFingerprint, onConflict?, skipBlocked? }; 409 when either side changed since the diff, or rows conflict
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.

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 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 — except GET /api/storage/sources, which answers 200 with an empty list.

Method Path Gate More
GET /api/functions session The names of the functions served, and how many files failed to load
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 lists them only to a signed-in caller — a session, an API key or the service key — and answers anyone else 401: an inventory of a deployment’s custom endpoints is not public.

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 when enableSwagger is false, the runtime’s default in production) The OpenAPI 3.0 document
GET /api/swagger none Swagger UI. Outside production only; REBASE_ENABLE_SWAGGER cannot turn it on in production. Not served when enableSwagger is false, in development either
GET /api/meta/schema-version none The schema hash this backend was built from and the runtime version, 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.

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