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

# Errors and rate limits

> Status codes, the error body, error codes and request limits.

## Error body

Every error from the public API has the same JSON shape:

```json theme={null}
{ "error": "This API key lacks the clients:write scope", "code": "INSUFFICIENT_SCOPE" }
```

**error** `string` *required*

A human-readable message. Log it; don't branch on it, the wording may change.

**code** `string`

A stable machine-readable code, when there is one. Branch on this.

### Validation errors

A request whose path, query or body fails validation gets `400` with a list of the failing parts instead, one entry per part, each with the [Zod issues](https://zod.dev/api#issues) that explain what is wrong:

```json theme={null}
[
  {
    "type": "body",
    "errors": [
      { "code": "too_small", "path": ["name"], "message": "Too small: expected string to have >=1 characters" }
    ]
  }
]
```

Show `path` and `message` to whoever wrote the input; don't parse `message`.

## Status codes

| Status | When | `code` |
| - | - | - |
| `200` / `201` | Success (`201` for creates) | |
| `400` | The path, query or body failed validation (see above) | |
| `401` | Missing, unknown or revoked API key | `INVALID_API_KEY` |
| `403` | The key lacks the operation's scope | `INSUFFICIENT_SCOPE` |
| `403` | The organization is suspended | `ORG_SUSPENDED` |
| `404` | The id does not exist in this organization | |
| `429` | Too many requests | |
| `5xx` | Something went wrong on our side | |

> [!NOTE]
>
> An id that belongs to another organization answers `404`, exactly like one that doesn't exist. Lancer never tells you whether another organization's record exists.

## Rate limits

| Surface | Limit |
| - | - |
| Public API (`/api/v1/*`) | 60 requests per minute per IP |
| MCP server (`/mcp`) | 120 requests per minute per IP |
| Inbound provider webhooks (`/webhooks/*`) | 120 requests per minute per IP |

Responses carry the standard `RateLimit` and `RateLimit-Policy` headers (IETF draft 8), so you can see how much of the window is left. Over the limit you get `429` with `{ "error": "Too many requests" }`.

## Retrying

> [accordion] Safe to retry
>
> `429`, `502`, `503`, `504` and network errors. Back off exponentially (for example 1s, 2s, 4s, with jitter) and give up after a few tries.

> [accordion] Don't retry as-is
>
> `400`, `401`, `403` and `404`. The same request will fail the same way. Fix the input, the key or its scopes first.

> [accordion] Creates are not idempotent
>
> `POST /v1/leads`, `/v1/clients` and `/v1/payment-requests` create a new record on every call. If a create timed out, list recent records (for example `GET /v1/clients?q=…`) before trying again, so you don't make a duplicate.


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