Error Handling
All error responses use a consistent format:
{
"error": {
"code": "validation_error",
"message": "project_id is required",
"field": "project_id"
}
}
HTTP Status Codes
| Code | Meaning | Common Cause |
|---|---|---|
| 400 | Bad Request | Missing required field, invalid value |
| 401 | Unauthorized | Missing or invalid API key |
| 403 | Forbidden | User not assigned to project |
| 404 | Not Found | Resource doesn’t exist |
| 409 | Conflict | Duplicate entry (if idempotency used) |
| 422 | Unprocessable Entity | Valid JSON but business rule violated |
| 429 | Too Many Requests | Rate limit exceeded |
| 500 | Internal Server Error | Server-side error |
Error Codes
| Code | Description |
|---|---|
validation_error | Request body failed validation |
authentication_error | API key missing or invalid |
authorization_error | Insufficient permissions |
not_found | Resource not found |
rate_limit_exceeded | Too many requests |
metadata_too_large | Metadata exceeds 4KB limit |
project_not_assigned | User not assigned to the target project |
Retry Strategy
For 429 responses, read the Retry-After header (in seconds) and wait before retrying. For 5xx responses, use exponential backoff starting at 1 second.
Both SDKs handle retries automatically with configurable limits:
// Node SDK
const keito = new Keito({
apiKey: process.env.KEITO_API_KEY,
maxRetries: 3,
retryDelay: 1000,
});
# Python SDK
client = Keito(
api_key=os.environ["KEITO_API_KEY"],
max_retries=3,
retry_delay=1.0,
)