Skip to main content
The control plane is a JSON HTTP API. Everything the frontend and the CLI do goes through it; the only non-HTTP surface is the daemon WebSocket, documented in Daemon protocol.
The endpoint pages in this tab are generated from a seed OpenAPI specification that currently covers auth, identity, keys, host listing, and grants. The remaining control-plane endpoints — credentials, sets, groups, backup jobs, users, invitations, notifications, and audit — are being transcribed.

Authentication

Send an opaque access token as a bearer header:
Get one from POST /login. Both token types are opaque and checked against the database on every request, which makes revocation immediate — the tradeoff Custos takes deliberately for a secrets vault with low request volume. expires_in is a duration, not a timestamp — add it to your own clock rather than parsing a server time.
POST /refresh returns a new refresh token alongside the new access token, and invalidates the one you sent. A client that stores only the access token from a refresh response will fail on its next refresh.

Roles

Every caller is either an admin or a member. Admins bypass grant resolution. Members act through grants — see Permissions. Endpoints self-gate on the relevant permission rather than on role, so most of the API is usable by members with the right grants.

Payload encryption

CUSTOS_ENCRYPTION on the control plane decides whether bodies are sealed. If it is off, send and read plain JSON and there is nothing to implement. If it is on, request and response bodies are sealed with a hybrid X25519 scheme on top of TLS, and your client has to match — see Encrypted transport for the full contract. Either way, the bodies on these pages describe the plaintext shapes, before any sealing.
The interactive playground sends plain JSON, so it only works against a control plane started with CUSTOS_ENCRYPTION=off — the usual local development setting. Turning it off disables neither HTTPS/TLS nor at-rest vault encryption.

Rate limits

Unauthenticated endpoints — login, refresh, enroll, invitation acceptance, and password reset — are rate-limited per IP at roughly 10 requests per minute. Login additionally throttles per account: 5 failures within 15 minutes locks that account for 15 minutes, clearing on window expiry or a successful login. Both return 429. The per-account window is deliberately not a hard lockout, which would turn the endpoint into a targeted denial-of-service tool.

Errors

Failures return the appropriate status code with a plain-text message body. 500 responses carry a generic message; the real cause is logged server-side with its trace and span id. Conventions worth knowing:
  • 403 means authenticated but not permitted — usually a missing grant.
  • 409 on enrollment means that machine already has an active host.
  • 503 means a dependency is unavailable; for secret endpoints, that the vault key wrapper is not configured.
  • Password reset always returns 204, whether or not the address exists, to avoid leaking which accounts are registered.

Health

GET /livez, GET /readyz, and GET /healthz need no authentication. See Install the control plane.