Skip to main content

Error Handling

The anyformat API uses conventional HTTP response codes and provides structured error responses to help you build robust integrations.

HTTP Status Codes

Status CodeMeaningDescription
200OKRequest succeeded
201CreatedResource was successfully created
202AcceptedRequest accepted for processing (async operations)
204No ContentRequest succeeded with no response body
400Bad RequestInvalid request data or parameters
401UnauthorizedMissing or invalid API key
403ForbiddenAuthenticated but lacking permission
404Not FoundResource doesn’t exist
500Internal Server ErrorUnexpected server error

Error Response Format

All error responses follow a consistent JSON structure:
{
  "error": "Brief, human-readable error description",
  "detail": "Detailed explanation of what went wrong",
  "error_code": "MACHINE_READABLE_ERROR_CODE"
}
FieldDescription
errorShort, human-readable summary
detailDetailed explanation for debugging
error_codeMachine-readable code for programmatic handling

Error Codes Reference

Authentication Errors

AUTH_FAILED (401)
{
  "error": "Authentication failed",
  "detail": "Invalid or missing authentication credentials.",
  "error_code": "AUTH_FAILED"
}

Validation Errors

VALIDATION_ERROR (400)
{
  "error": "Validation failed",
  "detail": "{'name': ['This field is required.'], 'fields': ['This field is required.']}",
  "error_code": "VALIDATION_ERROR"
}
INVALID_JSON (400)
{
  "error": "Invalid JSON format",
  "detail": "The request body contains invalid JSON. Please check your JSON syntax.",
  "error_code": "INVALID_JSON"
}

Resource Errors

NOT_FOUND (404)
{
  "error": "Resource not found",
  "detail": "The requested resource could not be found.",
  "error_code": "NOT_FOUND"
}

Server Errors

INTERNAL_ERROR (500)
{
  "error": "Internal server error",
  "detail": "An unexpected error occurred while processing your request. Please try again or contact support.",
  "error_code": "INTERNAL_ERROR",
  "reference_id": "err_1234"
}
Server errors (500) include a reference_id field. Use this ID when contacting support to help identify and resolve the specific issue.

Error Handling Best Practices

1. Check HTTP Status Codes

import requests

response = requests.get(
    "https://api.anyformat.ai/workflows/",
    headers={"x-api-key": "your-api-key"}
)

if response.status_code == 200:
    workflows = response.json()
elif response.status_code == 401:
    print("Authentication failed. Check your API key.")
elif response.status_code == 404:
    print("Resource not found.")
elif response.status_code >= 500:
    print("Server error. Retry with backoff.")
else:
    error = response.json()
    print(f"Error: {error.get('detail')}")

2. Use Error Codes for Logic

def handle_api_error(response):
    if response.status_code >= 400:
        error_data = response.json()
        error_code = error_data.get('error_code')

        if error_code == 'AUTH_FAILED':
            refresh_authentication()
        elif error_code == 'VALIDATION_ERROR':
            show_validation_error(error_data.get('detail'))
        elif error_code == 'NOT_FOUND':
            handle_missing_resource()
        elif error_code == 'INTERNAL_ERROR':
            retry_with_backoff()
        else:
            log_unexpected_error(error_data)

3. Implement Retry Logic

For server errors (5xx), implement exponential backoff:
import time
import random

def api_request_with_retry(url, headers, max_retries=3):
    for attempt in range(max_retries + 1):
        try:
            response = requests.get(url, headers=headers)

            # Don't retry client errors (4xx)
            if 400 <= response.status_code < 500:
                return response

            # Retry server errors (5xx)
            if response.status_code >= 500 and attempt < max_retries:
                delay = (2 ** attempt) + random.uniform(0, 1)
                time.sleep(delay)
                continue

            return response

        except requests.exceptions.RequestException as e:
            if attempt < max_retries:
                delay = (2 ** attempt) + random.uniform(0, 1)
                time.sleep(delay)
                continue
            raise e

4. Validate Before Sending

def create_workflow(name, description, fields):
    # Validate required fields locally first
    if not name:
        raise ValueError("Workflow name is required")
    if not fields or len(fields) == 0:
        raise ValueError("At least one field is required")

    for field in fields:
        if not field.get('name'):
            raise ValueError("Field name is required")
        if not field.get('data_type'):
            raise ValueError("Field data_type is required")

    # Make API request
    response = requests.post(
        "https://api.anyformat.ai/workflows/",
        headers={"x-api-key": "your-api-key", "Content-Type": "application/json"},
        json={"name": name, "description": description, "fields": fields}
    )

    return handle_response(response)

5. Log Errors for Debugging

import logging

def log_api_error(response, context=""):
    try:
        error_data = response.json()
        error_code = error_data.get('error_code', 'UNKNOWN')
        reference_id = error_data.get('reference_id', 'N/A')

        logging.error(
            f"API Error {response.status_code}: {error_code} - "
            f"{error_data.get('detail', 'No detail')} "
            f"[Context: {context}] [Reference: {reference_id}]"
        )
    except ValueError:
        logging.error(f"API Error {response.status_code}: {response.text}")

Testing Error Scenarios

When building your integration, test these common scenarios:
ScenarioHow to Test
Missing API keyOmit the x-api-key header
Invalid API keyUse a fake or expired key
Missing required fieldsCreate workflow without name or fields
Invalid JSONSend malformed JSON in request body
Nonexistent resourceRequest a workflow/job ID that doesn’t exist
Server errorsTest retry logic (mock 500 responses)

Framework-Level Errors

While most errors use the structured { "error", "detail", "error_code" } format, some framework-level responses (e.g., unknown URL path) may return a simpler format:
{ "detail": "Not found." }