# Errors and limits · DameDoklad docs

> The shape of an error response, status codes, error codes and request limits.

Source: https://damedoklad.cz/en/docs/errors-and-limits/

# Errors and limits

The shape of an error response, status codes, error codes and request limits.

## Error shape

An error always has an HTTP status code and a body with at least these fields:

```json
{
  "statusCode": 404,
  "error": "Not Found",
  "message": "Not found"
}
```

Decide based on `statusCode` and, when present, `code`. The `message` text is for people and can change; many messages are in Czech.

## Status codes

| Status | When | What to do |
| --- | --- | --- |
| `400` | The request failed validation. | Fix the data using the `validation` field. |
| `401` | The API key or token is missing or invalid. | Check the `Authorization` header. |
| `402` | The company’s plan does not include this, code `plan_limit`. | Change the plan in Settings under Subscription. |
| `403` | Not allowed: a read-only key or connection (`insufficient_scope`), or the user’s role. | Use a key with the `full` scope, or ask the company owner for another role. |
| `404` | The object does not exist or belongs to another company. | Check the ID. |
| `405` | You sent something other than `POST` to `/mcp`. | The MCP server is stateless, so use `POST`. |
| `409` | The action does not fit the object’s state, such as issuing an issued invoice. | Load the object’s current state. |
| `429` | You went over a request limit. | Wait as the `retry-after` header says. |
| `5xx` | An error on our side. | Try again later; a `GET` can be repeated right away. |

## Error codes

Where a status alone is not enough, the body has a `code`:

| Code | Status | Meaning |
| --- | --- | --- |
| `insufficient_scope` | `403` | The API key or OAuth connection is read-only. |
| `send_scope_required` | `403` | The key or connection has no permission to send. Full access does not include it. |
| `remote_send_off` | `403` | Sending through the API and MCP is not on in this company. |
| `send_owner_only` | `403` | Only a connection of the company’s owner may send. |
| `remote_send_order_limit`, `remote_send_daily_limit`, `remote_send_filing_limit` | `403` | Over a limit the owner set. The prepared send stays, and a person can confirm it in the app. |
| `remote_send_currency` | `403` | The limits are in crowns, so a person confirms an order in another currency in the app. |
| `remote_send_dashboard_only` | `403` | Turning sending on or raising a limit happens only in the app. |
| `plan_limit` | `402` | The plan lacks a feature, or a limit such as documents a month or users is used up. The body may name the `feature`. |

## Validation errors

When the body or parameters fail validation, you get a `400` with details per field:

```json
{
  "statusCode": 400,
  "error": "Bad Request",
  "message": "Validation failed",
  "validation": {
    "formErrors": [],
    "fieldErrors": { "issueDate": ["Invalid"] }
  }
}
```

## Duplicates

Some conflicts tell you which object they collided with:

```json
{
  "statusCode": 409,
  "error": "Conflict",
  "message": "…",
  "duplicate": true,
  "existingId": "rin_…"
}
```

## MCP errors

The `/mcp` endpoint answers in JSON-RPC. Without a valid token you get a `401` with a `WWW-Authenticate` header and the body `{ "jsonrpc": "2.0", "error": { "code": -32000, "message": "…" }, "id": null }`. When a tool’s underlying operation fails, the tool result is marked as an error and its text holds the HTTP status and body.

## Limits

These limits apply per IP address.

| Operation | Limit |
| --- | --- |
| Sign-up `POST /auth/register` | 10 an hour |
| Resend verification `POST /auth/resend-verification` | 5 an hour |
| Sign-in `POST /auth/login` | 10 a minute |
| Session refresh `POST /auth/refresh` | 300 a minute |
| Password reset and e-mail verification | 6 a minute |
| Password and two-factor changes, account export | 6 a minute |
| Deleting an account | 3 a minute |
| Viewing an invitation / accepting it | 30 / 10 a minute |
| `POST /oauth/register` | 20 an hour |
| `GET /oauth/authorize` | 60 a minute |
| OAuth sign-in and two-factor steps | 10 a minute |
| OAuth consent | 30 a minute |
| `POST /oauth/token`, `POST /oauth/revoke` | 60 a minute |
| Public document links | 120 a minute |

The public `/v1` and `/mcp` have no fixed per-key limit today. Please still call them sensibly: don’t try to overload them, and expect that a limit may be added. Respond to a `429` by waiting as the `retry-after` header says.

A request body can be at most 1 MiB, except for operations that take a file:

| Operation | Body limit |
| --- | --- |
| Importing a file (POHODA XML, XLSX, CSV) | 60 MiB |
| Uploading to the inbox (the file itself up to 25 MB) | 40 MiB |
| Importing a bank statement | 30 MB |
| Uploading a company logo | 4 MiB |

Files travel as base64, so they grow by about a third on the way.
