Error Codes
Allure Connect API errors use a flat JSON envelope:
{
"error": "Human-readable message",
"code": "STABLE_MACHINE_CODE"
}
Validation failures may also include details. The interactive
OpenAPI reference is the endpoint-level source of truth; this page
lists common cross-cutting and core delivery errors rather than inventing an
exhaustive global enum.
Authentication and Access
| HTTP | Code | Meaning |
|---|---|---|
| 401 | API_KEY_REQUIRED |
Missing, invalid, revoked, wrong-mode, or disallowed-scope API key |
| 402 | PAYMENT_REQUIRED |
The operation requires a paid plan |
| 403 | TENANT_MISMATCH |
A request named a tenant outside the authenticated key |
| 403 | DISPATCH_ORIGIN_REQUIRED |
A domain-restricted dispatch did not include usable origin context |
| 403 | DISPATCH_ORIGIN_NOT_ALLOWED |
The launch origin is outside the dispatch allowlist |
Use Authorization: Bearer <api_key> or X-API-Key: <api_key> on partner
routes. Bearer wins when both are supplied. Customer dashboard routes under
/api/customer/* require the signed-in Clerk browser session.
Request Validation
| HTTP | Code | Meaning |
|---|---|---|
| 400 | INVALID_JSON |
The request body is not valid JSON |
| 400/422 | INVALID_REQUEST |
The request does not match the endpoint schema |
| 400 | INVALID_BODY |
The body cannot be parsed for that endpoint |
| 400 | INVALID_PAGINATION |
A pagination value is invalid |
| 400 | INVALID_SESSION_ID |
A session identifier is not a UUID |
| 400 | INVALID_LIMIT |
The requested limit is outside the supported range |
| 400 | INVALID_STATEMENT |
An xAPI statement fails validation |
| 413 | STATEMENT_TOO_LARGE |
An xAPI statement exceeds the payload limit |
Packages, Sessions, and Dispatches
| HTTP | Code | Meaning |
|---|---|---|
| 404 | PACKAGE_NOT_FOUND |
The package does not exist in the authenticated workspace |
| 404 | SESSION_NOT_FOUND |
The session does not exist |
| 404 | UPLOAD_NOT_FOUND |
The multipart upload cannot be found |
| 404 | DISPATCH_POSTBACK_NOT_FOUND |
The dispatch has no postback delivery to retry |
| 409 | VERSION_CONFLICT |
A session update used a stale version |
| 409 | DISPATCH_POSTBACK_NOT_RETRYABLE |
The postback is not in a retryable state |
| 429 | RATE_LIMIT_EXCEEDED |
An operation-specific limit was reached |
| 502 | PRESIGN_FAILED |
Connect could not mint the upload URL |
| 502 | ARCHIVE_UPLOAD_FAILED |
Direct archive upload failed |
| 502 | MULTIPART_INIT_FAILED |
Multipart upload initialization failed |
| 502 | MULTIPART_COMPLETE_FAILED |
Multipart completion failed |
| 502 | MULTIPART_ABORT_FAILED |
Multipart abort failed |
Dispatch launch token failures may return INVALID_DISPATCH_TOKEN or
EXPIRED_DISPATCH_TOKEN. A protected dispatch can also return the specific
password error supplied by the launch service. Always display the error
message and branch programmatically on code.
Webhooks and xAPI
| HTTP | Code | Meaning |
|---|---|---|
| 404 | STATEMENT_NOT_FOUND |
The xAPI statement does not exist |
| 400 | INVALID_PAGE |
The xAPI offset/page input is invalid |
| 400 | INVALID_STATEMENT |
One or more xAPI statements are invalid |
Webhook endpoint creation uses INVALID_JSON and INVALID_REQUEST for invalid
payloads. Delivery history and manual retry are dashboard operations, not
separate public webhook-delivery endpoints.
Platform Failures
| HTTP | Code | Meaning |
|---|---|---|
| 503 | RATE_LIMIT_UNAVAILABLE |
A required durable rate-limit backend is unavailable |
| 503 | BACKEND_UNAVAILABLE |
A transient backend operation failed; retry when advised |
| 500 | INTERNAL_ERROR |
An unexpected non-transient failure occurred |
BACKEND_UNAVAILABLE responses may include Retry-After. Rate-limited routes
use X-RateLimit-*; see Rate Limiting.
Handling Pattern
const response = await fetch(url, init);
const payload = await response.json().catch(() => null);
if (!response.ok) {
const code = payload?.code ?? 'UNKNOWN_ERROR';
if (response.status === 503 && payload?.retryable === true) {
const retryAfterSeconds = Number(response.headers.get('Retry-After'));
scheduleRetry(Number.isFinite(retryAfterSeconds) && retryAfterSeconds >= 0
? retryAfterSeconds
: 5);
}
throw new Error(`${code}: ${payload?.error ?? response.statusText}`);
}