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."
}
FieldTypeDescription
errorstringA machine-readable error code that you can match against in your code.
messagestringA 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.

StatusMeaningWhen Used
200 OKThe request succeeded.Standard GET, PUT, PATCH, DELETE responses.
201 CreatedA resource was created successfully.POST responses that create a new resource.
202 AcceptedThe request was accepted for processing.Skill execution and async webhook triggers.
204 No ContentThe request succeeded with no response body.Some DELETE operations.
StatusMeaningWhen Used
400 Bad RequestThe request body or parameters are invalid.Missing required fields, malformed JSON, invalid parameter values.
401 UnauthorizedAuthentication failed.Missing or invalid API key, expired key, invalid admin secret.
403 ForbiddenThe authenticated key lacks permission.API key does not have the required scope for the requested operation.
404 Not FoundThe requested resource does not exist.Invalid IDs, non-existent endpoints.
409 ConflictThe request conflicts with current state.Attempting to create a duplicate resource.
422 Unprocessable EntityThe request is well-formed but semantically invalid.Valid JSON but with logically incorrect values.
429 Too Many RequestsRate limit exceeded.See Rate Limiting for details.
StatusMeaningWhen Used
500 Internal Server ErrorAn unexpected error occurred on the server.Platform bugs, unhandled exceptions.
502 Bad GatewayAn upstream service is unavailable.External integration connectivity issues.
503 Service UnavailableThe 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