Using the HTTP API
How to call the HTTP API — the bearer token every route needs, the vault each request reaches, the shape of an authentication failure, and how to confirm which principal a token is.
Custodian exposes an HTTP API under /v1, and an agent-facing endpoint at /mcp.
This page covers what is true of every call: the credential each one carries, the
vault it reaches, and the response a request that cannot be authenticated gets. Each
route has its own page under this section.
The values your machine seals
These pages describe the HTTP wire format: the exact requests each route accepts and
the responses it returns. Some requests carry bytes your own machine must produce
first — a field value sealed on your device, a record's wrapped key, a blind index to
search by, a recovery blob. This reference shows where each of these belongs in a
request, written as <base64>; it does not restate how to produce them.
Those bytes are produced on an enrolled device: a machine that holds a device key
and, through it, a wrapped copy of the vault's master key. The custodian command
line produces them, and so does any client that implements the same
formats. If you have not enrolled a device yet, start from the
command line.
Every request carries a bearer token
Every /v1 route, and /mcp, authenticates the caller from an Authorization
header carrying a principal token:
Authorization: Bearer <token>A principal is one identity in one vault — an operator, a service or an
agent. A token is minted once, when the principal is created, and is the only
thing that authenticates as it. You get a vault's first token from
bootstrapping the vault; an operator mints the rest from
/v1/principals.
The one route that does not carry a principal token is POST /v1/vaults, which
creates a vault before any principal for it exists; it authenticates against the
deployment bootstrap credential instead. See Vaults.
Each request reaches one vault, fixed by the credential
A request is scoped to the vault its principal belongs to, and to no other. You never name a vault in a request — the vault is taken from the credential, never from a parameter, a header or a path segment. A record, principal or grant in another vault is invisible: a request for it comes back as though it did not exist, so one tenant cannot tell whether another exists.
An agent principal reaches its vault only through /mcp.
Every /v1 route refuses an agent with the agent_forbidden_on_v1 code before it
does any work.
When a request cannot be authenticated
A request whose token is missing, unknown, unverifiable or belongs to a revoked principal is refused with one fixed response, and no work is done — no transaction is opened and nothing is read or written:
{
"code": "unauthenticated",
"message": "The request could not be authenticated."
}The message is the same for every one of those reasons, by design: the response
does not disclose which of them applied. The full shape every refusal takes, and
the closed set of code values, is on the Errors page.
When the vault is rotating or its keys are destroyed
Two vault states cut across every route. While a vault is
rotating its master key, and after its
keys are destroyed, any /v1 route may refuse the request
with a coded error envelope and a 409 Conflict — rather than the unexplained error
it returned before these states were made legible.
While a rotation is running:
{
"code": "vault_rotation_in_progress",
"message": "This vault is rotating its master key, and refuses this request until that rotation ends.",
"details": { "started_at": "2026-08-28T10:00:00Z" }
}After the vault's keys are destroyed:
{
"code": "vault_keys_destroyed",
"message": "This vault's keys have been destroyed, and it refuses this request.",
"details": { "destroyed_at": "2026-08-28T10:10:00Z" }
}Branch on the code: vault_rotation_in_progress clears once the rotation is
completed, suspended or discarded, so the request can be retried then;
vault_keys_destroyed is permanent. The rotation routes themselves are exempt from
the rotation refusal, so a rotation can still be read and carried forward while it
holds every other caller out.
GET /v1/whoami — which principal is this token?
GET /v1/whoami names the calling principal and its vault. It takes no parameters:
the answer is settled entirely by the credential presented. Use it to confirm which
principal a token is.
GET /v1/whoami
Authorization: Bearer <token>{
"principal": {
"slug": "liberty-agent",
"kind": "service",
"revoked": false
},
"vault": {
"id": 42,
"slug": "acme",
"display_name": "Acme Insurance",
"region": "af-south-1",
"created_at": "2026-08-12T09:00:00Z",
"keys_destroyed": false,
"recovery_configured": true
}
}The response carries the principal's slug, kind and revocation state, and the
vault's public fields. recovery_configured reports whether the vault holds a
recovery envelope; it never returns the envelope itself.
No grant, token, selector or key identifier is returned.