Databases
All four endpoints require the org:admin scope, which deliberately does not include the ability to read
the data inside these databases. See Authentication.
The database record
Section titled “The database record”{ "id": "db_01a00b50-f7d7-74e8-be44-877297734dec", "name": "production", "status": "active", "createdAt": "2026-08-16T09:14:02.118Z", "deletedAt": null}| Field | Type | |
|---|---|---|
id |
string | db_ followed by a UUIDv7. Immutable, never reused, and not derived from the name. |
name |
string | Yours, for your benefit. Not unique and not used for lookups. |
status |
"active" | "suspended" | "deleted" |
suspended answers 403; deleted answers 404. |
createdAt |
RFC 3339 string | |
deletedAt |
RFC 3339 string or null |
The id is a random UUIDv7 rather than anything derived from your name or a per-organization counter. A sequential id would let anyone holding one guess the next, and a name-derived id would make an object key depend on a customer-supplied string.
Create
Section titled “Create”POST /v1/databases{ "name": "production" }name is required, 1–128 characters after trimming. Characters are deliberately unrestricted — the name
is metadata and never reaches an object key or a filesystem path — so emoji and spaces are fine.
201 Created:
{ "database": { "id": "db_01a00b50-…", "name": "production", "status": "active", "createdAt": "2026-08-16T09:14:02.118Z", "deletedAt": null }}Names are not unique. Creating two databases called production gives you two databases, both called
production, with different ids. If you want uniqueness, enforce it on your side.
The database exists immediately but no worker has opened it yet; the first query pays a moment of setup.
| Error | |
|---|---|
400 bad-request |
name missing, not a string, empty, or over 128 characters. |
403 forbidden |
The key lacks org:admin. |
409 conflict |
Concurrent modification of your organization. Retry. |
GET /v1/databases{ "databases": [ { "id": "db_01a00b50-…", "name": "production", "status": "active", "createdAt": "…", "deletedAt": null }, { "id": "db_01a00b51-…", "name": "staging", "status": "active", "createdAt": "…", "deletedAt": null } ]}Deleted databases are not listed. There is no pagination — an organization’s databases are one record, and if you have enough of them for that to matter, tell us.
A key pinned to a single database sees only that database here, so the list always matches what the key can actually use.
Get one
Section titled “Get one”GET /v1/databases/{id}{ "database": { "id": "db_01a00b50-…", "name": "production", "status": "active", "createdAt": "…", "deletedAt": null }}404 for an id that does not exist, was deleted, belongs to another organization, or is simply malformed.
All four are indistinguishable on purpose — see 404 versus 403.
Delete
Section titled “Delete”DELETE /v1/databases/{id}{ "database": { "id": "db_01a00b50-…", "name": "production", "status": "deleted", "createdAt": "…", "deletedAt": "2026-08-16T11:02:44.901Z" }}The database stops answering immediately: every subsequent request to it is a 404.
Two things it does not do, and both matter:
- It does not free storage. The stored objects remain, because nothing in this system deletes an object. Reclaiming them needs a compactor that does not exist yet.
- It does not free the id. The record survives as a tombstone so the id can never be reused, which is
what makes a stale client’s request a clean
404rather than someone else’s data.