Skip to main content

Error Handling

The Ascend API uses standard HTTP status codes and returns structured JSON error responses to help you diagnose and handle errors effectively.

Error Response Format

All error responses follow a consistent JSON structure:

{
"detail": "Human-readable error message",
"error_code": "MACHINE_READABLE_CODE",
"status": 400,
"correlation_id": "action_20260120_143052_abc12345",
"timestamp": "2026-01-20T14:30:52Z"
}
FieldTypeDescription
detailstringHuman-readable error description
error_codestringMachine-readable error code for programmatic handling
statusintegerHTTP status code
correlation_idstringUnique ID for request tracing (include in support tickets)
timestampstringISO 8601 timestamp of the error

HTTP Status Codes

Success Codes

CodeNameDescription
200OKRequest succeeded
201CreatedResource created successfully
204No ContentRequest succeeded, no response body (e.g., DELETE)

Client Error Codes (4xx)

CodeNameDescription
400Bad RequestInvalid request syntax or parameters
401UnauthorizedMissing or invalid authentication
403ForbiddenValid auth but insufficient permissions
404Not FoundResource does not exist
409ConflictResource already exists or state conflict
422Unprocessable EntityValid syntax but semantic errors
429Too Many RequestsRate limit exceeded

Server Error Codes (5xx)

CodeNameDescription
500Internal Server ErrorUnexpected server error
502Bad GatewayUpstream service unavailable
503Service UnavailableService temporarily unavailable

Common Error Codes

Authentication Errors

Error CodeHTTP StatusDescriptionResolution
INVALID_API_KEY401API key is invalid or malformedCheck API key format and value
EXPIRED_API_KEY401API key has expiredGenerate a new API key
REVOKED_API_KEY401API key has been revokedGenerate a new API key
INVALID_TOKEN401JWT token is invalid or expiredRefresh or obtain new token
MISSING_AUTH401No authentication providedInclude X-API-Key or Authorization header

Example:

{
"detail": "API key has expired",
"error_code": "EXPIRED_API_KEY",
"status": 401,
"correlation_id": "auth_20260120_143052_def456"
}

Authorization Errors

Error CodeHTTP StatusDescriptionResolution
INSUFFICIENT_PERMISSIONS403User lacks required permissionsContact admin for role upgrade
ADMIN_REQUIRED403Admin role required for this actionUse admin credentials
ORGANIZATION_MISMATCH403Resource belongs to different orgVerify resource ownership

Example:

{
"detail": "Admin role required to manage webhooks",
"error_code": "ADMIN_REQUIRED",
"status": 403
}

Validation Errors

Error CodeHTTP StatusDescriptionResolution
MISSING_FIELD422Required field is missingInclude all required fields
INVALID_FIELD_TYPE422Field has wrong data typeCheck field type requirements
INVALID_FIELD_VALUE422Field value is out of rangeCheck valid value ranges
VALIDATION_ERROR422General validation failureReview request body

Example:

{
"detail": "Missing required fields: agent_id, action_type",
"error_code": "MISSING_FIELD",
"status": 422,
"missing_fields": ["agent_id", "action_type"]
}

Resource Errors

Error CodeHTTP StatusDescriptionResolution
RESOURCE_NOT_FOUND404Requested resource doesn't existVerify resource ID
AGENT_NOT_FOUND404Agent with given ID not foundRegister agent first
ACTION_NOT_FOUND404Action with given ID not foundVerify action ID
ALREADY_EXISTS409Resource with same ID existsUse unique identifier
INVALID_STATE400Resource in invalid state for operationCheck current state

Example:

{
"detail": "Action 12345 not found",
"error_code": "ACTION_NOT_FOUND",
"status": 404
}

Rate Limiting Errors

Error CodeHTTP StatusDescriptionResolution
RATE_LIMIT_EXCEEDED429Request rate limit exceededWait and retry with backoff
AGENT_RATE_LIMIT429Per-agent rate limit exceededReduce agent request frequency
ORG_RATE_LIMIT429Organization rate limit exceededContact support for limit increase

Example:

{
"detail": "Rate limit exceeded: 100 requests per minute",
"error_code": "RATE_LIMIT_EXCEEDED",
"status": 429,
"retry_after": 45,
"limit": 100,
"remaining": 0,
"reset_at": "2026-01-20T14:31:00Z"
}

Governance Errors

Error CodeHTTP StatusDescriptionResolution
ACTION_DENIED403Action blocked by policyReview policy or request exemption
APPROVAL_REQUIRED202Action requires human approvalWait for approval decision
SPEND_LIMIT_EXCEEDED402Organization spend limit reachedContact billing admin
KILL_SWITCH_ACTIVE402Organization kill-switch is activeContact admin to reactivate

