Docs

Error Codes

Complete reference of HTTP status codes and error responses

Error Codes

The API uses standard HTTP status codes and returns detailed error information to help you diagnose and handle issues.

HTTP Status Codes

Success (2xx)

CodeNameDescription
200OKRequest succeeded
201CreatedResource created successfully
202AcceptedRequest accepted for async processing
204No ContentRequest succeeded, no content returned

Client Errors (4xx)

CodeNameDescription
400Bad RequestInvalid request syntax or parameters
401UnauthorizedAuthentication required or invalid
403ForbiddenInsufficient permissions
404Not FoundResource does not exist
409ConflictResource conflict (e.g., duplicate)
422Unprocessable EntityValidation failed
429Too Many RequestsRate limit exceeded

Server Errors (5xx)

CodeNameDescription
500Internal Server ErrorUnexpected server error
502Bad GatewayUpstream service error
503Service UnavailableService temporarily unavailable
504Gateway TimeoutUpstream service timeout

Error Response Format

All errors follow a consistent JSON structure:

{
  "error": "Error code string",
  "code": "ERROR_CODE",
  "message": "Human-readable error description",
  "details": [
    {
      "field": "fieldName",
      "message": "Specific field error"
    }
  ],
  "requestId": "req_1234567890",
  "documentation": "https://docs.yourapp.com/errors/ERROR_CODE"
}

Authentication Errors

UNAUTHORIZED (401)

{
  "error": "Unauthorized",
  "code": "UNAUTHORIZED",
  "message": "Authentication required. Please provide a valid API key or session token.",
  "requestId": "req_abc123"
}

Common causes:

  • Missing or invalid API key
  • Expired session token
  • Invalid JWT signature

FORBIDDEN (403)

{
  "error": "Forbidden",
  "code": "FORBIDDEN",
  "message": "You do not have permission to access this resource.",
  "requestId": "req_def456"
}

Common causes:

  • Insufficient role permissions
  • Resource ownership mismatch
  • Feature not available on current plan

TOKEN_EXPIRED (401)

{
  "error": "Token expired",
  "code": "TOKEN_EXPIRED",
  "message": "Your session has expired. Please sign in again.",
  "requestId": "req_ghi789"
}

Validation Errors

VALIDATION_ERROR (422)

{
  "error": "Validation failed",
  "code": "VALIDATION_ERROR",
  "message": "The request contains invalid parameters.",
  "details": [
    {
      "field": "email",
      "message": "Invalid email format",
      "value": "not-an-email"
    },
    {
      "field": "password",
      "message": "Password must be at least 8 characters"
    }
  ],
  "requestId": "req_jkl012"
}

INVALID_JSON (400)

{
  "error": "Invalid JSON",
  "code": "INVALID_JSON",
  "message": "The request body contains malformed JSON.",
  "requestId": "req_mno345"
}

MISSING_FIELD (422)

{
  "error": "Missing required field",
  "code": "MISSING_FIELD",
  "message": "Required field is missing.",
  "details": [
    {
      "field": "to",
      "message": "Recipient email address is required"
    }
  ],
  "requestId": "req_pqr678"
}

Resource Errors

NOT_FOUND (404)

{
  "error": "Not found",
  "code": "NOT_FOUND",
  "message": "The requested resource does not exist.",
  "resource": "inbox",
  "resourceId": "inbox_123",
  "requestId": "req_stu901"
}

ALREADY_EXISTS (409)

{
  "error": "Already exists",
  "code": "ALREADY_EXISTS",
  "message": "A resource with this identifier already exists.",
  "resource": "inbox",
  "field": "address",
  "value": "test@yourdomain.com",
  "requestId": "req_vwx234"
}

RESOURCE_CONFLICT (409)

{
  "error": "Resource conflict",
  "code": "RESOURCE_CONFLICT",
  "message": "The resource is in a state that prevents this operation.",
  "resource": "subscription",
  "currentState": "canceled",
  "requestedAction": "update",
  "requestId": "req_yza567"
}

Rate Limit Errors

RATE_LIMIT_EXCEEDED (429)

{
  "error": "Rate limit exceeded",
  "code": "RATE_LIMIT_EXCEEDED",
  "message": "You have exceeded the rate limit for this endpoint.",
  "retryAfter": 3600,
  "limit": 100,
  "window": "1h",
  "requestId": "req_bcd890"
}

QUOTA_EXCEEDED (429)

{
  "error": "Quota exceeded",
  "code": "QUOTA_EXCEEDED",
  "message": "You have exceeded your plan's monthly quota.",
  "quota": "email_sends",
  "limit": 1000,
  "used": 1005,
  "resetsAt": "2024-02-01T00:00:00Z",
  "requestId": "req_efg123"
}

Email API Errors

INVALID_EMAIL_ADDRESS (422)

{
  "error": "Invalid email address",
  "code": "INVALID_EMAIL_ADDRESS",
  "message": "One or more email addresses are invalid.",
  "details": [
    {
      "field": "to[0]",
      "message": "Invalid email format",
      "value": "invalid@"
    }
  ],
  "requestId": "req_hij456"
}

DOMAIN_NOT_VERIFIED (403)

