Error Codes

Complete reference of HTTP status codes and application error codes returned by the AfroTools API.

Error Response Format

All errors return a consistent JSON structure. The success field is always false, and the error object contains a machine-readable code, a human-readable message, and a link to relevant documentation.

HTTP Status Codes

StatusMeaningDescription
200OKRequest succeeded. Response contains the requested data.
400Bad RequestThe request was malformed or contains invalid parameters.
401UnauthorizedNo API key was provided, or the key is invalid or expired.
403ForbiddenThe API key is valid but lacks permission for this resource (e.g., plan restriction).
404Not FoundThe requested endpoint or resource does not exist.
429Too Many RequestsRate limit exceeded. Check response headers for reset time.
500Internal Server ErrorAn unexpected error occurred on the server. Contact support if persistent.

Application Error Codes

Error CodeHTTP StatusDescription
INVALID_API_KEY 401 The API key provided is not valid. Check for typos or generate a new key from your dashboard.
EXPIRED_API_KEY 401 The API key has expired. Renew your subscription or generate a new key.
RATE_LIMIT_EXCEEDED 429 You have exceeded your plan's rate limit. Wait for the reset window or upgrade your plan.
INVALID_COUNTRY 400 The country code is not a valid ISO 3166-1 alpha-2 code or is not supported.
MISSING_REQUIRED_FIELD 400 A required field is missing from the request body or query parameters.
INVALID_SALARY 400 The salary or amount value is invalid. Must be a positive number.
UNSUPPORTED_REGIME 400 The tax type or regime is not available for the specified country.
ENGINE_ERROR 500 An internal calculation engine error occurred. Contact support with the request ID.
INVALID_JSON 400 The request body is not valid JSON. Check your Content-Type header and body format.
METHOD_NOT_ALLOWED 405 The HTTP method is not supported for this endpoint (e.g., GET on a POST-only endpoint).

Handling Errors

We recommend the following best practices when handling API errors:

  • Always check the success field before processing the response.
  • Use the error.code field for programmatic error handling (switch/case).
  • Display the error.message to end users when appropriate.
  • For 429 errors, implement exponential backoff and check the X-RateLimit-Reset header.
  • For 500 errors, retry with exponential backoff (max 3 retries).
  • Log the full error response including the request_id for debugging.

Troubleshooting

401 Unauthorized

Ensure your API key is included in the x-api-key header. Keys start with afro_live_ or afro_test_. Check that your key has not expired.

429 Rate Limited

Check the X-RateLimit-Remaining and X-RateLimit-Reset response headers. Upgrade your plan or implement caching to reduce calls. See Rate Limits.

400 Bad Request

Read the error.code field for specifics. Ensure all required parameters are present, country codes are 2-letter ISO codes, and amounts are positive numbers.

500 Internal Error

These are rare and automatically reported. If the issue persists, contact support with the request_id from the error response.

Error Response Format
{ "success": false, "error": { "code": "ERROR_CODE", "message": "Human-readable description.", "docs": "https://afrotools.com/docs/api/errors.html" } }

401 — Invalid API Key
{ "success": false, "error": { "code": "INVALID_API_KEY", "message": "The API key provided is not valid.", "docs": "https://afrotools.com/docs/api/authentication.html" } }

400 — Missing Required Field
{ "success": false, "error": { "code": "MISSING_REQUIRED_FIELD", "message": "The 'country' field is required.", "docs": "https://afrotools.com/docs/api/tax/calculate.html" } }

400 — Invalid Country
{ "success": false, "error": { "code": "INVALID_COUNTRY", "message": "Country code 'XX' is not supported.", "docs": "https://afrotools.com/docs/api/tax/countries.html" } }

400 — Invalid JSON
{ "success": false, "error": { "code": "INVALID_JSON", "message": "Request body is not valid JSON. Check Content-Type header.", "docs": "https://afrotools.com/docs/api/errors.html" } }

429 — Rate Limit Exceeded
{ "success": false, "error": { "code": "RATE_LIMIT_EXCEEDED", "message": "Rate limit exceeded. Upgrade your plan or wait until the reset window.", "docs": "https://afrotools.com/docs/api/rate-limits.html" } }

500 — Engine Error
{ "success": false, "error": { "code": "ENGINE_ERROR", "message": "An internal error occurred. Please try again or contact support.", "request_id": "req_7f3a9b2c", "docs": "https://afrotools.com/docs/api/errors.html" } }

Handling Errors (JavaScript)
try { const res = await fetch(url, { headers: { "x-api-key": apiKey } }); const data = await res.json(); if (!data.success) { switch (data.error.code) { case "RATE_LIMIT_EXCEEDED": const retry = res.headers.get("Retry-After"); // Wait and retry... break; case "INVALID_API_KEY": case "EXPIRED_API_KEY": // Re-authenticate... break; default: console.error(data.error.message); } return; } // Use data.data } catch (err) { console.error("Network error:", err); }