# Limits and errors

## Your plan

Each document Ocost reads counts once against your business's month. Resent bytes and searches count nothing. [Settings › Plan](https://app.ocost.io/settings/plan) shows the month so far. Each `POST /public/v1/files` answer says what is left in `X-Ocost-Documents-Left`.

At the limit, Ocost still stores a file. It answers `not_read` with `reason: "limit"` and `renews_on`. Ocost reads the file by itself once the month renews or the plan grows.

## Rate limits

Each key has a limit a minute for each scope:

| Scope | Calls a minute |
| --- | --- |
| `documents:write` | 120 |
| `documents:read` | 600 |
| `search:read` | 60 |
| `figures:read` | 120 |
| `exports:write` | 10 |

Past a limit, Ocost answers `429 urn:ocost:key:rate` with `Retry-After` in seconds. From one address, 30 wrong keys a minute get `401`, and more get `429`.

All keys from one address share an outer limit: 50 requests a second, bursts to 200, and 100 open at once. Past it, a plain-text `429` with `Retry-After` comes back. Keep to a few requests at once, and spread a batch over its minute.

## Sizes

| What | Limit |
| --- | --- |
| A file | 25 MB, refused before it is read with `413 urn:ocost:file:too_large` |
| A long PDF | Only its first pages are read. `pages_read` says how many. |
| A search | `q` up to 200 characters, `limit` up to 50, `offset` up to 250 |
| An MCP request | 4 MB. Keys with `documents:write` may send a file's base64. Past it, `413`. |

## Errors

Errors are RFC 9457 problems with `Content-Type: application/problem+json`. Branch on `status` and `type`. `detail` is English for your logs and may change.

```json
{
  "type": "urn:ocost:key:scope",
  "title": "Forbidden",
  "status": 403,
  "detail": "This key lacks the scope documents:write.",
  "instance": "/public/v1/files"
}
```

| Type | Status | Meaning |
| --- | --- | --- |
| `urn:ocost:key:invalid` | 401 | No key, or a wrong, revoked or expired one. |
| `urn:ocost:key:scope` | 403 | The key lacks the scope. |
| `urn:ocost:key:rate` | 429 | Too many calls. Wait `Retry-After`. |
| `urn:ocost:file:too_large` | 413 | The file is over 25 MB. |
| `urn:ocost:file:format` | 415 | A format Ocost doesn't read. |
| `urn:ocost:file:reading` | 409 | The file is being read. Delete it later. |
| `urn:ocost:file:kept` | 409 | The same bytes are kept where keys don't see them, such as a person's own upload. Nothing changes. |
| `urn:ocost:file:linked` | 409 | Ocost still needs the file. Delete it in Ocost once nothing does. |
| `about:blank` | 404 | No such file or document, or another business's. |
| `about:blank` | 422 | Invalid fields, each in `errors[]` with its `loc`. |
| `about:blank` | 503 | Try again shortly. |

A file sent without a `Content-Length` header gets `411`.

## Retrying

| Answer | What to do |
| --- | --- |
| `429`, `5xx` | Wait `Retry-After`, or pause 1, 2, 4 seconds and so on, at most a minute. |
| `401` | Stop and tell a person. The key needs replacing. |
| Any other `4xx` | Don't send the same request again. |

Resending a file is safe, because the same bytes are the same file. Deleting again is safe too, and answers `404`.

## Your data

Ocost runs in the EU. Originals, readings and the search index stay until you delete the file or your business is deleted. Documents never train a model.
