Skip to main content

Error Handling

The Covered API uses standard HTTP status codes and returns errors in a consistent JSON format.

Error response format

All error responses follow this structure:
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Invalid request",
    "details": [
      {
        "field": "amount",
        "message": "must be positive"
      }
    ]
  }
}
FieldDescription
codeMachine-readable error code for programmatic handling
messageHuman-readable error message
detailsOptional array of field-level validation errors

HTTP status codes

Success codes

CodeDescription
200Request succeeded
201Resource created successfully

Client error codes

CodeDescription
400Bad request - invalid parameters or request body
401Unauthorized - missing or invalid API key
403Forbidden - insufficient permissions
404Not found - resource doesn’t exist
409Conflict - resource already exists or state conflict
422Unprocessable - request understood but cannot be processed
429Rate limited - too many requests

Server error codes

CodeDescription
500Internal server error
502Bad gateway
503Service unavailable

Common error codes

Authentication errors

Error CodeHTTP StatusDescription
MISSING_API_KEY401No API key provided
INVALID_API_KEY401API key is invalid or revoked
API_KEY_EXPIRED401API key has expired
RATE_LIMITED429Too many requests

Validation errors

Error CodeHTTP StatusDescription
VALIDATION_ERROR400Request body validation failed
INVALID_PARAMETER400Query parameter is invalid
MISSING_REQUIRED_FIELD400Required field is missing

Resource errors

Error CodeHTTP StatusDescription
NOT_FOUND404Resource not found
ALREADY_EXISTS409Resource already exists
INVALID_STATE400Resource is in wrong state for operation

Payment errors

Error CodeHTTP StatusDescription
INSUFFICIENT_BALANCE400Not enough funds in treasury
PAYMENT_FAILED500Payment processing failed
ONBOARDING_REQUIRED400KYB verification not complete
ONBOARDING_PENDING400KYB verification in progress

Handling errors

async function createPayable(data) {
  const response = await fetch('https://api.allcovered.xyz/v1/payables', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${apiKey}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(data),
  });

  if (!response.ok) {
    const error = await response.json();

    switch (error.error.code) {
      case 'VALIDATION_ERROR':
        // Handle validation errors
        console.error('Validation failed:', error.error.details);
        break;
      case 'RATE_LIMITED':
        // Implement exponential backoff
        const resetTime = response.headers.get('X-RateLimit-Reset');
        console.log(`Rate limited. Try again at ${resetTime}`);
        break;
      case 'INSUFFICIENT_BALANCE':
        // Notify user to add funds
        console.error('Insufficient balance');
        break;
      default:
        console.error('API error:', error.error.message);
    }

    throw new Error(error.error.message);
  }

  return response.json();
}

Retry strategies

Rate limiting

When you receive a 429 response, check the X-RateLimit-Reset header for when to retry:
if (response.status === 429) {
  const resetTime = response.headers.get('X-RateLimit-Reset');
  const waitMs = (parseInt(resetTime) * 1000) - Date.now();
  await new Promise(resolve => setTimeout(resolve, waitMs));
  // Retry the request
}

Server errors

For 5xx errors, implement exponential backoff:
async function fetchWithRetry(url, options, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    const response = await fetch(url, options);

    if (response.status < 500) {
      return response;
    }

    // Exponential backoff: 1s, 2s, 4s
    const waitMs = Math.pow(2, i) * 1000;
    await new Promise(resolve => setTimeout(resolve, waitMs));
  }

  throw new Error('Max retries exceeded');
}

Idempotency

For POST requests that create resources, you can include an Idempotency-Key header to safely retry requests:
curl -X POST https://api.allcovered.xyz/v1/payables \
  -H "Authorization: Bearer cov_xxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: unique-request-id-123" \
  -d '{"invoice_number": "INV-001", ...}'
If you retry with the same idempotency key, you’ll get the same response without creating a duplicate resource.