Error Codes
All API errors follow a consistent format with an error code, message, and optional details.
{
"error": {
"code": "ERROR_CODE",
"message": "Human-readable description",
"details": {}
}
}
Authentication Errors
| Code |
HTTP Status |
Description |
UNAUTHORIZED |
401 |
No authentication provided or invalid credentials |
INVALID_API_KEY |
401 |
API key is invalid, expired, or deactivated |
ORG_REQUIRED |
403 |
Organization context required for this operation |
TENANT_REQUIRED |
403 |
API key is not scoped to a tenant |
TENANT_ACCESS_DENIED |
403 |
Selected or inferred tenant is not available for this organization |
FEATURE_NOT_ENTITLED |
403 |
Requested capability is not enabled for this organization |
API_KEY_NOT_ALLOWED |
403 |
Endpoint requires user authentication, not API key |
INSUFFICIENT_PERMISSIONS |
403 |
API key lacks required permission |
INSUFFICIENT_ACCESS_LEVEL |
403 |
User lacks required access level (owner/editor/viewer) |
Access Errors
| Code |
HTTP Status |
Description |
COURSE_ACCESS_DENIED |
403 |
Organization lacks access to this course |
RESOURCE_NOT_FOUND |
404 |
Course or topic not found |
Validation Errors
| Code |
HTTP Status |
Description |
INVALID_REQUEST |
400 |
Malformed request body or invalid JSON |
INVALID_PARAMETERS |
400 |
Invalid query or path parameters |
MISSING_FIELDS |
400 |
Required field missing from request |
UNKNOWN_PLAN |
400 |
Plan key does not exist or is inactive for the tenant |
INVALID_COURSES |
400 |
Plan contains course IDs unavailable to the tenant |
Plan-Based Provisioning Errors
| Code |
HTTP Status |
Description |
PLAN_EXISTS |
409 |
Plan key already exists for the tenant |
PLAN_NOT_FOUND |
404 |
Plan key not found for the tenant |
USER_ORG_CONFLICT |
409 |
Learner email already belongs to another organization |
LEARNER_NOT_FOUND |
404 |
The requested learner_id does not resolve in the API key's tenant |
Surface Embedding Errors
| Code |
HTTP Status |
Description |
EXTERNAL_IDENTITY_CONFLICT |
409 |
The requested learner ID or email is already associated with a different learner |
FEATURE_NOT_ENTITLED |
403 |
Surface embedding is not enabled for this organization |
INSUFFICIENT_PERMISSIONS |
403 |
API key is not authorized to create Surface embed links |
Server Errors
| Code |
HTTP Status |
Description |
INTERNAL_ERROR |
500 |
Unexpected server error |
SERVICE_UNAVAILABLE |
502 |
Downstream service unavailable |
HTTP Status Code Summary
| Status |
Meaning |
| 200 |
Success |
| 400 |
Bad request / validation error |
| 401 |
Authentication failed |
| 403 |
Permission denied |
| 404 |
Resource not found |
| 429 |
Rate limit exceeded |
| 500 |
Server error |
Handling Errors
import requests
response = requests.get(url, headers=headers)
if not response.ok:
error = response.json().get("error", {})
code = error.get("code")
message = error.get("message")
if code == "UNAUTHORIZED":
# Check API key is correct
pass
elif code == "INVALID_API_KEY":
# Ask your organization admin to rotate or revoke the key
pass
elif code == "COURSE_ACCESS_DENIED":
# Request access from admin
pass
elif code == "RESOURCE_NOT_FOUND":
# Handle missing resource
pass
elif code == "MISSING_FIELDS":
# Check required fields in request
pass