Authentication & limits
Every request carries an API key. Keys are scoped, bound to allowed origins, rate limited, hashed at rest, and rotated without downtime.
Sending the key
Use a Bearer token or the x-api-key header; both are equivalent.
Authorization: Bearer rrk_live_xxxxxxxx_...
# or
x-api-key: rrk_live_xxxxxxxx_...Keys are stored as SHA-256 hashes and shown exactly once on creation or rotation. Rotation creates a new active key and keeps the previous one valid in a rotating state until you revoke it, so deployments never race against key changes.
Scopes
A request that needs a missing scope fails with 403 scope_missing and names the scope in error.details.missingScope.
Allowed origins
Browser requests send an Origin header; if the key has an origin allowlist and the origin is not on it, the request fails with 403 origin_not_allowed. Server to server calls without an Origin header are unaffected. For website integrations prefer the proxy pattern from the widget guide so keys stay on your server entirely.
Rate limits
Each key has a per-minute limit (default 120). Above it the API answers 429 rate_limit_exceeded with a Retry-After header in seconds.
HTTP/1.1 429 Too Many Requests
Retry-After: 21
{ "error": { "code": "rate_limit_exceeded", "message": "Too many requests for this API key." } }Idempotency
Send an Idempotency-Key header on reservation creation. Replays with the same key and body return the original reservation; the same key with a different body fails with 409 idempotency_conflict. Records expire after 24 hours.
Error format
Every error is JSON with a stable machine-readable code.
{
"error": {
"code": "no_tables_available",
"message": "No matching table or table combination is available.",
"details": { }
}
}