Documentation navigation

Authentication

Every non-public endpoint takes a bearer credential:

Authorization: Bearer vamo_sk_...

Keys and sessions are one model

An API key represents an agent. A session represents a person. Both travel in the same header and are screened the same way, so anything a person can do in the app, a key can be granted. Keys are minted, listed, and revoked through the Keys endpoints.

A key is scoped to exactly one account. It cannot be widened after minting beyond what the minting principal itself holds.

Scoping a key

A key carries a set of entitlements, each an explicit resource:verb action such as search:read. You can only grant a key entitlements you hold yourself and that your plan includes, so a key is always a narrowing of its creator.

Give an integration the narrowest set that works. If a key is leaked, the blast radius is what you granted it.

What each refusal means

  • 401 no credential, or it is invalid or expired.
  • 403 the credential is valid, but its role lacks the entitlement this endpoint requires.
  • 402 the credential and role are fine, but the plan lacks the capability or the balance is short.

The distinction matters: a 403 is fixed by re-minting a key with the right entitlement, a 402 is fixed by upgrading or topping up.

Call GET /v1/me to see the principal the API resolved for your credential, and GET /v1/quotas for its allowances. Start there when a call is refused and you do not know why.

Signed requests

A key can additionally sign requests using HTTP Message Signatures (RFC 9421) with an Ed25519 key registered when the key is minted. A key can be configured to require signatures, in which case an unsigned request from that key is refused with signature_required.

Signing is optional and per key. If you do not register a public key, bearer authentication is unchanged.

POST /v1/keys/signature-check verifies the signature on the request you send to it and echoes a structured verdict: which signer matched, which components were covered, whether the body digest is valid, and whether the created and expires window is acceptable. Use it to debug a signing implementation without guessing.