Every error response carries the same envelope:
{
"success": false,
"error": {
"code": "INVALID_API_KEY",
"message": "The provided API key is invalid or has been revoked.",
"status": 401
}
}
Match on error.code programmatically — error.message is for humans
and may change between releases.
Authentication errors
| Code | Status | Meaning | Fix |
|---|---|---|---|
API_KEY_REQUIRED | 401 | No x-ansdev-key header | Add the header to the request |
INVALID_API_KEY | 401 | Key not found in our store | Check for typos; revoke and rotate if leaked |
API_KEY_EXPIRED | 401 | Key passed its expiresAt | Create a new key |
INSUFFICIENT_SCOPE | 403 | Key lacks the required scope | Recreate the key with the right scope |
Rate limiting
| Code | Status | Meaning |
|---|---|---|
RATE_LIMIT_EXCEEDED | 429 | Daily quota hit for this key |
Example payload:
{
"success": false,
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Daily playback-token quota exceeded.",
"status": 429,
"retryAfter": 14400
}
}
retryAfter is seconds until the next reset (also exposed as the
Retry-After header).
Resource errors
| Code | Status | Meaning | Fix |
|---|---|---|---|
VIDEO_NOT_FOUND | 404 | Unknown videoId, or not owned by this key | Verify ID; confirm key holder owns it |
PLAYBACK_TOKEN_EXPIRED | 401 | Token older than 5 minutes | Generate a fresh token server-side |
PLAYBACK_TOKEN_INVALID | 401 | Token signature or videoId mismatch | Don't reuse tokens across videos |
Request errors
| Code | Status | Meaning |
|---|---|---|
BAD_REQUEST | 400 | Body failed schema validation |
UNSUPPORTED_MEDIA_TYPE | 415 | Missing or wrong Content-Type |
PAYLOAD_TOO_LARGE | 413 | Body exceeded the per-route limit |
Example validation error:
{
"success": false,
"error": {
"code": "BAD_REQUEST",
"message": "body/name must be a non-empty string",
"status": 400
}
}
Server errors
| Code | Status | Meaning | What to do |
|---|---|---|---|
INTERNAL_ERROR | 500 | Unexpected failure | Retry with exponential backoff; report if persistent |
SERVICE_UNAVAILABLE | 503 | Upstream service cold start or scaling | Retry after a short delay |
BAD_GATEWAY | 502 | Edge → origin failure | Retry; if frequent, check status page |
💡 Retry logic
Retry idempotent requests (GET, DELETE, PATCH) on 5xx and
429. Never auto-retry POST requests that create resources — wait for
operator confirmation or use an idempotency key in your request body.
Troubleshooting checklist
- Is the header spelled right?
x-ansdev-key(lowercase, hyphens). - Is the key revoked? Check Dashboard → API Keys — revoked keys show as inactive.
- Does the key have the scope? A
video:readkey cannot access endpoints that require higher scopes. - Are you using the right base URL?
https://api.ansdev.cloud/v1, notapi.ansdev.cloud(no/v1) — older docs showed the bare host. - CORS errors in browser? Generate playback tokens server-side and pass the short-lived token to the Player SDK.