Skip to content

Error Handling

Learn how to handle errors gracefully when integrating with Circuit KYC.

Error Response Format

All errors follow a consistent format:

{
  "detail": "Error message describing what went wrong",
  "error_code": "INVALID_API_KEY",
  "request_id": "req_abc123"
}
Field Description
detail Human-readable error message
error_code Machine-readable error code
request_id Unique ID for support requests

HTTP Status Codes

Client Errors (4xx)

Status Meaning Common Causes
400 Bad Request Invalid JSON, missing fields
401 Unauthorized Invalid Bearer token
402 Payment Required Insufficient credits
403 Forbidden Invalid API key, account disabled
404 Not Found Resource doesn't exist
422 Unprocessable Entity Validation failed
429 Too Many Requests Rate limit exceeded

Server Errors (5xx)

Status Meaning What to Do
500 Internal Server Error Retry with backoff
502 Bad Gateway Retry with backoff
503 Service Unavailable Check status page, retry
504 Gateway Timeout Retry with backoff

Error Codes

Authentication Errors

Code Description Solution
MISSING_API_KEY No X-API-Key header Add API key header
INVALID_API_KEY API key not recognized Check key is correct
EXPIRED_API_KEY API key has been revoked Generate new key
ACCOUNT_DISABLED Account suspended Contact support

Validation Errors

Code Description Solution
INVALID_EMAIL Email format invalid Use valid email format
INVALID_PHONE Phone not E.164 format Use +[country][number]
MISSING_FIELD Required field not provided Check API docs
INVALID_DATE Date format invalid Use YYYY-MM-DD

Rate Limit Errors

Code Description Solution
RATE_LIMITED Too many requests Wait and retry
BURST_EXCEEDED Burst limit hit Spread requests

Credit Errors

Code Description Solution
INSUFFICIENT_CREDITS Not enough credits Purchase more credits
CREDITS_DEPLETED Zero credits Enable auto-recharge

Handling Errors in Code

Python

from circuit_kyc import CircuitKYC
from circuit_kyc.exceptions import (
    AuthenticationError,
    RateLimitError,
    InsufficientCreditsError,
    ValidationError,
    APIError
)

client = CircuitKYC(api_key="sk_live_your_key")

try:
    result = client.check_eligibility(
        email="user@example.com",
        phone_number="+15551234567"
    )
except AuthenticationError as e:
    # Invalid or missing API key
    print(f"Auth failed: {e.message}")

except RateLimitError as e:
    # Rate limited - wait and retry
    print(f"Rate limited. Retry after {e.retry_after} seconds")
    time.sleep(e.retry_after)

except InsufficientCreditsError as e:
    # Need more credits
    print("Please purchase more credits")

except ValidationError as e:
    # Invalid input
    print(f"Validation error: {e.message}")
    for error in e.errors:
        print(f"  - {error['field']}: {error['message']}")

except APIError as e:
    # Server error - retry with backoff
    print(f"API error: {e.message}")

TypeScript

import { CircuitKYC } from '@circuit-kyc/sdk';
import {
  AuthenticationError,
  RateLimitError,
  InsufficientCreditsError,
  ValidationError,
  APIError
} from '@circuit-kyc/sdk/errors';

const client = new CircuitKYC({ apiKey: 'sk_live_your_key' });

try {
  const result = await client.checkEligibility({
    email: 'user@example.com',
    phoneNumber: '+15551234567'
  });
} catch (error) {
  if (error instanceof AuthenticationError) {
    console.error('Auth failed:', error.message);
  } else if (error instanceof RateLimitError) {
    console.error(`Rate limited. Retry after ${error.retryAfter}s`);
    await sleep(error.retryAfter * 1000);
  } else if (error instanceof InsufficientCreditsError) {
    console.error('Please purchase more credits');
  } else if (error instanceof ValidationError) {
    console.error('Validation error:', error.errors);
  } else if (error instanceof APIError) {
    console.error('API error:', error.message);
  }
}

cURL / Raw HTTP

# Check response status
response=$(curl -s -w "\n%{http_code}" \
  -X POST https://api.circuitkyc.com/api/v1/check-eligibility \
  -H "X-API-Key: sk_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{"email": "user@example.com", "phone_number": "+15551234567"}')

status_code=$(echo "$response" | tail -1)
body=$(echo "$response" | head -n -1)

case $status_code in
  200)
    echo "Success: $body"
    ;;
  402)
    echo "Need more credits"
    ;;
  429)
    retry_after=$(echo "$body" | jq -r '.retry_after')
    echo "Rate limited. Retry after $retry_after seconds"
    ;;
  *)
    echo "Error $status_code: $body"
    ;;
esac

Retry Strategy

Implement exponential backoff for transient errors:

import time
import random

def retry_with_backoff(func, max_retries=3):
    """Retry a function with exponential backoff."""
    for attempt in range(max_retries):
        try:
            return func()
        except (RateLimitError, APIError) as e:
            if attempt == max_retries - 1:
                raise

            # Exponential backoff with jitter
            wait_time = (2 ** attempt) + random.uniform(0, 1)

            # Use retry_after header if available
            if hasattr(e, 'retry_after'):
                wait_time = e.retry_after

            print(f"Attempt {attempt + 1} failed. Retrying in {wait_time:.1f}s")
            time.sleep(wait_time)
Error Type Max Retries Initial Delay
429 Rate Limited 3 Use Retry-After
500 Server Error 3 1 second
502 Bad Gateway 3 2 seconds
503 Unavailable 5 5 seconds
504 Timeout 3 2 seconds

Rate Limit Headers

Every response includes rate limit headers:

X-RateLimit-Limit: 300
X-RateLimit-Remaining: 295
X-RateLimit-Reset: 1705312260
Retry-After: 30  (only on 429 responses)

Use these to implement proactive rate limiting:

def check_rate_limit(response):
    remaining = int(response.headers.get('X-RateLimit-Remaining', 0))

    if remaining < 10:
        print(f"Warning: Only {remaining} requests remaining")

    if remaining == 0:
        reset_time = int(response.headers.get('X-RateLimit-Reset'))
        wait_time = reset_time - time.time()
        print(f"Rate limit exhausted. Reset in {wait_time:.0f}s")

Debugging

Enable Debug Logging

import logging

# Enable debug logging
logging.basicConfig(level=logging.DEBUG)

client = CircuitKYC(api_key="sk_live_your_key")

Include Request ID in Support Requests

Always include the request_id when contacting support:

Subject: API Error - Request ID: req_abc123

I received an error when calling /check-eligibility:

Request ID: req_abc123
Status: 500
Time: 2024-01-15T10:30:00Z
Error: Internal Server Error

Best Practices

  1. Always handle errors - Don't let exceptions crash your app
  2. Implement retries - Use exponential backoff for 5xx errors
  3. Log errors - Include request_id for debugging
  4. Monitor rate limits - Track headers to avoid 429s
  5. Validate input - Check data before sending to API
  6. Use SDKs - They handle common errors automatically