API Authentication
All API requests must carry a valid bearer token. BitVault uses OAuth 2.1 with PKCE (ADR-0010) for interactive flows and scoped API tokens for programmatic access.
Bearer Token
Authorization: Bearer <access_token>
Every API endpoint validates the token on every request: signature, expiry
(exp), audience (aud), issuer (iss), and tenant claim. Validated tokens
are cached in Redis for the hot path (configurable TTL, default 30 s) to avoid
repeated JWKS fetches under load.
:::warning Token lifetime Access tokens are short-lived (default: 15 minutes). Use the refresh token endpoint to obtain a new access token before expiry. API tokens have configurable expiry and should be rotated on a schedule appropriate to their privilege level. :::
OAuth 2.1 Interactive Flow
For web and mobile clients:
- Authorization Code + PKCE: client generates
code_verifier+code_challenge. - Redirect to authorization endpoint with
response_type=code&code_challenge=.... - User authenticates; authorization server redirects back with
code. - Exchange
code+code_verifierfor access token + refresh token. - Refresh token rotation: every token refresh issues a new refresh token; the old one is invalidated. Replay of a rotated refresh token revokes the entire session.
API Tokens
Long-lived, scoped tokens for CLI and automation use. Created via:
POST /v1/api-tokens
| Property | Description |
|---|---|
| Scope | One or more permission scopes (e.g. files:read, files:write, admin) |
| Expiry | Configurable; required (no indefinite tokens) |
| Name | Human-readable label for auditing |
API tokens are passed as Authorization: Bearer <api_token>. They resolve to
the owning user’s identity and tenant at validation time.
Example Request
curl -H "Authorization: Bearer $TOKEN" \
https://api.bitvault.example/v1/files
Rate Limit Headers
Every response includes rate-limit headers:
| Header | Value |
|---|---|
X-RateLimit-Limit |
Maximum requests allowed in the current window |
X-RateLimit-Remaining |
Requests remaining in the current window |
X-RateLimit-Reset |
Unix timestamp when the window resets |
Rate limits are enforced per-token (or per-IP for unauthenticated endpoints) and
stored in Redis. A 429 Too Many Requests response is returned when the limit
is exceeded; the Retry-After header indicates how long to wait.
Token Validation Summary
| Check | Enforcement |
|---|---|
| Signature | JWKS from issuer; cached |
exp |
Must be in the future |
aud |
Must match the configured API audience |
iss |
Must match the configured issuer |
tenant claim |
Must match the resource’s tenant (enforced at RLS layer) |
| Token revocation | Redis blocklist for explicitly revoked tokens |