Aurion Docs

Error Handling

HTTP status codes, error response format, and retry strategies for the Aurion API.

Error Handling

The Aurion API uses standard HTTP status codes and returns structured JSON error responses.

HTTP Status Codes

CodeMeaningWhen
200OKRequest succeeded
201CreatedResource created successfully
204No ContentResource deleted successfully
400Bad RequestInvalid request body or parameters
401UnauthorizedMissing or invalid API key
403ForbiddenValid key but insufficient scope
404Not FoundResource does not exist
409ConflictResource already exists (duplicate)
422Unprocessable EntityValidation error on request body
429Too Many RequestsRate limit exceeded
500Internal Server ErrorUnexpected server error
503Service UnavailableTemporary outage or maintenance

Error Response Format

All error responses follow the same structure:

{
  "error": "validation_error",
  "message": "Human-readable description of what went wrong",
  "details": [
    {
      "field": "priority",
      "message": "Must be one of: low, medium, high, urgent"
    }
  ]
}
FieldTypeDescription
errorstringMachine-readable error code
messagestringHuman-readable error description
detailsarrayField-level validation errors (only for 422)

Common Error Codes

Error CodeHTTP StatusDescription
unauthorized401Missing or invalid API key
forbidden403Insufficient scope
not_found404Resource not found
validation_error422Request body validation failed
rate_limit_exceeded429Too many requests
idempotency_conflict409Different request body with same idempotency key
internal_error500Unexpected server error

Rate Limiting

The API returns a 429 response when you exceed your rate limit. The response includes a Retry-After header:

HTTP/1.1 429 Too Many Requests
Retry-After: 12
{
  "error": "rate_limit_exceeded",
  "message": "Rate limit exceeded. Retry after 12 seconds.",
  "retry_after": 12
}

Retry Strategy

For transient errors (429, 500, 503), use exponential backoff with jitter:

Python
import time
import random
import requests

def request_with_retry(method, url, max_retries=3, **kwargs):
    for attempt in range(max_retries + 1):
        response = requests.request(method, url, **kwargs)

        if response.status_code == 429:
            retry_after = int(response.headers.get("Retry-After", 5))
            time.sleep(retry_after)
            continue

        if response.status_code in (500, 503) and attempt < max_retries:
            delay = (2 ** attempt) + random.uniform(0, 1)
            time.sleep(delay)
            continue

        return response

    return response
TypeScript
async function requestWithRetry(
  url: string,
  options: RequestInit,
  maxRetries = 3
): Promise<Response> {
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    const response = await fetch(url, options);

    if (response.status === 429) {
      const retryAfter = parseInt(
        response.headers.get("Retry-After") ?? "5"
      );
      await new Promise((r) => setTimeout(r, retryAfter * 1000));
      continue;
    }

    if ([500, 503].includes(response.status) && attempt < maxRetries) {
      const delay = 2 ** attempt + Math.random();
      await new Promise((r) => setTimeout(r, delay * 1000));
      continue;
    }

    return response;
  }

  throw new Error("Max retries exceeded");
}

Best Practices

  • Check the error field — Use the machine-readable code for programmatic handling
  • Log the full response — Include the message for debugging
  • Respect Retry-After — Don't retry faster than the header suggests
  • Don't retry 4xx — Client errors (except 429) indicate a problem with your request

On this page