Limits
GET /v1/access shows the request limits and Redact's text limits that apply to your key. Text limits and offsets count UTF-16 code units, as string length does in JavaScript and .NET.
Request limits
Every call counts against several per-minute limits at once. The first one reached answers 429 rate_limited with Retry-After, the seconds to wait, at most 60.
| Limit | Calls per minute | Shared by |
|---|---|---|
| Person | Set by komplai for each tool in your organisation, at most 120. GET /v1/access shows it in services[].limits.requests_per_minute. | All of a person's personal API keys and their use of the hub, across tools |
| Integration | Set by komplai for Redact in your organisation | All keys of one organisation integration, also after komplai issues a new key |
| Organisation | 120 | Everyone in the organisation, people and integrations, in the API and in the apps |
| API | 300 | Every organisation, in the API and in the apps |
| IP address | 300 for calls with a komplai key, 60 for other requests | All calls from one IP address |
A 429 from the per-IP limit also carries x-ratelimit-limit, x-ratelimit-remaining and x-ratelimit-reset, which describe that limit. A second key does not give you more calls: your keys share your limit.
What counts:
- GET /v1/access counts as one call.
- Each read of a text job's status or result counts. Wait at least 2 seconds between reads.
- DELETE /v1/redact/jobs/{id} counts only against the per-IP limit.
- POST /v1/decide/batch counts as one call for up to 100 texts.
- GET /v1/openapi.json needs no key and counts only against the per-IP limit.
Some work runs without a queue, so when every slot is busy, the call answers 429 processing_capacity_busy with Retry-After: each API process runs your organisation's redaction rules in at most two workers and reads at most two PDF or Word files at a time. The language model on local infrastructure has a shared queue; when it is full, a synchronous call answers 503 model_busy, while a text job waits for its turn.
AI spending
A call that runs a model in komplai's EU cloud is metered at the provider's price and counts towards:
- your organisation's monthly AI spending cap, agreed with komplai;
- your organisation's own limit, when its administrator has set one below the cap;
- your personal limit, when the administrator has set one. It applies to personal API keys only; an organisation integration key has none.
When the lowest of these is reached, calls in EU cloud answer 429 ai_credit_exhausted or person_ai_credit_exhausted. Waiting does not help: the monthly cap starts again next month. The API never moves a call to local infrastructure by itself; choose local processing in the request.
Local infrastructure has no AI charge. Your organisation's own AI connections are paid to the provider directly and do not count towards the cap. Your organisation's administrator sees the cap and sets the organisation's own limit and personal limits under Organisation › AI usage › Limits. You see your own usage under APIs and integrations › Usage.
Size limits
| Operation | Limits |
|---|---|
| POST /v1/redact/detect | Text: 16,000 UTF-16 code units. Body: 100,000 bytes. |
| POST /v1/redact | Text: 750,000 UTF-16 code units, or 2,000,000 with Prefer: respond-async. |
| POST /v1/redact/jobs | Text: 2,000,000 UTF-16 code units, about 800 standard pages of 2,400 characters. |
| POST /v1/redact/restore | Text: 750,000 UTF-16 code units. The list of labels (mapping): 100,000 entries, 2,000,000 UTF-16 code units and 500 fixed labels. The text with the originals put back: 8,000,000 UTF-16 code units. |
| POST /v1/redact/file Beta | File: 50 MiB decoded and 2,000 PDF pages. File name: 255 characters. Extracted text: 750,000 UTF-16 code units. |
| POST /v1/redact/file/jobs Beta | As POST /v1/redact/file, with up to 2,000,000 UTF-16 code units of extracted text. |
| Every Redact result | 32 MiB. |
| POST /v1/chat/completions | 32 messages and 80,000 UTF-16 code units of content. Body: 400,000 bytes. max_tokens: at most 32,768 and the model's max_output_tokens. response_format: 32,768 bytes, with a schema at most 24 levels deep and 2,048 values. |
| POST /v1/decide Beta | 80,000 characters as JSON. Body: 320,000 bytes. 64 questions, each with up to 32 criteria. |
| POST /v1/decide/batch Beta | 100 texts. 200,000 characters as JSON. Body: 800,000 bytes. |
| POST /v1/coding/chat/completions Beta | Body: 2,000,000 bytes and 2,000,000 characters as JSON. 512 messages and 64 tools. max_tokens or max_completion_tokens: at most 32,000. |
Single fields have their own bounds, such as at most three values in detectors or four strings in stop. Each operation's page in the API reference lists them.
Redact also bounds the work a text may need: candidate matches, matched characters and coreference matching grow with the text's length, and your organisation's rules have a time limit that grows with the text and the number of rules. A text beyond them answers 413 processing_complexity_exceeded. The bounds are in text_contract.complexity_limits in GET /v1/access. Because they grow with the text, splitting it rarely helps.
Timeouts
| Call | Limit | When it is reached |
|---|---|---|
| POST /v1/redact, POST /v1/redact/file | 300 seconds | A run komplai estimates cannot finish in time is refused before anything runs, with 413 use_job. A run that still reaches the limit ends with 504 processing_timeout. |
| Reading a PDF or Word file | 120 seconds | 413 file_too_complex |
| POST /v1/chat/completions | 120 seconds for the model to answer | 504 timeout |
| POST /v1/decide, POST /v1/decide/batch | 30 seconds | 502 service_unavailable |
| POST /v1/coding/chat/completions | 600 seconds for the whole answer | 504 timeout, or an error event with timeout once the stream has begun |
| Text jobs | No limit while the job makes progress | After 65 minutes without progress, the job ends with redact_job_stalled. After three interruptions, it ends with redact_job_attempts_exhausted. |
Give your HTTP client a timeout a little longer than the call's limit, so you get komplai's answer instead of your own timeout. For long texts, use a text job or Prefer: respond-async rather than a longer wait.
A text job and its encrypted result are kept until you delete the job or until its expiresAt. The retention period counts from when the job ends.