InboxIssue

Error Handling

API error codes and handling best practices

Error Handling

Learn how to handle API errors gracefully and troubleshoot common issues.

Error Response Format

All API errors return a consistent JSON format:

{
  "success": false,
  "error": "Human-readable error message",
  "errors": ["Array of validation errors if applicable"]
}

HTTP Status Codes

CodeDescription
200Success
201Created
400Bad Request - Invalid parameters
401Unauthorized - Invalid or missing API token
403Forbidden - API access not available on your plan
404Not Found - Resource doesn't exist
422Unprocessable Entity - Validation errors
429Too Many Requests - Rate limit exceeded
500Internal Server Error
503Service Unavailable - Temporary issue

Common Errors

401 Unauthorized

{
  "success": false,
  "error": "Invalid or missing API token"
}

Causes:

  • Missing Authorization header
  • Invalid API token
  • Revoked token

Solutions:

  • Include Authorization: Bearer YOUR_TOKEN header
  • Verify token is correct
  • Generate a new token if needed

403 Forbidden

{
  "success": false,
  "error": "API access not available on your subscription plan"
}

Cause: API access requires Pro or Enterprise plan.

Solution: Upgrade your subscription at Settings > Subscription.


404 Not Found

{
  "success": false,
  "error": "Test not found"
}

Causes:

  • Invalid test ID
  • Test belongs to different account
  • Test was deleted

Solutions:

  • Verify the test ID is correct
  • Check you're using the right account

422 Unprocessable Entity

{
  "success": false,
  "error": "Validation failed",
  "errors": [
    "Name can't be blank",
    "Provider types invalid: unknown_type"
  ]
}

Cause: Request body failed validation.

Solution: Check the errors array for specific issues and fix your request.


429 Rate Limited

{
  "success": false,
  "error": "Rate limit exceeded. Try again in 60 seconds."
}

Cause: Too many requests in a short period.

Solution: Implement exponential backoff:

import time
 
def api_request_with_retry(func, max_retries=5):
    delay = 1
    for attempt in range(max_retries):
        try:
            return func()
        except RateLimitError:
            if attempt == max_retries - 1:
                raise
            time.sleep(delay)
            delay *= 2  # Exponential backoff

503 Service Unavailable

{
  "success": false,
  "error": "Service temporarily unavailable. Please try again."
}

Cause: Temporary service issue.

Solution: Retry with exponential backoff after a few seconds.


Validation Errors

Invalid Provider Types

{
  "success": false,
  "error": "Invalid provider types: invalid_type. Valid types: consumer, business, protected"
}

Valid values: consumer, business, protected


Missing Required Fields

{
  "success": false,
  "error": "Validation failed",
  "errors": ["Name is required"]
}

Error Handling Best Practices

1. Check Status Codes

response = requests.post(url, headers=headers, json=data)
 
if response.status_code == 401:
    raise AuthenticationError("Invalid API token")
elif response.status_code == 403:
    raise PlanError("API access requires Pro plan")
elif response.status_code == 429:
    retry_after = int(response.headers.get('Retry-After', 60))
    raise RateLimitError(f"Rate limited. Retry after {retry_after}s")
elif response.status_code >= 500:
    raise ServiceError("Server error. Retry later.")
elif not response.ok:
    error_data = response.json()
    raise APIError(error_data.get('error', 'Unknown error'))

2. Implement Retries

import time
from functools import wraps
 
def retry_on_error(max_retries=3, backoff_factor=2):
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            delay = 1
            for attempt in range(max_retries):
                try:
                    return func(*args, **kwargs)
                except (RateLimitError, ServiceError) as e:
                    if attempt == max_retries - 1:
                        raise
                    time.sleep(delay)
                    delay *= backoff_factor
        return wrapper
    return decorator
 
@retry_on_error(max_retries=3)
def create_test(client, name):
    return client.create_test(name=name)

3. Log Errors

import logging
 
logger = logging.getLogger(__name__)
 
try:
    result = api_client.create_test(name="Test")
except APIError as e:
    logger.error(f"API error: {e}", extra={
        "status_code": e.status_code,
        "error": e.message
    })
    raise

4. Handle Gracefully

def safe_create_test(name):
    try:
        return api_client.create_test(name=name)
    except AuthenticationError:
        return {"error": "Please check your API credentials"}
    except PlanError:
        return {"error": "Please upgrade to Pro plan for API access"}
    except RateLimitError as e:
        return {"error": f"Too many requests. Please wait {e.retry_after}s"}
    except APIError as e:
        return {"error": f"Failed to create test: {e.message}"}

Debugging Tips

1. Enable Verbose Logging

import logging
import http.client
 
# Enable HTTP debug logging
http.client.HTTPConnection.debuglevel = 1
logging.basicConfig(level=logging.DEBUG)

2. Check Request/Response

response = requests.post(url, headers=headers, json=data)
print(f"Status: {response.status_code}")
print(f"Headers: {response.headers}")
print(f"Body: {response.text}")

3. Validate JSON

import json
 
try:
    data = json.loads(response.text)
except json.JSONDecodeError as e:
    print(f"Invalid JSON response: {e}")