# Errors

> Every status and error code, what is charged, and what to retry.

Section: Guides
Source: https://statementbear.com/docs/errors
Product: StatementBear statement parsing API, $0.49 per document, 25 free.

---

Errors come back in one envelope with a stable `code`. Branch on the code: messages get reworded, codes do not.

## The envelope

```json
{
  "error": {
    "code": "not_a_bank_statement",
    "message": "This document does not look like a bank or card statement.",
    "documentId": "doc_5f2a9c4b1e77d0a3c8b6e412"
  }
}
```

`documentId` is present whenever we got far enough to allocate one. Quote it in a support question. Some errors carry extra fields, such as `reason` on a `409`.

## Every code

| Status | Code | Description |
| --- | --- | --- |
| 400 | `empty_body` | No PDF arrived. Returned as missing_file when a multipart request has no file part. |
| 401 | `missing_key` | No Authorization header on the request. Check that your client is sending the header. It is a separate code from invalid_key so the two cases are easy to tell apart in a log. |
| 401 | `invalid_key` | The key is unknown or has been revoked. Revoking a key in the console applies to the next request. Check the value before assuming the key was revoked: a typo returns the same code. |
| 402 | `trial_exhausted` | The free allowance is spent and no card is on file. Add a payment method in the console and the same key keeps working. Nothing needs redeploying. |
| 402 | `monthly_cap_reached` | Your monthly document ceiling was hit. There is nothing to buy. Tell us your volume and we raise it. |
| 402 | `canceled` | Billing for this account was cancelled. Contact us to reactivate. Keys are kept, so nothing needs reissuing. |
| 405 | `method_not_allowed` | Only POST. The response carries an Allow header. GET, HEAD, PUT, PATCH and DELETE all land here. |
| 409 | `idempotency_key_not_replayable` | The key succeeded but its stored response is gone. It expired after 24 hours or was too large to store; the reason field says which. Retry with a new key if you want the document parsed again. |
| 413 | `file_too_large` | Over 20MB. Refused as soon as the size is known. Split the statement or export a smaller range. |
| 415 | `not_a_pdf` | The body is not a PDF. Decided from the file itself rather than the content type you declare, so a mislabelled file fails immediately. |
| 415 | `unsupported_media_type` | Neither an application/pdf body nor a multipart file part. Send the PDF as a raw body with Content-Type: application/pdf, or as multipart/form-data with a part named file. |
| 422 | `not_a_bank_statement` | Readable, but not a statement. A payslip, a receipt, an invoice or a scan with no text layer. Usually the right thing to show whoever uploaded the file. |
| 429 | `too_many_concurrent_requests` | More than 4 documents in flight at once. A limit on documents in flight at once. There is no per-minute limit. Wait a couple of seconds and retry with the same idempotency key. |
| 500 | `parse_failed` | Our error. Nothing is charged and no allowance is spent. Retry with the same key; if the same file fails three times, send us the documentId. |

## What is charged

Only a `200` is billable. Every error is free and none of them count against your monthly cap. `X-Billable-Documents` is on every response.

## What to retry

| Status | Retry | How |
| --- | --- | --- |
| `429` | Yes | Four documents are already in flight. Wait a couple of seconds and retry with the same idempotency key. |
| `500` | Yes | Retry with the same key and exponential backoff. If the same file fails three times, send us the `documentId`. |
| `402` | After a change | Add a payment method, or ask us to raise the cap. Until then the answer stays the same. |
| `400`, `401`, `405`, `413`, `415`, `422` | No | The request or the file is the problem. Fix it and send again. |
| `409` | No | The call already succeeded. Use a new idempotency key only if you want the document parsed and charged again. |

> **422 is validation**
>
> `not_a_bank_statement` means the file was readable and is not a statement: a payslip, an invoice, a screenshot or a scan. It is free, and it is usually what to show whoever uploaded the file.

---

All documentation: https://statementbear.com/docs/llms.txt
Questions: api@statementbear.com
