API Error Codes

All API errors return a consistent JSON structure with an error code, message, and optional details.

Error Response Format

{
  "code": "ERROR_CODE",
  "message": "Human-readable error message",
  "details": { ... },
  "request_id": "optional-request-id"
}

Error Codes Reference

Authentication Errors (4xx)

CodeHTTP StatusDescriptionResolution
UNAUTHORIZED401Missing or invalid authenticationProvide valid API key or session cookie
INVALID_CREDENTIALS401Invalid username or passwordCheck login credentials
SESSION_EXPIRED401Session has expiredRe-authenticate to get new session
INVALID_SIGNATURE401Webhook signature validation failedVerify webhook secret configuration
FORBIDDEN403Authenticated but not authorizedCheck user role and permissions
CSRF_VALIDATION_FAILED403CSRF token missing or invalidInclude valid CSRF token in request
ACCOUNT_DISABLED403User account is disabledContact administrator

Client Errors (4xx)

CodeHTTP StatusDescriptionResolution
NOT_FOUND404Resource not foundVerify resource ID exists
BAD_REQUEST400Malformed requestCheck request syntax and parameters
CONFLICT409Resource conflict (e.g., already exists)Action already completed or duplicate resource
UNPROCESSABLE_ENTITY422Semantic error in requestCheck request logic and data validity
VALIDATION_ERROR422Field validation failedSee details for field-specific errors
RATE_LIMIT_EXCEEDED429Too many requestsWait and retry with exponential backoff

Server Errors (5xx)

CodeHTTP StatusDescriptionResolution
INTERNAL_ERROR500Unexpected server errorCheck server logs, contact support
DATABASE_ERROR500Database operation failedCheck database connectivity
SERVICE_UNAVAILABLE503Service temporarily unavailableRetry later

Detailed Error Examples

Validation Error

When field validation fails, the response includes detailed field-level errors:

{
  "code": "VALIDATION_ERROR",
  "message": "Validation failed",
  "details": {
    "name": {
      "code": "required",
      "message": "Name is required"
    },
    "email": {
      "code": "invalid_format",
      "message": "Invalid email format"
    }
  }
}

Not Found Error

{
  "code": "NOT_FOUND",
  "message": "Not found: Incident 550e8400-e29b-41d4-a716-446655440000 not found"
}

Conflict Error

Returned when attempting an action that conflicts with current state:

{
  "code": "CONFLICT",
  "message": "Conflict: Action is not pending approval (current status: Approved)"
}

Rate Limit Error

{
  "code": "RATE_LIMIT_EXCEEDED",
  "message": "Rate limit exceeded"
}

Include a Retry-After header when available.

Unauthorized Error

{
  "code": "UNAUTHORIZED",
  "message": "Unauthorized: No authentication provided"
}

Error Handling Best Practices

Client Implementation

import requests

def handle_api_error(response):
    error = response.json()
    code = error.get('code')

    if code == 'RATE_LIMIT_EXCEEDED':
        # Implement exponential backoff
        retry_after = int(response.headers.get('Retry-After', 60))
        time.sleep(retry_after)
        return retry_request()

    elif code == 'SESSION_EXPIRED':
        # Re-authenticate
        refresh_session()
        return retry_request()

    elif code == 'VALIDATION_ERROR':
        # Handle field-specific errors
        for field, details in error.get('details', {}).items():
            print(f"Field '{field}': {details['message']}")

    elif code in ['INTERNAL_ERROR', 'DATABASE_ERROR']:
        # Log and alert on server errors
        log_error(error)
        raise ServerError(error['message'])

Retry Strategy

For transient errors (5xx, RATE_LIMIT_EXCEEDED), implement exponential backoff:

import time
import random

def retry_with_backoff(func, max_retries=3):
    for attempt in range(max_retries):
        try:
            return func()
        except (RateLimitError, ServiceUnavailableError) as e:
            if attempt == max_retries - 1:
                raise
            delay = (2 ** attempt) + random.uniform(0, 1)
            time.sleep(delay)

HTTP Status Code Summary

StatusMeaningRetryable
400Bad RequestNo
401UnauthorizedAfter re-auth
403ForbiddenNo
404Not FoundNo
409ConflictNo
422Unprocessable EntityAfter fixing request
429Rate LimitedYes, with backoff
500Internal ErrorYes, with caution
503Service UnavailableYes, with backoff