Error Codes

When an API request fails, the response includes an error code and message to help you understand and handle the issue.

Error Response Format

All error responses follow this structure (request_id is included when available — quote it when contacting support):

{
  "success": false,
  "error": {
    "code": "ERROR_CODE",
    "message": "Human-readable error description",
    "request_id": "abc123..."
  }
}

Error Code Reference

CodeHTTPDescription
BAD_REQUEST400Invalid request parameters, malformed JSON, or missing required fields (details in the message)
INVALID_WEBHOOK_SECRET400webhook_secret is empty, longer than 256 characters, or supplied without webhook_url
WEBHOOK_URL_INVALID400Webhook URL is malformed, not HTTPS, or targets a private/reserved address
UNAUTHORIZED401Missing or invalid API key
INSUFFICIENT_CREDITS402Not enough credits for this operation
PAYMENT_REQUIRED402A paid plan or payment is required for this operation
FORBIDDEN403API key does not have permission to access this resource
PLAN_LIMIT_EXCEEDED403Your plan’s limit for this feature has been reached (e.g. connected integrations)
NOT_FOUND404Resource not found (e.g. unknown job ID or expired uploaded file)
METHOD_NOT_ALLOWED405HTTP method not supported on this endpoint
CONFLICT409Request conflicts with the current state of the resource
BATCH_SIZE_EXCEEDED413Batch or file exceeds your plan’s per-batch email cap
RATE_LIMITED429Too many requests — check the Retry-After header when present
INTERNAL_ERROR500Unexpected server error
SERVICE_UNAVAILABLE503Service temporarily unavailable
WEBHOOK_DNS_TEMPORARY_FAILURE503Webhook URL hostname could not be resolved (transient DNS failure) — safe to retry
INTEGRATION_NOT_CONFIGURED503The requested integration provider is not configured/available yet
GATEWAY_TIMEOUT504Upstream verification timed out — retry or poll the job

Handling Errors

4xx Client Errors

These errors indicate a problem with the request. Check the error message, fix the issue, and retry.

429 Rate Limited

Retry timing is communicated via the Retry-After response header (there is no retry_after field in the JSON body). Auth endpoints (login, registration, password reset) and per-key API throttling set it — wait that long, then retry. Other 429s come from a shared platform throttle that may omit the header; back off with exponential, jittered delays.

5xx Server Errors

These are server-side issues. Retry with exponential backoff. If the problem persists, contact support.

Example: Error Handling in Node.js

async function verifyEmail(email) {
  try {
    const response = await fetch('https://api.kawaa.com/v1/verify', {
      method: 'POST',
      headers: {
        'X-Api-Key': process.env.KAWAA_API_KEY,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ email }),
    });

    const data = await response.json();

    if (!data.success) {
      switch (data.error.code) {
        case 'RATE_LIMITED': {
          // Retry timing arrives in the Retry-After response HEADER (not the
          // JSON body). It may be absent on shared-throttle 429s — back off.
          const retryAfter = Number(response.headers.get('retry-after')) || 60;
          await sleep(retryAfter * 1000);
          return verifyEmail(email);
        }

        case 'INSUFFICIENT_CREDITS':
          // Handle billing issue
          throw new Error('Please add credits to continue');

        case 'BAD_REQUEST':
          // e.g. malformed email input — skip it
          return { status: 'skipped', reason: data.error.message };

        default:
          throw new Error(data.error.message);
      }
    }

    return data.data;
  } catch (error) {
    console.error('Verification failed:', error);
    throw error;
  }
}

Need Help?

If you're experiencing persistent errors, check our status page for any ongoing issues, or contact support.