Errors and Rate Limits
Most /api/v1 endpoints use a common JSON envelope.
Success envelope
{
"success": true,
"data": {},
"meta": {
"timestamp": "2026-07-11T20:00:00.000Z",
"request_id": "R8k2example"
}
}
Error envelope
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Validation failed",
"details": {
"session_id": ["Session ID is required"]
}
},
"meta": {
"timestamp": "2026-07-11T20:00:00.000Z",
"request_id": "R8k2example"
}
}
Standard codes
| HTTP | Code | Meaning | Action |
|---|---|---|---|
400 | VALIDATION_ERROR, BAD_REQUEST | JSON, query, or domain validation failed. | Fix the request; do not retry unchanged. |
401 | UNAUTHORIZED | Credential missing, invalid, expired, or not permitted for the public subject. | Refresh the ID token or replace/check the site key. |
403 | FORBIDDEN | Authenticated actor lacks ownership, role, or action permission. | Request access; do not retry unchanged. |
404 | NOT_FOUND | Resource does not exist in the authenticated scope. | Check the ID and workspace. |
409 | CONFLICT | Resource or lifecycle state conflicts with the requested operation. | Refresh state and decide whether to retry. |
429 | RATE_LIMIT_EXCEEDED | Key or merchant request budget is exhausted. | Wait until reset, then retry with jitter. |
500 | INTERNAL_ERROR | Server or dependency failure. | Retry idempotent requests with exponential backoff; escalate with request_id. |
Rate-limit headers
Rate-limited API-key endpoints can return:
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 742
X-RateLimit-Reset: 1783803600
The key record stores an hourly request limit. A newly created site key currently defaults to 1,000 requests per hour; plan, deployment, or key configuration can differ, so treat the response headers as authoritative.
For event batches, one request is rate-checked and the remaining allowance must also accommodate the number of events in that batch.
Retry policy
- Retry network failures,
429, and5xxonly. - Respect
X-RateLimit-Resetfor429. - Use exponential backoff with jitter and a maximum attempt count.
- Reuse a stable
client_event_idfor event retries. - Do not automatically retry non-idempotent management writes unless the endpoint documents an idempotency contract.
Partial success
POST /events/batch can return 207 with top-level success: true. Inspect data.failed and every data.results[] item. The browser SDK requeues failed event items.
Diagnostics to preserve
When escalating, include the path, method, UTC timestamp, HTTP status, response request_id, safe key prefix, and redacted error body. Never include the full API key or bearer token.