Errors
Errors and rate limits
Every error response uses the same JSON envelope so clients can branch on a stable code instead of parsing free-form messages.
Error envelope
Errors always return application/json with HTTP status and a stable code. Localize the human-facing message yourself; never branch on it.
{
"error": {
"code": "rate_limited",
"message": "Too many requests",
"details": { "retry_after": 12 }
}
}Common codes
These are the codes you are most likely to see in production.
| Status | Code | Description |
|---|---|---|
| 401 | unauthorized | Missing or invalid Authorization header. |
| 403 | forbidden | Authenticated but not allowed for this resource. |
| 404 | not_found | Resource does not exist or has been deleted. |
| 422 | invalid_request | Body failed validation. Inspect the details field. |
| 429 | rate_limited | Too many requests. Wait and retry. |
| 500 | internal_error | Unexpected server error. Safe to retry with backoff. |
Rate limits
/v1/serve and /v1/track are aggressively rate-limited per SDK key and per client IP. Authenticated endpoints are limited per session. When you exceed a limit we return 429 with Retry-After in seconds.