Skip to main content

Error Handling Guide

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

HTTP Status Codes

The API uses standard HTTP status codes to indicate the success or failure of requests:
Status CodeMeaningDescription
200OKRequest succeeded
201CreatedResource was successfully created
204No ContentRequest succeeded with no response body
400Bad RequestInvalid request data or parameters
403ForbiddenMissing/invalid authentication or insufficient permissions
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"
}

Common Error Scenarios

Authentication Errors

Missing API Key:
{
  "detail": "Authentication credentials were not provided."
}
Invalid API Key:
{
  "detail": "Invalid token."
}

Validation Errors

Missing Required Fields:
{
  "error": "Validation failed",
  "detail": "{'name': ['This field is required.'], 'fields': ['This field is required.']}",
  "error_code": "VALIDATION_ERROR"
}
Invalid Field Values:
{
  "error": "Validation failed",
  "detail": "{'fields': ['This field cannot be empty.']}",
  "error_code": "VALIDATION_ERROR"
}
Invalid JSON:
{
  "error": "Invalid JSON format",
  "detail": "The request body contains invalid JSON. Please check your JSON syntax.",
  "error_code": "INVALID_JSON"
}

Resource Errors

Workflow Not Found:
{
  "error": "Resource not found",
  "detail": "The requested resource could not be found.",
  "error_code": "NOT_FOUND"
}
Job Not Found:
{
  "error": "Resource not found", 
  "detail": "The requested resource could not be found.",
  "error_code": "NOT_FOUND"
}
Internal Server Error:
{
  "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"
}

Error Handling Best Practices

1. Always 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()
    # Process successful response
elif response.status_code == 403:
    error = response.json()
    print(f"Authentication error: {error['detail']}")
elif response.status_code >= 400:
    error = response.json()
    print(f"Error {response.status_code}: {error['detail']}")

2. Use Error Codes for Programmatic Handling

def handle_api_error(response):
    if response.status_code >= 400:
        error_data = response.json()
        error_code = error_data.get('error_code')
        
        if response.status_code == 403:
            # Handle authentication failures (missing/invalid API key)
            refresh_authentication()
        elif error_code == 'VALIDATION_ERROR':
            # Show validation errors to user
            # All errors use the 'detail' field consistently
            show_validation_error(error_data.get('detail', 'Validation failed'))
        elif error_code == 'NOT_FOUND':
            # Handle missing resource gracefully
            handle_missing_resource()
        elif error_code == 'INTERNAL_ERROR':
            # Implement retry logic with exponential backoff
            retry_with_backoff()
        else:
            # Log unexpected error for investigation
            log_unexpected_error(error_data)

3. Implement Retry Logic for Server Errors

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:
                # Exponential backoff with jitter
                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 Requests Before Sending

def create_workflow(name, description, fields):
    # Validate required fields
    if not name:
        raise ValueError("Workflow name is required")
    if not fields or len(fields) == 0:
        raise ValueError("At least one field is required")
    
    # Validate field structure
    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"},
        json={
            "name": name,
            "description": description,
            "fields": fields
        }
    )
    
    return handle_response(response)

5. Log Errors for Debugging

import logging

def log_api_error(response, context=""):
    """Log API errors with context for debugging"""
    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} - {error_data.get('detail', 'No detail')} "
            f"[Context: {context}] [Reference: {reference_id}]"
        )
    except ValueError:
        # Response is not JSON
        logging.error(f"API Error {response.status_code}: {response.text} [Context: {context}]")

# Usage
response = requests.get(url, headers=headers)
if response.status_code >= 400:
    log_api_error(response, "fetching workflows")

Error Response Structure Notes

  • All error messages use "detail" for consistent error descriptions
  • Internal errors (500) automatically include a "reference_id" field (format: err_XXXX) for tracking and support purposes
  • All errors include an "error_code" field for programmatic handling
This structure provides both human-readable error descriptions and machine-readable error codes for robust error handling.

Technical Note: Authentication Status Codes

The API returns 403 Forbidden for authentication failures (missing or invalid API keys). This follows standard HTTP conventions where authentication middleware handles API key validation and converts authentication failures to 403 responses by default.

Testing Error Scenarios

When building your integration, test these common error scenarios:
  1. Missing API key - Make requests without the x-api-key header
  2. Invalid API key - Use a fake or expired API key
  3. Missing required fields - Create workflows without name or fields
  4. Invalid JSON - Send malformed JSON in request body
  5. Nonexistent resources - Try to access workflows or jobs that don’t exist
  6. Large payloads - Test with very large files or data