Error Handling
Error Response Format
When an error occurs, the API returns error information in the following format:
{ "error": "error_code", "error_description": "Detailed error description", "details": { "field": "Additional information (optional)" }}Field Description
| Field | Type | Description |
|---|---|---|
error | string | Error code (machine-readable) |
error_description | string | Error description (human-readable) |
details | object | Additional error details (optional) |
Errors by HTTP Status Code
400 Bad Request
When the request format is invalid:
{ "error": "invalid_request", "error_description": "Invalid JSON in request body"}401 Unauthorized
When authentication fails:
{ "error": "unauthorized", "error_description": "Authentication token is invalid or expired"}403 Forbidden
When permissions are insufficient:
{ "error": "forbidden", "error_description": "You do not have permission to perform this operation"}404 Not Found
When resource is not found:
{ "error": "not_found", "error_description": "The specified user was not found"}409 Conflict
When a resource conflict occurs:
{ "error": "conflict", "error_description": "This email address is already in use"}422 Unprocessable Entity
For validation errors:
{ "error": "validation_error", "error_description": "Invalid input data", "details": { "email": "Please enter a valid email address", "name": "Name is required" }}429 Too Many Requests
When rate limit is exceeded:
{ "error": "rate_limit_exceeded", "error_description": "Rate limit exceeded", "retry_after": 60}500 Internal Server Error
For server internal errors:
{ "error": "internal_error", "error_description": "An internal error occurred. Please try again later."}Error Code Reference
Authentication & Authorization Errors
| Error Code | HTTP Status | Description |
|---|---|---|
unauthorized | 401 | Invalid or missing authentication credentials |
token_expired | 401 | Token has expired |
token_revoked | 401 | Token has been revoked |
forbidden | 403 | Insufficient permissions |
insufficient_scope | 403 | Required scope is missing |
Resource Errors
| Error Code | HTTP Status | Description |
|---|---|---|
not_found | 404 | Resource not found |
user_not_found | 404 | User not found |
client_not_found | 404 | Client not found |
organization_not_found | 404 | Organization not found |
role_not_found | 404 | Role not found |
policy_not_found | 404 | Policy not found |
flow_not_found | 404 | Flow not found |
Validation Errors
| Error Code | HTTP Status | Description |
|---|---|---|
invalid_request | 400 | Invalid request format |
validation_error | 422 | Input data validation failed |
invalid_email | 422 | Invalid email address format |
invalid_password | 422 | Password does not meet requirements |
invalid_json | 400 | JSON parsing failed |
Conflict Errors
| Error Code | HTTP Status | Description |
|---|---|---|
conflict | 409 | Resource conflict |
email_already_exists | 409 | Email address is already in use |
client_id_already_exists | 409 | Client ID is already in use |
role_already_assigned | 409 | Role is already assigned |
State Errors
| Error Code | HTTP Status | Description |
|---|---|---|
user_suspended | 403 | User is suspended |
user_locked | 403 | User is locked |
client_disabled | 403 | Client is disabled |
flow_inactive | 400 | Flow is inactive |
Job Errors
| Error Code | HTTP Status | Description |
|---|---|---|
job_not_found | 404 | Job not found |
job_failed | 500 | Job execution failed |
job_cancelled | 400 | Job was cancelled |
import_failed | 422 | Import processing failed |
export_failed | 500 | Export processing failed |
System Errors
| Error Code | HTTP Status | Description |
|---|---|---|
internal_error | 500 | Internal server error |
service_unavailable | 503 | Service temporarily unavailable |
database_error | 500 | Database error |
timeout | 504 | Request timeout |
Error Handling Best Practices
Retry Strategy
For transient errors (5xx), we recommend retrying with exponential backoff:
async function fetchWithRetry(url, options, maxRetries = 3) { for (let i = 0; i < maxRetries; i++) { try { const response = await fetch(url, options);
if (response.status === 429) { // Rate limit: wait for retry_after const retryAfter = parseInt(response.headers.get('Retry-After') || '60'); await sleep(retryAfter * 1000); continue; }
if (response.status >= 500) { // Server error: exponential backoff await sleep(Math.pow(2, i) * 1000); continue; }
return response; } catch (error) { if (i === maxRetries - 1) throw error; await sleep(Math.pow(2, i) * 1000); } }}Error Logging
Log API errors appropriately:
try { const response = await adminApi.createUser(userData);} catch (error) { console.error('User creation error:', { error_code: error.error, description: error.error_description, details: error.details, request_id: error.request_id });}User Feedback
Display error messages in a user-friendly way:
function getErrorMessage(error) { switch (error.error) { case 'email_already_exists': return 'This email address is already registered.'; case 'validation_error': return Object.values(error.details).join('\n'); case 'rate_limit_exceeded': return 'Too many requests. Please wait a moment.'; default: return 'An error occurred. Please try again later.'; }}Debug Information
Request ID
All responses include an X-Request-ID header:
X-Request-ID: req_abc123xyzInclude this request ID when contacting support.
Debug Mode
In development environments, you can enable detailed error information:
curl -X POST "https://{tenant-domain}/api/admin/users" \ -H "Authorization: Bearer {token}" \ -H "X-Debug: true" \ -d '{...}'Response:
{ "error": "validation_error", "error_description": "Invalid input data", "details": { "email": "Please enter a valid email address" }, "debug": { "stack_trace": "...", "request_body": {...}, "timestamp": "2024-01-22T10:30:00Z" }}