Navigation

Error Handling

BillerAPI uses conventional HTTP status codes and structured error responses to indicate the success or failure of API requests.

Error Response Format

All error responses return a JSON body with a consistent structure:

Error response
JSON
{
  "status_code": 400,
  "error": "validation_error",
  "message": "The 'biller_id' field is required.",
  "documentation_url": "https://docs.billerapi.com/concepts/errors"
}
status_codeThe HTTP status code of the response.
errorA machine-readable error code (see table below).
messageA human-readable description of the problem.
documentation_urlA link to relevant documentation for this error type.

HTTP Status Codes

CodeMeaningDescription
200OKRequest succeeded.
201CreatedResource was created successfully.
202AcceptedRequest accepted for async processing (e.g., bill sync).
400Bad RequestInvalid request body or parameters.
401UnauthorizedMissing or invalid authentication credentials.
403ForbiddenValid credentials but insufficient permissions.
404Not FoundThe requested resource does not exist.
429Too Many RequestsRate limit exceeded. See Retry-After header.
500Internal Server ErrorSomething went wrong on our end. Contact support if persistent.

Error Codes

The error field contains one of these machine-readable codes:

Error CodeHTTP StatusDescription
validation_error400Request body or query params failed validation.
authentication_error401Invalid or missing API credentials.
authorization_error403Authenticated but not authorized for this resource.
not_found404The resource does not exist or is not accessible.
rate_limit_exceeded429Too many requests. Retry after the indicated period.
internal_error500An unexpected error occurred on the server.

Handling Errors

Always check the HTTP status code and parse the error response body for details.

Error handling
try {
  const response = await fetch('https://sandbox.api.billerapi.com/billers', {
    headers: {
      'X-Client-ID': process.env.BILLERAPI_CLIENT_ID,
      'X-Client-Secret': process.env.BILLERAPI_CLIENT_SECRET,
    },
  });

  if (!response.ok) {
    const error = await response.json();
    console.error(`[${error.status_code}] ${error.error}: ${error.message}`);

    if (error.error === 'rate_limit_exceeded') {
      const retryAfter = response.headers.get('Retry-After');
      console.log(`Retry after ${retryAfter} seconds`);
    }
    return;
  }

  const data = await response.json();
  console.log(data);
} catch (err) {
  console.error('Network error:', err.message);
}

Related