Example:

{
"detail": "Action blocked by policy: No database writes during maintenance window",
"error_code": "ACTION_DENIED",
"status": 403,
"policy_name": "maintenance-window-policy",
"policy_id": 42
}

Error Handling Best Practices

1. Always Check Status Codes

import requests

response = requests.post(
"https://pilot.owkai.app/api/v1/actions/submit",
headers={"X-API-Key": api_key},
json=payload
)

if response.status_code == 200:
result = response.json()
# Handle success
elif response.status_code == 401:
# Handle authentication error
raise AuthenticationError(response.json()["detail"])
elif response.status_code == 429:
# Handle rate limiting with exponential backoff
retry_after = response.json().get("retry_after", 60)
time.sleep(retry_after)
elif response.status_code >= 500:
# Handle server errors with retry
raise ServerError(response.json()["detail"])
else:
# Handle other errors
raise APIError(response.json()["detail"])

2. Implement Exponential Backoff

import time
import random

def submit_with_retry(payload, max_retries=3):
for attempt in range(max_retries):
response = requests.post(url, json=payload)

if response.status_code == 200:
return response.json()

if response.status_code == 429:
# Exponential backoff with jitter
wait_time = (2 ** attempt) + random.uniform(0, 1)
time.sleep(wait_time)
continue

if response.status_code >= 500:
# Server error - retry with backoff
wait_time = (2 ** attempt) + random.uniform(0, 1)
time.sleep(wait_time)
continue

# Client error - don't retry
raise APIError(response.json())

raise MaxRetriesExceeded("Failed after maximum retries")

3. Log Correlation IDs

Always log the correlation_id from error responses for debugging:

try:
result = client.actions.submit(payload)
except APIError as e:
logger.error(
f"API error: {e.detail}",
extra={
"correlation_id": e.correlation_id,
"error_code": e.error_code,
"status": e.status
}
)

4. Handle Pending Approvals

When an action requires approval, poll for status:

result = client.actions.submit(payload)

if result["status"] == "pending_approval":
action_id = result["id"]

# Poll for approval decision
while True:
status = client.actions.get_status(action_id)

if status["decision_ready"]:
if status["status"] == "approved":
print("Action approved!")
break
elif status["status"] == "denied":
print("Action denied")
break

time.sleep(5) # Poll every 5 seconds

SDK Error Handling

Python SDK

from ascend import AscendClient
from ascend.exceptions import (
AuthenticationError,
RateLimitError,
ValidationError,
ActionDeniedError
)

client = AscendClient(api_key="owkai_...")

try:
result = client.actions.submit(
agent_id="my-agent",
action_type="database_query",
description="Query users",
tool_name="postgresql"
)
except AuthenticationError as e:
print(f"Auth failed: {e}")
except RateLimitError as e:
print(f"Rate limited. Retry after {e.retry_after}s")
except ValidationError as e:
print(f"Invalid request: {e.missing_fields}")
except ActionDeniedError as e:
print(f"Action denied by policy: {e.policy_name}")

Node.js SDK

import { AscendClient, AscendError } from '@ascend-ai/sdk';

const client = new AscendClient({ apiKey: 'owkai_...' });

try {
const result = await client.actions.submit({
agentId: 'my-agent',
actionType: 'database_query',
description: 'Query users',
toolName: 'postgresql'
});
} catch (error) {
if (error instanceof AscendError) {
console.error(`Error: ${error.message}`);
console.error(`Code: ${error.code}`);
console.error(`Correlation ID: ${error.correlationId}`);

if (error.code === 'RATE_LIMIT_EXCEEDED') {
await sleep(error.retryAfter * 1000);
// Retry...
}
}
}

Troubleshooting

"Invalid API Key" Error

  1. Verify the API key format: owkai_{role}_{random}
  2. Check that the key hasn't been revoked
  3. Ensure the key hasn't expired
  4. Confirm you're using the correct environment (production vs sandbox)

"Rate Limit Exceeded" Error

  1. Check the retry_after value in the response
  2. Implement exponential backoff
  3. Consider batching requests
  4. Contact support if you need higher limits

"Action Denied" Error

  1. Review the policy that denied the action
  2. Check if the action type is allowed for your agent
  3. Verify the risk score isn't exceeding thresholds
  4. Request a policy exemption if needed

"Spend Limit Exceeded" Error

  1. Contact your billing administrator
  2. Review current usage in the admin console
  3. Request a limit increase if needed

500 Internal Server Error

  1. Note the correlation_id for support
  2. Retry with exponential backoff
  3. Check the status page for outages
  4. Contact support if the issue persists