How errors are returned
The Integrations API does not use a universalerror_code field, and it does not return a request_id. Instead, errors are signalled by the HTTP status code and one of four response body shapes. Always branch on response.status_code first, then read the body shape that matches.
Error envelope shapes
- Domain error
- Validation error (422)
- Rate limit (429)
Most domain errors return a The
detail message. Some also include a docs_url pointing at the relevant documentation.docs_url field is optional. Authentication failures (401) use this shape with messages such as Missing X-API-Key header, Invalid API key, This API key has expired, or This API key has been revoked.Status codes
| Code | When |
|---|---|
| 200 | OK |
| 201 | Created (submission, direct upload, webhook subscription) |
| 202 | Accepted (asset retry) |
| 204 | No content (delete subscription) |
| 400 | simulationDelaySeconds sent on a live key; subscription missing a delivery destination |
| 401 | Missing, invalid, expired, or revoked API key |
| 402 | Tier not authorized for the Integrations API (plan gating) |
| 403 | Sandbox-only endpoint called with a live key; invalid blob path |
| 404 | Resource not found in your workspace; asset not finished (topics or issues still pending) |
| 409 | Asset already submitted; asset not retryable; retry already in progress |
| 413 | Upload too large |
| 415 | Unsupported or mismatched content type |
| 422 | Request validation failed |
| 429 | Rate limit exceeded (includes Retry-After) |
| 500 | Storage error or internal failure |
| 502 | Failed to load an issue or topic blob from storage |
Common situations
These are real conditions you will encounter, described by status code and the style ofdetail message returned. There are no error-code constants to match against.
| Status | Situation | Example message |
|---|---|---|
| 401 | Missing or bad API key | Invalid API key |
| 402 | Plan does not include API access | see the 402 envelope above |
| 403 | Invalid blob path, or sandbox-only endpoint hit with a live key | Invalid blob path |
| 404 | Submission or asset not found in your workspace; topics/issues requested before the asset finished | Submission not found |
| 409 | Asset already submitted, or a retry is not allowed | Asset already submitted |
| 413 | File exceeds the direct-upload limit | File too large; use the presigned upload URL |
| 415 | Content type not in the allowlist or does not match the file | Unsupported content type |
| 422 | Request body failed validation | see the validation envelope above |
| 429 | A rate-limit bucket was exceeded | Rate limit exceeded: ... |
| 500 | Storage write or internal error | Internal server error |
| 502 | Issue or topic blob could not be loaded | Failed to load results from storage |
Retry guidance
| Status | Retryable? | How |
|---|---|---|
| 429 | Yes | Wait for the Retry-After header, then retry with backoff |
| 500 | Yes | Retry with exponential backoff and jitter |
| 502 | Yes | Retry with exponential backoff and jitter |
| Other 4xx | No | Fix the request; retrying will not help |
Handling errors in code
Branch on the status code, then read the matching body shape. Readdetail for domain errors and the fields array for validation errors. Do not look for error_code (except on 402) or request_id (which does not exist).
Retry-After header before retrying. See Rate limiting for a complete backoff example.
Need help?
- Note the HTTP status code and the
detailorfieldsmessage - Review the Error handling guide
- Contact support at https://support.mediamagic.app with the status code and message