Skip to main content
Base URL: https://api.grantiva.io

Rate limiting

Two layers of rate limiting apply:
  • Per-IP — DoS protection on the challenge and validate endpoints. Applied before the tenant limit.
  • Per-tenant — a Redis sliding 60-second window, scoped per organization and endpoint bucket, with limits set by your plan tier.

Headers

Rate-limited endpoints attach these headers to every response: A 429 body looks like:

Per-tier limits

Requests per minute, per organization, by endpoint bucket: Flag limits are 4x attestation limits to accommodate SDK polling. API key limits are lower than SDK limits because calls originate from a server, not individual devices.
Rate limiting fails open: if the limiter backend is unavailable, requests are allowed through. Treat limits as a ceiling, not a guarantee of throttling behavior.

402 vs 429

These are different signals — don’t handle them the same way: The 402 body includes the details you need:

Request IDs

Every response carries an X-Request-ID header. If you send X-Request-ID on the request, your value is echoed back; otherwise the server generates a UUID. The same ID appears as requestId in error bodies and in server logs — include it in support requests.

Deployment version

Every response carries an X-Grantiva-Commit header with the deployed commit SHA. Useful for verifying which version you’re talking to.

Error envelope

API errors return a JSON envelope with a stable machine-readable code, a developer-readable message in error, and (where useful) a hint:
Attestation endpoints use domain-specific codes (see validate errors). Generic failures map to codes derived from the HTTP status: bad_request, unauthorized, forbidden, not_found, conflict, unprocessable_entity, rate_limited, internal_error.