Skip to documentation content

Errors and rate limits

Error codes, HTTP statuses, rate-limit tiers, and retry guidance for the CookieBeam REST API.

Error envelope

Errors use the same envelope as successful responses. The data object carries a human-readable error message and, for most API-key and consent-subject failures, a machine-readable code:

{
  "data": {
    "error": "API key is missing required scope(s): banners:write",
    "code": "missing_scope"
  },
  "version": "v1"
}

Validation errors add a details array describing each invalid field.

Error codes

Authentication and scope failures (see Authentication):

HTTP statusCodeMeaning
400invalid_requestThe request body failed validation (consent subject endpoints)
401invalid_keyThe API key is malformed, unknown, or has the wrong environment prefix
401revoked_keyThe API key has been revoked
401expired_keyThe API key has expired
401unauthorizedThe endpoint requires an API key and none was sent
403plan_requiredThe team's plan does not include the required feature
403missing_scopeThe key lacks a required scope; the message names the missing scopes
403test_key_read_onlyA test key was used for a write or publish operation
404not_foundThe referenced banner or consent subject was not found
409version_conflictA consent state write carried a stale baseVersion; the response includes the current snapshot
413invalid_requestThe request body exceeded 20 KB (consent subject endpoints)
429rate_limitedA rate limit was exhausted; see below
500internal_errorUnexpected server error
503identity_unavailableConsent identity hashing is temporarily unavailable; retry later

Rate limits for API keys

API-key requests are limited per key over a fixed 15-minute window. The limit depends on the team's plan:

PlanRequests per 15 minutes
Free50
Starter200
Professional500
Business2,000
Enterprise5,000

A plan the server cannot map to a tier falls back to the Free limit.

Responses that pass key authentication and reach the rate limiter carry three headers:

  • X-RateLimit-Limit — the key's limit for the window.
  • X-RateLimit-Remaining — requests left in the current window.
  • X-RateLimit-Reset — when the window resets, as a Unix timestamp in milliseconds.

This includes HTTP 429 rejections. It does not include requests rejected before rate limiting runs — entitlement, scope, and test-key failures (and malformed, revoked, or expired keys) return without these headers — and some server-error paths also skip them. Treat the headers as present on rate-limiter outcomes, not as a universal invariant.

When the limit is exhausted the API returns HTTP 429:

{
  "data": {
    "error": "Rate limit exceeded",
    "code": "rate_limited"
  },
  "version": "v1"
}

The response includes a Retry-After header with the number of seconds to wait before the next request.

Other rate limits

Two limits apply independently of API keys:

  • Requests to the banner endpoints that arrive without an API key (dashboard sessions and other browser traffic) are limited to 100 requests per 15 minutes per client IP.
  • POST /api/consent/log (the unversioned banner ingestion route) is limited to 1,000 requests per minute per client IP.
  • Failed authentication attempts are limited to 10 per minute per client IP; beyond that, further attempts return HTTP 429 with rate_limited and a Retry-After header.

Retry guidance

  • On HTTP 429, wait at least the number of seconds in Retry-After before retrying. Do not retry in a tight loop — repeated bursts just consume the next window.
  • On HTTP 5xx, retry with exponential backoff.
  • Reads (GET and the consent resolve endpoint) are safe to retry as-is.
  • For consent state writes, retry a 409 version_conflict by re-reading the subject, merging against the returned current snapshot, and writing again with the new version as baseVersion.