Limits¶
Every ceiling a caller can meet, the code it answers with, and whether it moves.
The figures below are the defaults a deployment ships with. Several are configurable by whoever runs the service. The right number depends on how much recognition capacity sits behind it, which is not a property of the contract. The ones that are not configurable say so.
The rate limits¶
| Caller | Limit | Window | Keyed by |
|---|---|---|---|
sk_sandbox_public |
10 requests | 1 hour | The client's IP address |
| A registered key | 60 requests | 1 minute | The key |
The two tiers are different animals. The public sandbox key is unregistered and shared by everyone, so its bucket is per address and its window is long. It exists to keep one visitor from consuming the demo for the rest. A registered key is metered by its own balance, so its limit only keeps a runaway client from flooding the service.
Over either, the answer is 429
rate_limited.
The sandbox bucket is keyed by address, not by key. Everyone shares one credential there, so counting per key would count everybody as one caller.
The free allowances¶
Two separate allowances govern the public sandbox key, and both apply.
| Allowance | Figure | Answered with |
|---|---|---|
| Lifetime free recognitions, per anonymous client | 10 | 403 registration_required |
| The same image, on the free sandbox | 5 submissions per hour | 429 document_repeated |
The repeat guard keeps only a digest of the image bytes, and only for the window — neither the image nor a durable record of it. It runs before the engine, so a refused repeat costs neither recognition time nor one of the free attempts.
A registered account arrives with 20 free documents credited to its balance, and neither of these two walls applies to its keys.
Sizes¶
| Limit | Figure | Answered with |
|---|---|---|
| Request body | 36 MiB | 413 payload_too_large |
| Image, on either web surface | 25 MiB | Refused in the browser, before any request |
reference |
128 characters | 422 validation_failed |
Idempotency-Key |
1 to 255 characters | 422 validation_failed |
The body ceiling is derived, not chosen. The largest image either web surface accepts is 25 MiB; base64 makes that about 33.4 MiB, and the rest is the JSON envelope. It is sized for the worst case on purpose. Normally the browser re-encodes the photograph first and the body is a few hundred kilobytes. A browser that cannot decode the image sends the original bytes, and a direct API caller sends whatever it likes.
The ceiling is enforced before the body is read into memory. An oversized request costs nothing and reaches no engine.
Retention¶
| Limit | Figure |
|---|---|
retain_hours |
0 to 8760, one year |
| The windows the dashboard offers for the account setting | 24 hours, 7 days, 1 month, 1 year |
| A new account's setting | 1 year |
A value outside the range is 422
validation_failed. The API accepts any integer
inside it, so a window the dashboard does not offer is still a valid
retain_hours.
0 is not a short window. It writes no row at all, so nothing exists that a
later read could find.
Result images¶
| Slot | Height cap |
|---|---|
document_crop |
250 px |
| Every other slot | 100 px |
Scaled by height, proportionally, and never upwards. A crop already inside its cap is published at the size the recognition produced it. The rest of what the re-encode does is on result images.
A retained scan keeps a thumbnail of at most 96 px and 16 KiB, readable in the dashboard rather than through this API.
Time¶
| Limit | Figure | What happens past it |
|---|---|---|
| The recognition engine's deadline | 15 s | 503 engine_unavailable; nothing is charged |
| The wait for an in-flight idempotent request | 2 s | 409 idempotency_in_progress |
| The age at which an unfinished idempotency claim is reclaimable | 10 minutes | The next caller takes the key over |
The engine deadline is far longer than a recognition takes, which is about a second. It exists so a request cannot hang on an engine that has stopped answering.
What is not limited¶
- The number of scans an account may make. The balance is the limit, and it is the caller's own.
- The number of API keys, beyond a per-account ceiling the dashboard enforces.
- Concurrency. Nothing caps parallel requests beyond the rate limit above.
- Reads.
GET /v1/scans/{id}andGET /v1/usageare never billed, and are bounded only by the rate limit for the key.
Which limits move¶
| Limit | Configurable |
|---|---|
| Both rate limits, and their windows | Yes, per deployment |
| The free-recognition allowance | Yes |
| The repeat-document threshold and window | Yes |
| The request body ceiling | Yes |
| The engine deadline and the idempotency waits | Yes |
retain_hours' range, reference's length, the key's length |
No — they are the contract |
| The image height caps | No |
A deployment that changes a configurable figure changes what its own API
answers. The figures on this page are the ones api.doc.cheap runs.