How errors are returned
The Integrations API does not use a universalerror_code field, and it does not return a request_id. 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.
- Domain error
- Validation error (422)
- Rate limit (429)
Most domain errors return a Authentication failures (401) use this shape, with messages such as
detail message. Some also include an optional docs_url.Missing X-API-Key header, Invalid API key, This API key has expired, or This API key has been revoked.HTTP status codes
| Code | Meaning | Retryable? |
|---|---|---|
| 200 | OK | No |
| 201 | Created (submission, direct upload, webhook subscription) | No |
| 202 | Accepted (asset retry) | No |
| 204 | No content (delete subscription) | No |
| 400 | Bad request (e.g. simulationDelaySeconds on a live key) | No |
| 401 | Missing, invalid, expired, or revoked API key | No |
| 402 | Tier not authorized for the Integrations API | No |
| 403 | Sandbox-only endpoint with a live key; invalid blob path | No |
| 404 | Resource not found in your workspace | No |
| 409 | Asset already submitted; asset not retryable | No |
| 413 | Upload too large | No |
| 415 | Unsupported or mismatched content type | No |
| 422 | Request validation failed | No |
| 429 | Rate limit exceeded (includes Retry-After) | Yes (with backoff) |
| 500 | Storage error or internal failure | Yes (with backoff) |
| 502 | Failed to load an issue or topic blob from storage | Yes (with backoff) |
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.
401 Invalid API key
Missing or invalid API key, returned as a domain error.X-API-Key header is present and correct, and that the key has not expired or been revoked.
403 Invalid blob path
A blob path failed validation, or a sandbox-only endpoint was called with a live key.404 Not found
A submission or asset does not exist in your workspace, or topics/issues were requested before the asset finished processing.409 Asset already submitted
The same asset was already submitted, or a retry is not allowed./api/integrations/submissions/{submission_id}/versions for existing versions, or upload a new file.
413 Upload too large
The file exceeds the direct-upload limit. Use the presigned upload URL flow instead.415 Unsupported content type
The content type is not in the allowlist, or it does not match the file.422 Validation error
The request body failed validation. Read thefields array — see the validation envelope above.
402 Tier not authorized
Your plan does not include Integrations API access — see the 402 envelope above.429 Rate limit exceeded
A rate-limit bucket was exceeded. Wait for theRetry-After header — see the 429 envelope above.
Retry strategies
Retry only on 429, 500, and 502. Use exponential backoff with jitter, and respect theRetry-After header on 429 responses.
Exponential backoff with jitter
Retry-After header gives the number of seconds to wait. See Rate limiting for the bucket model.
A note on duplicate submissions
Submission creation is not idempotent, and the API does not support anIdempotency-Key header. If you retry a submission request whose response you did not receive, you may create a duplicate. Guard against this client-side — for example, only retry submission creation on a network error or a retryable status (429/500/502), and track which assets you have already submitted. A repeated submission of the same asset returns 409 (asset already submitted).
Validation before upload
Validate files client-side before uploading to fail fast. Maximum sizes are per category (video up to 5 GB, audio 500 MB, image 50 MB, document 100 MB); the 10 MB cap applies only to the direct-upload endpoint. The example below enforces per-category limits.Logging errors
Log the status code and thedetail (or validation fields) for context. Do not log error_code or request_id — neither exists on most responses.
Handling specific asset errors
Per-asset failures are reported byGET /api/integrations/submissions/{submission_id} (there is no /status suffix). Each asset carries flat camelCase failure fields: errorMessage, errorType, isRetryable, and retryCount. There is no nested error object. An asset is failed when its status is failed; terminal asset states are complete and failed.
isRetryable is true, you can re-run the asset with POST /api/integrations/submissions/{submission_id}/assets/{asset_id}/retry.