Authentication
When RB_REQUIRE_AUTH=true, every request carries an Authorization: Bearer <token> header. A JWT-authenticated client uses 24-hour JWTs from POST /auth/login; your server code uses API keys of the form rb_live_…. Both resolve to the same tenant.
API key lifecycle
Created with a JWT, revocable any time, raw value returned exactly once.
Create a key (JWT required):
curl -s -X POST http://localhost:8080/auth/keys \
-H "Authorization: Bearer $JWT" \
-H "Content-Type: application/json" \
-d '{"name":"Production server"}'Response (HTTP 201):
{
"id": "key_01H...",
"key": "rb_live_xyz789...",
"name": "Production server",
"created_at": "2026-05-14T12:34:56Z"
}The raw key field is returned once. Subsequent GET /auth/keys calls list metadata only (id, name, created_at, last_used_at, revoked_at).
Revoke a key:
curl -s -X DELETE http://localhost:8080/auth/keys/key_01H... \ -H "Authorization: Bearer $JWT"
Returns HTTP 204. The row is kept for audit; the key is marked revoked_at and rejected on all subsequent requests.
Authenticated request
Any endpoint accepts either a JWT or an API key on the same header.
curl -s http://localhost:8080/auth/me \ -H "Authorization: Bearer rb_live_xyz789..."
Error envelope
Every 4xx/5xx response uses the same shape.
{
"error": {
"code": "unauthorized",
"message": "Missing or invalid credentials"
}
}Common codes:
unauthorized— missing, invalid, or expired token (HTTP 401)invalid_credentials— login failed; same code for wrong password and unknown email (HTTP 401)rate_limited— per-key token bucket exhausted (HTTP 429)