CapyDB Docs
ReferenceAPI

API overview

The CapyDB control plane is a plain HTTP API documented by an OpenAPI spec. Everything the dashboard and CLI do, you can do.

Base URL and spec

https://capydb.dev/api/capydb

All endpoints are under /v1. The OpenAPI document is public:

GET https://capydb.dev/api/capydb/v1/openapi.json

The per-tag pages in this section are generated from that document, so they cannot drift from the implementation. The TypeScript SDK is generated from the same spec.

Authentication & API keys

Programmatic callers authenticate with an API key, either as a bearer token or a header:

curl -H "Authorization: Bearer capy_live_..." https://capydb.dev/api/capydb/v1/projects
curl -H "X-API-Key: capy_live_..." https://capydb.dev/api/capydb/v1/projects

Keys belong to an organization and are created in the dashboard (Settings → API keys) or via POST /v1/organizations/{orgID}/api-keys. The plaintext is shown once; only a SHA-256 hash is stored. Keys can carry an expiry and are revocable without touching anything else.

Scopes

Each key carries explicit scopes: projects:read, projects:write, credentials:read, backups:read, backups:write, jobs:read, organizations:read, organizations:write, api_keys:read, api_keys:write. Grant what the consumer needs, nothing else.

Project-scoped keys

A key created with a project_id is restricted to that single project:

  • it can only act on that project (and its previews, backups, jobs)
  • it cannot touch sibling projects
  • org-management scopes (organizations:write, api_keys:write, ...) are rejected on it

Use project-scoped keys for CI and integrations — the GitHub Action, deploy scripts, anything whose blast radius should be one project. A leaked project-scoped key is an incident; a leaked org key is a worse one.

Human sessions

Browser and CLI sessions are Clerk-authenticated; the active Clerk organization resolves which org you act in. Some actions are gated to the Clerk org admin role when called with a session: project create/delete, overwrite-restores, and API-key create/revoke.

Asynchronous jobs

Lifecycle actions (provision, backup, restore, import, preview create/reset/delete, credential rotation, deletion) return 202 Accepted with a job object instead of blocking. Poll GET /v1/jobs/{jobID} until completed or failed:

curl -s -H "X-API-Key: $CAPYDB_API_KEY" \
  https://capydb.dev/api/capydb/v1/jobs/job_... | jq '.job.state'

Or subscribe to webhooks (job.completed, job.failed, and the higher-level *.ready/*.completed events) instead of polling.

Conventions

  • List endpoints always return JSON arrays — never null.
  • Errors are {"error": "message"} with an appropriate 4xx/5xx status.
  • Rate limiting is applied per IP (with a stricter bucket on the CLI-login endpoints). Back off on 429.

Quick tour

# Who am I?
curl -s -H "X-API-Key: $KEY" $BASE/v1/me

# Create a clone preview and wait for it
JOB=$(curl -s -X POST -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
  -d '{"name":"pr-42","mode":"clone","ttl_hours":72}' \
  $BASE/v1/projects/$PROJECT/preview-databases | jq -r '.job.id')

curl -s -H "X-API-Key: $KEY" $BASE/v1/jobs/$JOB | jq '.job.state'

# Fetch its connection strings once ready
curl -s -H "X-API-Key: $KEY" $BASE/v1/preview-databases/$PREVIEW/connections