On this page

Management API

The REST API behind the CLI: projects, settings, keys, SQL, types, migrations, branches, functions, members, the audit log, and every dashboard feature (backups, compute, replicas, flags, queues, cron, push, links, metering, monitors and more), with an access token.

Base URL https://stitchdb.com/platform/v1. Authenticate with an access token (Authorization: Bearer sdb_pat_…). Read-only tokens can read everything their projects allow and run read-only SQL; changes need a read-write token. Tokens limited to some projects only see those. Requests are limited to about 5 per second per token (bursts of 120); over it you get 429 with Retry-After.

Terminal
curl https://stitchdb.com/platform/v1/projects \
  -H "Authorization: Bearer $STITCHDB_TOKEN"

#Projects

Method and pathDoes
GET /projectsProjects you can access (yours and your organizations'), with your role
GET /projects/<ref>Status, region, API URL, anon key and connection details; the service role key and database password only for owners and admins with a read-write token
GET /projects/<ref>/api-keys[{ name, api_key }]
POST /projects, PATCH /projects/<ref>, DELETE /projects/<ref>Create, rename / label, delete a project; also /pause, /restore, /api-keys/rotate (see Provisioning)
GET /projects/<ref>/usageDaily usage (?from&to)
GET|PATCH /projects/<ref>/config/authAuth settings (sign-up, providers, URLs, e-mail)

#Project settings

Method and pathDoes
GET|PUT /projects/<ref>/network-restrictions{ allowlist: ["203.0.113.7", "198.51.100.0/24"] }: who may connect to Postgres from outside; null or [] allows every address (owners and admins)
GET|PUT /projects/<ref>/graphql{ enabled: true } turns on GraphQL at /graphql/v1; the answer has its url
GET|POST|DELETE /projects/<ref>/region-moveRegions it can move to, allowance and the current move; { region, when: "now" | "quiet" | ISO time } moves or schedules it (owners and admins); DELETE cancels a scheduled move. See Projects and regions
GET|DELETE /projects/<ref>/database/query-performanceSlowest and most frequent statements (?sort=total|mean|calls|rows|io&limit=50, database:read); DELETE resets the statistics. See Query performance
GET|PATCH /projects/<ref>/limitsPer-project caps below the plan (see Limits)

#Organization: members and audit log

These need a dashboard session or a personal access token (not an organization or project token), and the Administrator or Owner role. <org> is the organization id from GET /organizations.

Method and pathDoes
GET /organizations/<org>/members[{ user_id, email, role, project_refs, created_at, last_sign_in_at }] (every member can read it)
PATCH /organizations/<org>/members/<user_id>{ role?, project_refs? }: change a role (admin, developer, read_only) or limit to some projects
DELETE /organizations/<org>/members/<user_id>Remove a member
GET|POST /organizations/<org>/invitationsPending invitations; { email, role, project_refs? } sends one by e-mail
DELETE /organizations/<org>/invitations/<id>Revoke an invitation (the link stops working)
GET /organizations/<org>/audit-logThe audit log, newest first; filters ?action&actor&project&since&until, paging with ?before= the X-Next-Cursor header, ?format=csv to download

#Database

Method and pathDoes
POST /projects/<ref>/database/query{ query, read_only? } → { rows, results }. Runs as the project's database role; read-only tokens always run read-only.
GET /projects/<ref>/types/typescript?schemas=public{ types }: the TypeScript Database type
GET /projects/<ref>/types/dart|swift|kotlin?schemas=public{ types }: Dart, Swift or Kotlin models (&package= sets the Kotlin package)
GET /projects/<ref>/database/dumpSQL dump of your schemas (?schemas=, ?data_only=1 for rows, admins only)
Terminal
curl -X POST https://stitchdb.com/platform/v1/projects/<ref>/database/query \
  -H "Authorization: Bearer $STITCHDB_TOKEN" -H 'Content-Type: application/json' \
  -d '{"query":"select count(*) from public.todos","read_only":true}'

#Migrations

Method and pathDoes
GET /projects/<ref>/migrationsApplied migrations (?include_sql=1 for their SQL)
POST /projects/<ref>/migrations{ migrations: [{ version, name, sql }], dry_run? } → { applied, skipped, failed? }. In version order, one transaction each, stops at the first failure; 409 if an applied version has different SQL.
POST /projects/<ref>/migrations/repair{ version, status: "applied" | "reverted", name?, sql? }: fix the history without running SQL

#Branches, functions and secrets

See Preview branches and Deploy functions with the API.

#Dashboard features

Everything below runs the same code as the dashboard, under /projects/<ref>. The rules of the dashboard apply: your role in the project (some changes need Administrator or Owner), the plan, and turning a feature on before you use it. Read-only tokens can call the GET routes (and the ones marked changes nothing) and see what a Developer sees. Organization tokens need the scopes in the last column. Answers never contain stored keys or signing secrets. The same routes are in the management client and the CLI.

#Backups

Restores and point-in-time recovery need the Administrator or Owner role. Download links are signed and expire; they need a read-write token.

Method and pathDoesScopes
GET /projects/<ref>/backupsBackups of the project, the retention of the plan and the point-in-time windowprojects:read
POST /projects/<ref>/backupsStart a manual backup now (one per hour)projects:write
POST /projects/<ref>/backups/<id>/restoreRestore a backup (the current state is backed up first, so the restore can be undone)projects:write
POST /projects/<ref>/backups/exportA signed link that streams a fresh dump of the current dataprojects:write
GET /projects/<ref>/backups/<id>/downloadA signed download link of a backup (?files=1: its Storage files)projects:write
GET /projects/<ref>/backups/pitrPoint-in-time recovery: the window you can restore toprojects:read
POST /projects/<ref>/backups/pitrRestore to a point in time: { target_time, branch? }; with branch, into a new preview branch insteadprojects:write
GET /projects/<ref>/backups/jobsRestore and backup jobs with their progressprojects:read
GET /projects/<ref>/backups/jobs/<id>One restore or backup jobprojects:read
POST /projects/<ref>/backups/table-restoreRestore one table or some rows to a point in time: { schema, table, mode, where?, target_time }projects:write

#Compute

Changing the size and restarting need the Administrator or Owner role. A larger size is billed from the prepaid balance, like in the dashboard; POST /compute/estimate shows the price first.

Method and pathDoesScopes
GET /projects/<ref>/computeCompute: whether the plan allows a dedicated size, the current server, recent servers and the locationsprojects:read
GET /projects/<ref>/compute/catalogCompute sizes with their size_key and price (?location&kind=cloud|auction|large&need_gb)projects:read
POST /projects/<ref>/compute/estimateWhat a compute size costs: { size_key }; changes nothingprojects:read
POST /projects/<ref>/computeChange the compute size: { size_key, idempotency_key? }; billed from the prepaid balanceprojects:write
POST /projects/<ref>/restartRestart the project's Auth and REST servicesprojects:write

#Replicas

Adding replicas needs the Administrator or Owner role and is billed hourly from the prepaid balance.

Method and pathDoesScopes
GET /projects/<ref>/replicasRead replicas with their connection details, price and failover stateprojects:read
POST /projects/<ref>/replicasAdd a read replica (billed hourly from the prepaid balance)projects:write
DELETE /projects/<ref>/replicas/<node>Remove a read replicaprojects:write
GET /projects/<ref>/auto-replicasAutomatic read replicas: settings, running replicas and costprojects:read
PUT /projects/<ref>/auto-replicasChange the automatic read replica settingsprojects:write

#Budget

Reading the budget needs billing:read as well (organization tokens). Changes need the Administrator or Owner role. The account-wide spend cap stays in the dashboard.

Method and pathDoesScopes
GET /projects/<ref>/budgetBudget of the project: limits per resource, alerts and what stops at the limitprojects:read, billing:read
PUT /projects/<ref>/budgetSet the budgetprojects:write
DELETE /projects/<ref>/budgetRemove the budgetprojects:write
POST /projects/<ref>/budget/testSend a test budget alertprojects:write

#Export

The list holds download links of the whole database, so it needs a read-write token. Restoring an archive into a project needs the organization owner.

Method and pathDoesScopes
GET /projects/<ref>/exportFull exports and imports with their download / upload linksprojects:write
POST /projects/<ref>/exportStart a full export (database and files)projects:write
POST /projects/<ref>/export/importStart a full import: returns the upload link for an export archiveprojects:write
POST /projects/<ref>/export/import/<job>/restoreRestore an uploaded export archive into this project (organization owner)projects:write
DELETE /projects/<ref>/export/<job>Delete an export or importprojects:write

#Feature flags

Method and pathDoesScopes
GET /projects/<ref>/flagsFeature flags: state, flags, segmentsprojects:read
POST /projects/<ref>/flagsTurn feature flags onprojects:write
DELETE /projects/<ref>/flagsTurn feature flags offprojects:write
POST /projects/<ref>/flags/flagsCreate a flagprojects:write
PATCH /projects/<ref>/flags/flags/<key>Change a flag (rules, rollout, variants, enabled)projects:write
DELETE /projects/<ref>/flags/flags/<key>Delete a flagprojects:write
GET /projects/<ref>/flags/flags/<key>/statsHow often a flag was evaluated, per variantprojects:read
POST /projects/<ref>/flags/segmentsCreate a segmentprojects:write
PATCH /projects/<ref>/flags/segments/<key>Change a segmentprojects:write
DELETE /projects/<ref>/flags/segments/<key>Delete a segmentprojects:write
GET /projects/<ref>/flags/historyChange history of flags and segmentsprojects:read
POST /projects/<ref>/flags/history/<id>/restoreRestore a flag or segment from its history: { side?: "before" | "after" }projects:write
POST /projects/<ref>/flags/testEvaluate the flags for a test context (changes nothing)projects:read

#Rate limits

Method and pathDoesScopes
GET /projects/<ref>/rate-limitsRate limit rules and recent blocksprojects:read
PATCH /projects/<ref>/rate-limitsChange the rate limit rulesprojects:write
POST /projects/<ref>/rate-limits/sqlInstall the SQL rate-limit function in the databaseprojects:write
DELETE /projects/<ref>/rate-limits/sqlRemove the SQL rate-limit functionprojects:write

#Inbound webhooks

Signing secrets are write-only: you set them, but they are never returned.

Method and pathDoesScopes
GET /projects/<ref>/inboundInbound webhooks: state and endpointsprojects:read
POST /projects/<ref>/inboundTurn inbound webhooks onprojects:write
DELETE /projects/<ref>/inboundTurn inbound webhooks offprojects:write
POST /projects/<ref>/inbound/endpointsAdd an endpoint (provider, signing secret, target table)projects:write
PATCH /projects/<ref>/inbound/endpoints/<endpoint>Change an endpointprojects:write
DELETE /projects/<ref>/inbound/endpoints/<endpoint>Delete an endpoint (?events=1 also deletes its events)projects:write
POST /projects/<ref>/inbound/endpoints/<endpoint>/testSend a test event to an endpointprojects:write
GET /projects/<ref>/inbound/eventsReceived events (?endpoint&status&limit&before)projects:read
GET /projects/<ref>/inbound/events/<id>One event with its payloadprojects:read
POST /projects/<ref>/inbound/events/<id>/redeliverProcess an event againprojects:write
DELETE /projects/<ref>/inbound/events/<id>Delete an eventprojects:write

#Status page

Method and pathDoesScopes
GET /projects/<ref>/status-pageStatus page: state, settings, components and incidentsprojects:read
POST /projects/<ref>/status-pageTurn the status page onprojects:write
DELETE /projects/<ref>/status-pageTurn the status page offprojects:write
PUT /projects/<ref>/status-page/settingsChange the page (title, components, checks, notifications)projects:write
POST /projects/<ref>/status-page/incidentsPost an incident or scheduled maintenanceprojects:write
PATCH /projects/<ref>/status-page/incidents/<incident>Add an update to an incident or change itprojects:write
PATCH /projects/<ref>/status-page/incidents/<incident>/updates/<update>Edit an incident updateprojects:write
DELETE /projects/<ref>/status-page/incidents/<incident>Delete an incidentprojects:write
GET /projects/<ref>/status-page/subscribersE-mail subscribersprojects:write
DELETE /projects/<ref>/status-page/subscribers/<id>Remove a subscriberprojects:write

#Cron

Needs pg_cron in the project (409 otherwise).

Method and pathDoesScopes
GET /projects/<ref>/cron/jobsScheduled jobs (pg_cron)database:read
GET /projects/<ref>/cron/runsRecent runs (?jobid&limit)database:read
POST /projects/<ref>/cron/jobsSchedule a job: { jobname, schedule, command, active? }database:write
PATCH /projects/<ref>/cron/jobs/<id>Change a job (schedule, command, active)database:write
DELETE /projects/<ref>/cron/jobs/<id>Unschedule a jobdatabase:write

#Queues

Needs pgmq in the project (409 otherwise).

Method and pathDoesScopes
GET /projects/<ref>/queuesQueues (pgmq) with their length and agedatabase:read
POST /projects/<ref>/queuesCreate a queue: { name, unlogged? }database:write
DELETE /projects/<ref>/queues/<queue>Delete a queue and its messagesdatabase:write
GET /projects/<ref>/queues/<queue>/messagesMessages of a queue, newest 100 (?archived=true for the archive)database:read
POST /projects/<ref>/queues/<queue>/messagesSend a message: { message, delay? }database:write
POST /projects/<ref>/queues/<queue>/readRead messages (they stay invisible for vt seconds)database:write
POST /projects/<ref>/queues/<queue>/messages/<id>/<action>Archive or delete a messagedatabase:write

#Push notifications

Answers say which credentials are on file, never the keys themselves.

Method and pathDoesScopes
GET /projects/<ref>/pushPush notifications: credentials on file (never the keys), devices, recent messagesprojects:read
PATCH /projects/<ref>/pushSet the APNs (.p8) or FCM credentials: { ios: { p8, key_id, team_id, bundle_id, production } | null, android: { service_account } | null }projects:write
POST /projects/<ref>/push/testSend a test notification to a user: { user_id, title?, body? }projects:write
DELETE /projects/<ref>/pushTurn push notifications off and remove the credentialsprojects:write

#In-app purchases

Answers say which store credentials are on file, never the keys. Webhook signing secrets are only shown in the dashboard.

Method and pathDoesScopes
GET /projects/<ref>/purchasesIn-app purchases: store credentials on file (never the keys), products, webhooks, deliveriesprojects:read
PATCH /projects/<ref>/purchasesSet the App Store / Google Play credentials, products and webhooksprojects:write
POST /projects/<ref>/purchases/webhooks/<webhook>/testSend a test event to a purchase webhookprojects:write
POST /projects/<ref>/purchases/deliveries/<id>/retryDeliver a failed purchase webhook againprojects:write
DELETE /projects/<ref>/purchasesTurn in-app purchases off and remove the credentialsprojects:write
Method and pathDoesScopes
GET /projects/<ref>/linksDeep links and short links: state and settingsprojects:read
POST /projects/<ref>/linksTurn links onprojects:write
DELETE /projects/<ref>/linksTurn links offprojects:write
PUT /projects/<ref>/links/settingsChange the settings (apps, app stores, fallback, domain)projects:write
GET /projects/<ref>/links/itemsShort links (?q&limit&offset)projects:read
POST /projects/<ref>/links/itemsCreate a short linkprojects:write
GET /projects/<ref>/links/items/<code>One link with its click statistics (?days)projects:read
PATCH /projects/<ref>/links/items/<code>Change a linkprojects:write
DELETE /projects/<ref>/links/items/<code>Delete a linkprojects:write

#Metering

Method and pathDoesScopes
GET /projects/<ref>/meteringUsage metering: state, meters, alerts and the Stripe push (the Stripe key masked)projects:read, usage:read
POST /projects/<ref>/meteringTurn usage metering onprojects:write
DELETE /projects/<ref>/meteringTurn usage metering offprojects:write
PUT /projects/<ref>/metering/settingsChange meters, plans and alertsprojects:write
PUT /projects/<ref>/metering/stripeSet the Stripe push (secret key, meters)projects:write
GET /projects/<ref>/metering/stripe/customersEnd customers and their Stripe customer idsprojects:read, usage:read
PUT /projects/<ref>/metering/stripe/customersSet Stripe customer ids of end customersprojects:write
POST /projects/<ref>/metering/stripe/retryPush failed usage to Stripe againprojects:write
GET /projects/<ref>/metering/customersUsage per end customer (?from&to&meter&q&limit)projects:read, usage:read
GET /projects/<ref>/metering/customers/<customer>Daily usage of one end customerprojects:read, usage:read
GET /projects/<ref>/metering/exportUsage as CSV (?from&to&meter)projects:read, usage:read

#Job monitoring

Method and pathDoesScopes
GET /projects/<ref>/heartbeatJob monitoring: state, alert settings and monitorsprojects:read
POST /projects/<ref>/heartbeatTurn job monitoring onprojects:write
DELETE /projects/<ref>/heartbeatTurn job monitoring offprojects:write
PUT /projects/<ref>/heartbeat/settingsChange the alert settings (e-mail, webhook, Slack)projects:write
POST /projects/<ref>/heartbeat/monitorsAdd a monitor: { name, kind: "ping" | "cron" | "job", schedule | period_s, grace_s, target? }projects:write
GET /projects/<ref>/heartbeat/monitors/<monitor>One monitor with its recent pings (?limit)projects:read
PATCH /projects/<ref>/heartbeat/monitors/<monitor>Change a monitorprojects:write
DELETE /projects/<ref>/heartbeat/monitors/<monitor>Delete a monitorprojects:write
POST /projects/<ref>/heartbeat/monitors/<monitor>/tokenA new ping URL for a monitor (the old one stops working)projects:write
POST /projects/<ref>/heartbeat/testSend a test alertprojects:write

#Crash reporting

Method and pathDoesScopes
GET /projects/<ref>/crashesCrash reporting: state and alert settingsprojects:read
POST /projects/<ref>/crashesTurn crash reporting onprojects:write
DELETE /projects/<ref>/crashesTurn crash reporting offprojects:write
PUT /projects/<ref>/crashes/settingsChange the alert settings (new issue, regression, spike; e-mail, webhook, Slack)projects:write
POST /projects/<ref>/crashes/testSend a test alertprojects:write
GET /projects/<ref>/crashes/issuesIssues (?status&release&q&limit&offset)projects:read
GET /projects/<ref>/crashes/issues/<issue>One issue with its latest eventsprojects:read
PATCH /projects/<ref>/crashes/issues/<issue>Resolve, ignore or reopen an issue: { status: "open" | "resolved" | "ignored" }projects:write

#Auth

Also see GET|PATCH /config/auth above. SSO providers need the Administrator or Owner role and auth:write.

Method and pathDoesScopes
GET /projects/<ref>/config/auth/sso/providersSAML SSO providersauth:write
POST /projects/<ref>/config/auth/sso/providersAdd a SAML SSO provider: { metadata_url | metadata_xml, domains, attribute_mapping? }auth:write
PUT /projects/<ref>/config/auth/sso/providers/<uuid>Change a SAML SSO providerauth:write
DELETE /projects/<ref>/config/auth/sso/providers/<uuid>Remove a SAML SSO providerauth:write

#Recycle bin

Method and pathDoesScopes
GET /projects/<ref>/recycle-binDeleted rows kept by the recycle bin (?table&limit) and the tables it coversdatabase:read
PUT /projects/<ref>/recycle-bin/tablesTurn the recycle bin on or off for a table: { schema?, table, enabled }database:write
POST /projects/<ref>/recycle-bin/restoreRestore deleted rows: { ids }database:write
POST /projects/<ref>/recycle-bin/purgeDelete rows from the bin for good: { ids }database:write

#Change history

Method and pathDoesScopes
GET /projects/<ref>/historyRow changes (?table&pk&limit&before) and the tables that keep a historydatabase:read
PUT /projects/<ref>/history/tablesTurn the change history on or off for a table: { schema?, table, enabled }database:write
POST /projects/<ref>/history/revertRevert one change: { id }database:write

#Shared views

Method and pathDoesScopes
GET /projects/<ref>/shared-viewsShared table views (read-only links for people without dashboard access)projects:read
POST /projects/<ref>/shared-viewsCreate a shared view: { name, schema, table, columns, filters }projects:write
GET /projects/<ref>/shared-views/<view>One shared view with its membersprojects:read
PATCH /projects/<ref>/shared-views/<view>Change a shared viewprojects:write
DELETE /projects/<ref>/shared-views/<view>Delete a shared viewprojects:write
POST /projects/<ref>/shared-views/<view>/membersGive people access by e-mail: { emails }projects:write
DELETE /projects/<ref>/shared-views/<view>/membersRemove a person (?email)projects:write
GET /projects/<ref>/shared-views/<view>/auditWho opened the view and whenprojects:read

#Errors

Errors are JSON: { "error": "message" } with the HTTP status (400 invalid input or SQL error with code/detail/hint, 401 missing or invalid token, 403 not allowed, 404 not found or no access, 409 conflict, 429 rate limited).