Skip to content

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.

{
"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.

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 /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 /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 404 rather than someone else’s data.