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

# Errors

> The Integration API error model (RFC 7807 problem+json) and the full catalog of status codes with their meaning and fix.

When a request fails, the Integration API returns a standard HTTP status code and
an [RFC 7807](https://www.rfc-editor.org/rfc/rfc7807) `application/problem+json`
body:

```json theme={null}
{
  "type": "https://integration.fatorly.com/errors/validation-failed",
  "title": "Validation Failed",
  "status": 422,
  "detail": "2 business-rule violations",
  "instance": "/v1/invoices",
  "traceId": "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01",
  "errors": [
    { "field": "lines[0].vatRate", "message": "VAT rate not permitted for category S" }
  ]
}
```

| Field      | Meaning                                                                                                                     |
| ---------- | --------------------------------------------------------------------------------------------------------------------------- |
| `type`     | **Stable machine-readable identifier.** Branch on this (or on `status`) — never on `title`/`detail` text, which may change. |
| `title`    | Short human-readable summary of the error class.                                                                            |
| `status`   | The HTTP status code, repeated in the body.                                                                                 |
| `detail`   | What went wrong in this specific case *(optional)*.                                                                         |
| `instance` | The request path that produced the error *(optional)*.                                                                      |
| `traceId`  | Correlation id — include it when contacting support *(optional)*.                                                           |
| `errors`   | Field-level validation errors, each with `field` and `message` *(optional)*.                                                |

## Error catalog

All `type` identifiers live under `https://integration.fatorly.com/errors/`:

| Status                        | `type` suffix       | Meaning                                                                                                                                                    | How to fix                                                                                                                          |
| ----------------------------- | ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| **400** Bad Request           | `bad-request`       | Malformed/unparseable JSON, a field that fails validation, or the required `Idempotency-Key` header is missing or too long.                                | Check `detail` and `errors[]`. Add an `Idempotency-Key` header and correct any invalid fields.                                      |
| **401** Unauthorized          | `unauthorized`      | The `X-Api-Key` header is missing or the key is invalid or revoked.                                                                                        | Send a valid key in `X-Api-Key`. If it was revoked, create a new key.                                                               |
| **402** Quota Exceeded        | `quota-exceeded`    | Your monthly document quota has been reached.                                                                                                              | Wait for the quota to reset or upgrade your plan.                                                                                   |
| **403** Forbidden             | `forbidden`         | The key is valid but lacks the scope the endpoint requires (e.g. `invoices:write`).                                                                        | Adjust the key's scopes in Settings → API Keys, or use a key that has the scope.                                                    |
| **404** Not Found             | `not-found`         | The endpoint or referenced resource doesn't exist.                                                                                                         | Verify the URL, the resource id, and that the key's company owns it.                                                                |
| **409** Conflict              | `conflict`          | An `Idempotency-Key` was reused with a **different** body, or the document is in a state that forbids the operation (e.g. cancelling a submitted invoice). | Use a fresh key for a new request, or resolve the document-state conflict.                                                          |
| **422** Validation Failed     | `validation-failed` | The document failed PINT-AE schematron validation.                                                                                                         | Read `errors[]` for the failing rules and correct the invoice data (for example a missing `exemptionReasonCode` on an exempt line). |
| **429** Too Many Requests     | `rate-limited`      | Rate limit exceeded (default 100 requests per 10 seconds per company).                                                                                     | Wait for the number of seconds in the `Retry-After` header, then retry.                                                             |
| **500** Internal Server Error | `internal-error`    | An unexpected platform fault.                                                                                                                              | Retry with backoff; report the `traceId` if it persists.                                                                            |
| **502** Upstream Error        | `upstream-error`    | The gateway could not get a valid response from an upstream service — your request itself was well-formed.                                                 | Retry with backoff.                                                                                                                 |

<Note>
  **400 vs 422.** A **400** means the request itself is malformed — bad JSON, a
  missing header, or a field that doesn't validate. A **422** means the request was
  well-formed but the resulting e-invoice doesn't pass the UAE PINT-AE rules.
</Note>

<Note>
  **500 vs 502.** A **502** means your request was fine but an upstream hop failed —
  safe to retry with backoff. A **500** is an unexpected fault; if it persists,
  contact support with the `traceId`.
</Note>

## Rate limiting

Requests are limited per company. A **429** response carries two headers:

* `Retry-After` — seconds to wait before retrying.
* `X-RateLimit-Remaining` — always `0` on a rejected request.

## Validation and quota

* **`Idempotency-Key`** is mandatory on every `POST` (except
  `…/validate`); omitting it is the most common cause of **400**. See
  [Idempotency](/en/developers/idempotency).
* An `exemptionReasonCode` is **required** on any line whose `taxCategoryCode` is
  `E`; omitting it triggers a validation error.
* A **402** is about your plan, not your request — the request was otherwise
  valid. Retrying won't help until the quota resets.

## Delivery failures after submit

`POST /invoices/{id}/submit` is **asynchronous**: it returns `202` with status
`Pending`, and the PINT-AE validation and Peppol delivery happen in the
background. If either fails, the document's status becomes **`DeliveryFailed`**
— a successful `202` on submit therefore does not guarantee delivery.

* List every failed document with **`GET /invoices/failed`** — each item carries
  a `submissionError` with the reason (a PINT-AE rule failure or a Peppol
  delivery error).
* Or poll a single document with `GET /invoices/{id}` — when its status is
  `DeliveryFailed`, the response includes the same `submissionError`.

To recover: fix the data with `PUT /invoices/{id}`, re-check it with
`POST /invoices/{id}/validate` until it returns `"valid": true`, then submit
again with `POST /invoices/{id}/submit`.

<Note>
  `POST /invoices/{id}/validate` runs the same checks as the background submission
  and persists nothing — call it as often as you like while fixing a document. It
  is the one `POST` that does **not** require an `Idempotency-Key`.
</Note>

## Handling errors in code

* Branch on the `type` URI (or `status`), never on `title`/`detail` text.
* Retry **transient** failures (**429**, **500**, **502**, network errors,
  timeouts) with backoff, and reuse the **same** `Idempotency-Key` on POSTs so
  you never duplicate a document.
* Do **not** blindly retry **400/401/402/403/404/409/422** — these need a fix
  (correct the payload, the key, its scopes, or your plan), not another attempt.
* Log the `traceId` of any unexpected **500**/**502** — support can use it to
  find the exact request in the platform logs.

## Related

* [Authentication](/en/developers/authentication) — fixing 401s and 403s.
* [Idempotency](/en/developers/idempotency) — fixing missing-key 400s and conflict 409s.
