> ## Documentation Index
> Fetch the complete documentation index at: https://docs.finowl.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Errors

> Every error code the Finowl API returns, what it means and how to handle it.

Errors use standard HTTP status codes and a consistent JSON body:

```json theme={null}
{ "error": { "code": "invalid_input" } }
```

Build your error handling around `error.code`. Codes are stable and will not change meaning. New codes may be added, so treat unknown codes by their HTTP status.

## Error codes

### Fix the request (4xx, not charged)

| Status | Code | Meaning |
| - | - | - |
| `400` | `invalid_input` | The body is not valid JSON, has an unknown or `null` field, is missing a required field, or a value is out of range. |
| `401` | `unauthorized` | The API key is missing, malformed or revoked. |
| `404` | `not_found` | The endpoint does not exist. Check the path and the `/v1` prefix. |
| `405` | `method_not_allowed` | Use `POST`. |
| `413` | `payload_too_large` | The body is larger than 128 KB. |
| `415` | `json_required` | Set `Content-Type: application/json`. |

### Wait and retry (429)

| Code | Meaning | Charged |
| - | - | - |
| `rate_limited` | More than 60 requests this minute. | No |
| `quota_exceeded` | Not enough credits for this request. | No |
| `provider_rate_limited` | Finowl intelligence is at capacity. | Yes |

Every `429` includes a `Retry-After` header in seconds.

### Something went wrong on our side (5xx)

| Status | Code | Meaning | Charged |
| - | - | - | - |
| `502` | `provider_unavailable` | Finowl intelligence could not complete the lookup. | Yes |
| `503` | `provider_unavailable` | Finowl intelligence is temporarily unavailable. | Yes |
| `503` | `provider_not_configured` | This endpoint is temporarily disabled. | No |
| `503` | `service_unavailable` | Finowl is temporarily unavailable. | Usually no |
| `503` | `accounting_response_unconfirmed` | The lookup ran but Finowl could not confirm the charge. | Treat as yes |
| `504` | `provider_response_unconfirmed` | Finowl intelligence did not answer in time. The lookup may have run. | Yes |

<Note>
  `gender/batch` can also return `502` with a full batch body, when every item failed. Check for a `data` array before treating it as a plain error. See [Predict in batch](/api-reference/gender/batch).
</Note>

## Validation rules that cause `400`

`invalid_input` is deliberately general. These are the most common causes:

* A field name is misspelled or not supported by that endpoint, such as `country` on a breach endpoint.
* A field is `null`. Omit optional fields instead of sending `null`.
* `email` is not a plain address. Display names such as `"Alice <alice@example.com>"` are rejected.
* `country` is not exactly two letters.
* `forceToGenderize: true` is combined with `ai_mode` `off` or `always`.
* A batch has 0 or more than 50 items, a duplicate `id`, an `id` over 100 characters, or an unknown `type`.
* A value is empty after trimming, or longer than the endpoint's maximum.

## Handling errors in code

```javascript theme={null}
async function finowl(path, body) {
  const response = await fetch(`https://api.finowl.co${path}`, {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.FINOWL_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify(body),
    signal: AbortSignal.timeout(40_000),
  });

  const payload = await response.json();
  if (response.ok) return payload;

  const code = payload?.error?.code ?? `http_${response.status}`;
  const retryAfter = Number(response.headers.get("Retry-After")) || undefined;
  throw Object.assign(new Error(code), { status: response.status, code, retryAfter });
}
```

Then decide what to do by code, as described in [Retries](/concepts/retries).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.