{
  "error": "Domain not verified",
  "code": "DOMAIN_NOT_VERIFIED",
  "message": "The sending domain has not been verified. Please complete domain verification.",
  "domain": "yourdomain.com",
  "verificationStatus": "pending",
  "requestId": "req_klm789"
}

ATTACHMENT_TOO_LARGE (413)

{
  "error": "Attachment too large",
  "code": "ATTACHMENT_TOO_LARGE",
  "message": "The total attachment size exceeds the maximum allowed.",
  "maxSize": "25MB",
  "actualSize": "32MB",
  "requestId": "req_nop012"
}

TEMPLATE_NOT_FOUND (404)

{
  "error": "Template not found",
  "code": "TEMPLATE_NOT_FOUND",
  "message": "The specified email template does not exist.",
  "templateId": "tmpl_welcome",
  "requestId": "req_qrs345"
}

Billing Errors

PAYMENT_REQUIRED (402)

{
  "error": "Payment required",
  "code": "PAYMENT_REQUIRED",
  "message": "A valid payment method is required to perform this action.",
  "requestId": "req_tuv678"
}

SUBSCRIPTION_EXPIRED (403)

{
  "error": "Subscription expired",
  "code": "SUBSCRIPTION_EXPIRED",
  "message": "Your subscription has expired. Please renew to continue.",
  "expiredAt": "2024-01-15T00:00:00Z",
  "requestId": "req_wxy901"
}

INSUFFICIENT_CREDITS (402)

{
  "error": "Insufficient credits",
  "code": "INSUFFICIENT_CREDITS",
  "message": "You do not have enough credits to complete this operation.",
  "required": 100,
  "available": 45,
  "requestId": "req_zab234"
}

Webhook Errors

INVALID_SIGNATURE (401)

{
  "error": "Invalid signature",
  "code": "INVALID_SIGNATURE",
  "message": "The webhook signature could not be verified.",
  "requestId": "req_cde567"
}

WEBHOOK_TIMEOUT (504)

{
  "error": "Webhook timeout",
  "code": "WEBHOOK_TIMEOUT",
  "message": "The webhook endpoint did not respond in time.",
  "timeout": "30s",
  "requestId": "req_fgh890"
}

Error Handling Examples

TypeScript

interface ApiError {
  error: string;
  code: string;
  message: string;
  details?: Array<{ field: string; message: string }>;
  requestId: string;
}

async function handleApiError(response: Response): Promise<never> {
  const error: ApiError = await response.json();
  
  switch (error.code) {
    case 'RATE_LIMIT_EXCEEDED':
      const retryAfter = response.headers.get('X-RateLimit-Retry-After');
      throw new RateLimitError(error.message, parseInt(retryAfter || '60'));
      
    case 'UNAUTHORIZED':
      throw new AuthError(error.message);
      
    case 'VALIDATION_ERROR':
      throw new ValidationError(error.message, error.details);
      
    default:
      throw new ApiError(error.message, error.code, error.requestId);
  }
}

Python

import requests
from requests.exceptions import HTTPError

class ApiException(Exception):
    def __init__(self, error_data):
        self.code = error_data.get('code')
        self.message = error_data.get('message')
        self.request_id = error_data.get('requestId')
        super().__init__(self.message)

def handle_api_error(response: requests.Response):
    try:
        error_data = response.json()
    except ValueError:
        error_data = {'code': 'UNKNOWN', 'message': response.text}
    
    if response.status_code == 429:
        retry_after = int(response.headers.get('X-RateLimit-Retry-After', 60))
        raise RateLimitError(error_data, retry_after)
    
    raise ApiException(error_data)

cURL Example

# Example error response
curl -X POST https://api.yourapp.com/api/email/send \
  -H "Authorization: Bearer invalid_token" \
  -H "Content-Type: application/json" \
  -d '{"to": "test@example.com"}'

# Response:
# HTTP/1.1 401 Unauthorized
# {
#   "error": "Unauthorized",
#   "code": "UNAUTHORIZED",
#   "message": "Invalid or expired token",
#   "requestId": "req_abc123"
# }

Error Code Reference Table

CodeHTTP StatusCategoryDescription
UNAUTHORIZED401AuthInvalid or missing credentials
FORBIDDEN403AuthInsufficient permissions
TOKEN_EXPIRED401AuthSession token has expired
NOT_FOUND404ResourceResource does not exist
ALREADY_EXISTS409ResourceDuplicate resource
VALIDATION_ERROR422InputRequest validation failed
RATE_LIMIT_EXCEEDED429LimitToo many requests
QUOTA_EXCEEDED429LimitPlan quota exceeded
INVALID_EMAIL_ADDRESS422EmailMalformed email address
DOMAIN_NOT_VERIFIED403EmailSending domain not verified
ATTACHMENT_TOO_LARGE413EmailAttachment exceeds size limit
PAYMENT_REQUIRED402BillingNo valid payment method
SUBSCRIPTION_EXPIRED403BillingSubscription has lapsed
INVALID_SIGNATURE401WebhookWebhook signature invalid
INTERNAL_ERROR500ServerUnexpected server error

On this page