Skip to content

Errors

When an API request fails, Horizon returns an appropriate HTTP status code along with a JSON error body that describes what went wrong. This page documents the error format and lists common error responses.

All error responses follow a consistent JSON format:

{
"error": "error_code",
"message": "A human-readable description of what went wrong."
}
Field Type Description
error string A machine-readable error code that you can match against in your code.
message string A human-readable explanation of the error, suitable for logging or debugging.

Some error responses include additional fields with context-specific details:

{
"error": "validation_error",
"message": "Request body validation failed.",
"details": [
{ "field": "cron_expression", "issue": "Invalid cron expression format" },
{ "field": "agent_id", "issue": "Required field missing" }
]
}

Horizon uses standard HTTP status codes to indicate the result of an API request.

Status Meaning When Used
200 OK The request succeeded. Standard GET, PUT, PATCH, DELETE responses.
201 Created A resource was created successfully. POST responses that create a new resource.
202 Accepted The request was accepted for processing. Skill execution and async webhook triggers.
204 No Content The request succeeded with no response body. Some DELETE operations.
Status Meaning When Used
400 Bad Request The request body or parameters are invalid. Missing required fields, malformed JSON, invalid parameter values.
401 Unauthorized Authentication failed. Missing or invalid API key, expired key, invalid admin secret.
403 Forbidden The authenticated key lacks permission. API key does not have the required scope for the requested operation.
404 Not Found The requested resource does not exist. Invalid IDs, non-existent endpoints.
409 Conflict The request conflicts with current state. Attempting to create a duplicate resource.
422 Unprocessable Entity The request is well-formed but semantically invalid. Valid JSON but with logically incorrect values.
429 Too Many Requests Rate limit exceeded. See Rate Limiting for details.
Status Meaning When Used
500 Internal Server Error An unexpected error occurred on the server. Platform bugs, unhandled exceptions.
502 Bad Gateway An upstream service is unavailable. External integration connectivity issues.
503 Service Unavailable The service is temporarily unavailable. Maintenance windows, overload conditions.

Missing API key:

// 401 Unauthorized
{
"error": "authentication_required",
"message": "Missing API key. Provide a valid key in the x-api-key header."
}

Invalid or revoked API key:

// 401 Unauthorized
{
"error": "invalid_api_key",
"message": "The provided API key is invalid or has been revoked."
}

Expired API key:

// 401 Unauthorized
{
"error": "api_key_expired",
"message": "The provided API key has expired."
}

Invalid admin secret:

// 401 Unauthorized
{
"error": "invalid_admin_secret",
"message": "The provided admin secret is invalid."
}

Insufficient scope:

// 403 Forbidden
{
"error": "insufficient_scope",
"message": "The API key does not have the required scope 'quickbooks' for this operation."
}

Missing required field:

// 400 Bad Request
{
"error": "validation_error",
"message": "The 'client_name' field is required."
}

Invalid parameter value:

// 400 Bad Request
{
"error": "validation_error",
"message": "The 'limit' parameter must be between 1 and 200."
}

Resource not found:

// 404 Not Found
{
"error": "not_found",
"message": "Conversation 'conv_nonexistent' not found."
}

Rate limit exceeded:

// 429 Too Many Requests
{
"error": "rate_limit_exceeded",
"message": "Rate limit exceeded. Maximum 100 requests per minute.",
"retry_after": 23
}
Terminal window
# Check the HTTP status code in the response
curl -s -w "\nHTTP Status: %{http_code}" \
-X GET https://api.horizonplatform.ai/api/conversations/invalid_id \
-H "x-api-key: hz_live_abc123def456"
const response = await fetch(
'https://api.horizonplatform.ai/api/conversations/invalid_id',
{ headers: { 'x-api-key': 'hz_live_abc123def456' } }
);
if (!response.ok) {
const error = await response.json();
console.error(`Error ${response.status}: [${error.error}] ${error.message}`);
switch (response.status) {
case 401:
// Re-authenticate or refresh API key
break;
case 403:
// Check key scopes
break;
case 429:
// Implement backoff and retry
break;
default:
// Log and alert
break;
}
}
import requests
response = requests.get(
'https://api.horizonplatform.ai/api/conversations/invalid_id',
headers={'x-api-key': 'hz_live_abc123def456'}
)
if not response.ok:
error = response.json()
print(f"Error {response.status_code}: [{error['error']}] {error['message']}")
if response.status_code == 401:
# Re-authenticate or refresh API key
pass
elif response.status_code == 403:
# Check key scopes
pass
elif response.status_code == 429:
# Implement backoff and retry
pass
else:
# Log and alert
pass