Errors
The Airclou API uses standard HTTP status codes to indicate the success or failure of requests. Error responses include detailed information to help you debug issues.
HTTP status codes
The API returns the following status code ranges:
| Status Code | Description |
|---|---|
| 2xx | Success — Request completed successfully |
| 4xx | Client Error — Invalid request or insufficient permissions |
| 5xx | Server Error — Something went wrong on our end |
Common status codes
200 OK
Request succeeded. The response body contains the requested data.
201 Created
Resource was successfully created. The response body contains the new resource.
204 No Content
Request succeeded but there’s no content to return (e.g., DELETE requests).
400 Bad Request
The request was malformed or contains invalid parameters.
401 Unauthorized
Authentication failed. Check your API key.
403 Forbidden
You don’t have permission to access this resource.
404 Not Found
The requested resource doesn’t exist.
429 Too Many Requests
You’ve exceeded your rate limit. Wait before making more requests.
500 Internal Server Error
Something went wrong on our servers. Try again later.
503 Service Unavailable
The API is temporarily unavailable. Check our status page.
Error response format
All error responses follow this structure:
{
"error": {
"code": "validation_error",
"message": "Invalid email address format",
"details": "The email field must be a valid email address",
"field": "email",
"request_id": "req_1234567890"
}
}
Error object properties
- code — Machine-readable error code for programmatic handling
- message — Human-readable error description
- details — Additional context about the error (optional)
- field — The field that caused the error (for validation errors)
- request_id — Unique identifier for debugging (include in support requests)
Error codes
Here are the most common error codes you’ll encounter:
Authentication errors
| Code | HTTP Status | Description |
|---|---|---|
authentication_failed | 401 | Invalid or missing API key |
api_key_expired | 401 | API key has expired |
api_key_revoked | 401 | API key has been revoked |
insufficient_permissions | 403 | API key lacks required permissions |
Validation errors
| Code | HTTP Status | Description |
|---|---|---|
validation_error | 400 | Request validation failed |
missing_required_field | 400 | Required field is missing |
invalid_field_format | 400 | Field format is invalid |
field_too_long | 400 | Field exceeds maximum length |
Resource errors
| Code | HTTP Status | Description |
|---|---|---|
resource_not_found | 404 | Requested resource doesn’t exist |
resource_already_exists | 409 | Resource with same identifier exists |
resource_in_use | 409 | Cannot delete resource in use |
Rate limiting errors
| Code | HTTP Status | Description |
|---|---|---|
rate_limit_exceeded | 429 | Too many requests |
Server errors
| Code | HTTP Status | Description |
|---|---|---|
internal_error | 500 | Unexpected server error |
service_unavailable | 503 | Service temporarily unavailable |
Handling errors
Basic error handling
Here’s how to handle errors in different languages:
JavaScript/TypeScript:
try {
const response = await fetch('https://app.airclou.com/playbook/api/v1/users', {
headers: { 'Authorization': `Bearer ${apiKey}` }
});
if (!response.ok) {
const error = await response.json();
console.error(`Error ${response.status}:`, error.error.message);
// Handle specific error codes
if (error.error.code === 'rate_limit_exceeded') {
// Wait and retry
await new Promise(resolve => setTimeout(resolve, 60000));
return retryRequest();
}
throw new Error(error.error.message);
}
const data = await response.json();
return data;
} catch (err) {
console.error('Request failed:', err);
}
Python:
import requests
try:
response = requests.get(
'https://app.airclou.com/playbook/api/v1/users',
headers={'Authorization': f'Bearer {api_key}'}
)
response.raise_for_status()
data = response.json()
except requests.exceptions.HTTPError as err:
error = response.json()['error']
print(f"Error {response.status_code}: {error['message']}")
if error['code'] == 'rate_limit_exceeded':
# Handle rate limiting
time.sleep(60)
return retry_request()
except requests.exceptions.RequestException as err:
print(f"Request failed: {err}")
Retry logic
For transient errors (5xx status codes, network timeouts), implement exponential backoff:
async function fetchWithRetry(url, options, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
const response = await fetch(url, options);
// Don't retry client errors (4xx)
if (response.status >= 400 && response.status < 500) {
throw new Error(await response.text());
}
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
return await response.json();
} catch (error) {
const isLastRetry = i === maxRetries - 1;
if (isLastRetry) throw error;
// Exponential backoff: 1s, 2s, 4s
const delay = Math.pow(2, i) * 1000;
await new Promise(resolve => setTimeout(resolve, delay));
}
}
}
Rate limit headers
When you receive a 429 error, check these response headers:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1735824000
Retry-After: 60
- X-RateLimit-Limit — Your rate limit (requests per minute)
- X-RateLimit-Remaining — Requests remaining in current window
- X-RateLimit-Reset — Unix timestamp when limit resets
- Retry-After — Seconds to wait before retrying
Getting help
If you encounter persistent errors:
- Check the
request_idin the error response - Review our API status page
- Search our documentation and community forum
- Contact support@airclou.com with the request ID