Skip to content

Branches API

Base URL and authentication are described in the API overview. In the tables, “Action” is the permission name checked for the call.

{
"name": "feature-x",
"id": "alice/feature-x",
"owner": "alice@example.com",
"access": "private",
"status": "ready",
"status_reason": null,
"base": "prod",
"snapshot": "s20261109",
"runtime": "postgres@18.6",
"node": "node1",
"created_at": "2026-11-09T12:00:00Z",
"expires_at": "2026-11-12T12:00:00Z",
"reset_at": null,
"storage": { "used": 1048576, "referenced": 83886080 },
"connection": { "host": "node1", "port": 41203, "user": "feature-x" },
"proxy": { "host": "node1", "port": 6133, "user": "feature-x" },
"operation": null
}
Field Meaning
status provisioning, ready, resetting, deleting, failed, or lost (its node is gone; see recreate)
status_reason Why a branch is failed or lost, otherwise null
id owner/name when the branch has an owner (an email owner is shortened to its local part), otherwise the name
access private (own password; owner and admins) or open (the cluster’s shared password; anyone may connect)
snapshot The snapshot of the base the branch was cloned from
expires_at When the branch is deleted automatically; null for no expiry
storage Bytes written by the branch (used) and bytes it can read (referenced), or null if unknown
connection Direct connection: the node’s host, the branch’s own port and its user (the database name is not included; use /dsn)
proxy Connection through the node’s proxy by user name, or null when the node has no proxy
operation The operation running on the branch now (id, kind), or null

Action branch.read. Lists all branches, sorted by name.

{ "items": [ { "name": "feature-x", "status": "ready", "...": "..." } ], "next_cursor": null }

Action branch.create. Clones a base into a new branch. Answers 202 with an operation of kind branch.create.

Field Type Meaning
name string, required Branch name
base string, required Base to clone
snapshot string Snapshot to clone. Default: the base’s latest
ttl string Lifetime, such as 72h. Default: the cluster’s Default TTL setting, or no expiry
init_sql string SQL to run once after cloning. A reset returns to this state
node string Node to place the branch on. Default: chosen by load, among nodes that hold the snapshot
owner string Who manages the branch. Default: the caller. Only an admin may name someone else
access string private (default) or open

Errors: 404 not_found (no such base), 409 already_exists, 503 no_capacity. Open branches and the shared password are set in Settings.

Callers without a login can create a branch only from a snapshot marked public. Such a branch is always open, its TTL is capped at the Anonymous branch TTL, and only a limited number may exist (Settings: Anonymous branches).

Action branch.read. Returns one branch.

Action branch.extend. Sets the expiry to now plus ttl. Answers 200 with the branch.

{ "ttl": "24h" }

Action branch.delete. Answers 202 with an operation of kind branch.delete. A branch can be deleted when it is ready, failed or lost. Deleting a lost branch is recorded and finished when its node returns.

Action branch.reset. Discards every change and returns the branch to its state right after creation (after init_sql). Answers 202, operation kind branch.reset. The branch must be ready; otherwise 409 conflict.

Action branch.recreate. Builds a lost branch again on a node that holds its snapshot. Answers 202, operation kind branch.recreate. Optional query parameter node picks the node; without it one is chosen. Data written to the branch after it was created is gone.

Action branch.connect. Returns the connection URL, including the password. Each call is written to the audit log.

{ "dsn": "postgres://feature-x:s3cret@node1:41203/postgres" }

With ?via=proxy the URL points at the node’s proxy port instead. If the node has no proxy, or the branch has no user of its own yet, the answer is 409 not_routable.

Action branch.query. Runs one SQL statement on a ready branch as the branch’s own user.

Field Type Meaning
sql string, required One statement
max_rows number Rows to return, at most 1000 (the default)
{
"columns": ["id", "email"],
"rows": [["1", "user1@example.invalid"], ["2", null]],
"truncated": false,
"millis": 4
}

Values are strings, and SQL NULL is null. A statement without rows returns affected (the number of rows changed) instead of columns and rows. A failing statement returns 422 query_failed. A branch that is not ready returns 409 conflict.

An admin (or a full token) can use every branch. Other callers can read all branches but change, connect to and query only their own. The exception is an open branch, which anyone may connect to and query. A paid module can also let teammates share branches. Other callers get 403 forbidden.