# Errors

Every error response from the Lazy Embedded API has the same JSON shape, the error envelope.

## The error envelope

```json
{
  "error": {
    "code": "validation_error",
    "message": "limit must be at most 100",
    "param": "limit",
    "request_id": "q8Zr1Ndk2vLp0Xw7HcYt3Rb9Fs6Mj4Ge5Ua1Ki8Oy2Wn0Tz7Ql3Px=="
  }
}
```

| Field        | Type           | Description                                                                                                       |
| ------------ | -------------- | ----------------------------------------------------------------------------------------------------------------- |
| `code`       | string         | Machine-readable error code from the table below. Stable within `/v1`.                                            |
| `message`    | string         | Human-readable explanation, for your logs. Do not parse it.                                                       |
| `request_id` | string or null | The ID of this request. Quote it when you contact Lazy. Null only on [rate limit](https://developers.lazyinvoice.co.il/embedded/rate-limits/) errors. |
| `param`      | string         | The body field or query parameter at fault. Present only on some `validation_error` responses.                    |
| `biz_id`     | string         | The existing business that caused a `business_exists` conflict. Present only on that error.                       |

## Error codes

| Status | Code                 | Cause                                                                                                                                                                           | What to do                                                                                            |
| ------ | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
| 400    | `validation_error`   | A body field or query parameter is missing, empty, mistyped, out of range or unknown; the body is not valid JSON or not a JSON object; or the request contains a NUL character. | Fix the request. `param` names the field when the error is about one field. Do not retry unchanged.   |
| 401    | `unauthorized`       | The API key is missing, malformed or not recognized.                                                                                                                            | Check the `Authorization` header. See [Authentication](https://developers.lazyinvoice.co.il/embedded/authentication/).                    |
| 403    | `forbidden`          | Your platform is not allowed to make this request.                                                                                                                              | Contact Lazy with the `request_id`.                                                                   |
| 404    | `not_found`          | No business with this `biz_id` belongs to your platform, or the path does not exist.                                                                                            | Check the `biz_id` and the path. A deleted business stays not found.                                  |
| 409    | `business_exists`    | Another business of your platform already has this `external_id`.                                                                                                               | Use the business named by the error's `biz_id`, or choose another `external_id`.                      |
| 409    | `billing_not_ready`  | Your platform's billing is not set up yet.                                                                                                                                      | Contact Lazy.                                                                                         |
| 409    | `business_not_ready` | The business's creation did not finish.                                                                                                                                         | Repeat [Create a business](https://developers.lazyinvoice.co.il/embedded/api/businesses/create/) with the same `external_id`, then retry. |
| 429    | `rate_limited`       | You sent too many requests.                                                                                                                                                     | Wait, then retry, as [Rate limits](https://developers.lazyinvoice.co.il/embedded/rate-limits/) describes.                                 |
| 500    | `internal_error`     | Lazy failed to handle the request.                                                                                                                                              | Retry as described in [Retries and idempotency](https://developers.lazyinvoice.co.il/embedded/retries/).                                  |

Each endpoint's page lists the errors that endpoint can return and their causes there.

Lazy may add error codes and envelope fields within `/v1`. The
[compatibility policy](https://developers.lazyinvoice.co.il/embedded/compatibility/) says how to handle ones you do not know.

## Validation errors

A `validation_error` reports one problem at a time: the first one Lazy finds. Fix it and send the
request again to see the next one.

Lazy checks a request in two stages, with the API key in between:

1. Before the key: the body is valid JSON and a JSON object, every body field has the right type
   and range, no body field is unknown, and `limit` is in range. A request with no key that fails
   one of these checks gets `400 validation_error`, not `401 unauthorized`.
2. After the key: the checks that need the value itself, such as an empty `name`, an unknown query
   parameter or an unreadable `cursor`.

So when both the body and the query string are invalid, the error names the body field.

The `message` of a field error starts with the field's name, such as `units must be at least 1` or
`nickname is not a known field`. The same name is in `param`.

## Errors from outside the API

A response with status 502, 503 or 504 comes from the network in front of the API, not from the API
itself. Its body is not an error envelope. Treat it like a request whose response you never got:
see [Retries and idempotency](https://developers.lazyinvoice.co.il/embedded/retries/).
