Errors and rate limits
How the Coassemble API signals failures, the status codes you should plan for, and the request rate the API will accept per IP.
Error envelope
Failed requests respond with a JSON body containing a human-readable message and a structured error object. The error object carries a stable code and the HTTP status.
{
"message": "Course not found",
"error": {
"code": "NOT_FOUND",
"status": 404
}
} Prefer error.code for application logic and the HTTP status for transport-level handling.
Common status codes
| Status | Code | Meaning |
|---|---|---|
400 | BAD_REQUEST | Your request body, query, or path was invalid — for example a missing required field, an unknown enum value, or an unparseable date. |
401 | UNAUTHORIZED | The Authorization header was missing, malformed, or did not match a valid User ID + API key pair. |
403 | FORBIDDEN | Your plan does not include the entitlement required by this endpoint (e.g. authoring, analytics, advanced, or SCORM). See Get Started. |
404 | NOT_FOUND | The resource ID does not exist, or does not belong to your workspace. |
429 | TOO_MANY_REQUESTS | You have exceeded the per-IP rate limit. See below. |
500 | INTERNAL_SERVER_ERROR | Something went wrong on our side. Retry idempotent requests with exponential backoff. |
Rate limits
The API enforces a per-IP rate limit on a rolling 1-minute window. Most endpoints share a budget of 100 requests per minute.
When you exceed the budget, the API responds with 429 Too Many Requests and a Retry-After header set to the number of seconds until the window resets:
HTTP/1.1 429 Too Many Requests
Retry-After: 23
Content-Type: application/json
{
"message": "Too many requests",
"error": {
"code": "TOO_MANY_REQUESTS",
"status": 429
}
} Respect Retry-After rather than retrying immediately. X-RateLimit-* headers are not currently emitted.