BunyanBunyanDocs
Public APIs

Document Intelligence Limits

The Document Intelligence API uses three separate allowances: request rate, processing units, and the organization's API-call balance.

Plan Limits

These are the default DI tier values. A deployment can configure different values for its plans.

PlanRequests/minute per API keyUnits/minute per organizationMaximum file size
Free / Default55010 MiB
Basic2040025 MiB
Basic+601,20050 MiB
Pro2004,000100 MiB
Pro+60012,000200 MiB
Enterprise2,00040,000500 MiB

File size means decoded content, not the larger base64 string. One MiB is 1,048,576 bytes. Default DI tiers are configured for these plan families; a plan without a DI tier returns 403 with doc_intel_not_available.

Request and unit allowances refill continuously at their per-minute rate, up to the tier capacity. They do not reset together at the start of a calendar minute. A request must fit both allowances. If either is exhausted, the request is rejected with 429 and neither rate-limit allowance is deducted.

Multiple API keys have separate request-rate allowances but share the organization's unit allowance. Creating another key does not increase the organization's available units.

What Is a Unit?

A unit measures the declared processing cost for rate limiting. Units refill automatically; they are not a purchased balance and are not LLM tokens or API calls.

ComponentUnits
Base parsing1
OCR, when enabled for a file+2
LLM enhancement, when enabled for a file+2
Summarization+1
Structured extraction+1
Agentic task+1
Job-status lookup0.1

Costs are additive:

RequestBasic file: both flags offOCR onlyLLM enhancement onlyBoth enabled
Parse a file1335
Summarize a file2446
Extract from a file2446
Agentic with a file2446

Summarization and extraction with direct text each cost 1 unit. Agentic without a file costs 1 unit. Parsing flags do not add unit costs to requests without a file.

Default file cost

llm_enhanced defaults to true and ocr_enabled defaults to false. Omitting both flags costs 3 units for parsing a file or 4 units for a file-based summarize, extract, or agentic request. Set llm_enhanced: false for the basic-file costs above.

Units are deducted when processing is admitted. They are not refunded if later processing fails. An asynchronous submission pays its operation's unit cost once; the worker does not repeat that debit. Each status poll costs another 0.1 units, including reads of cached results and lookups that later return 404.

API-Call Consumption

The organization's api_calls resource is separate from DI units. After successful DI authentication and access checks, each processing submission costs one API call before processing. Job-status reads do not consume this balance.

ActionAPI calls
Synchronous submission1
Asynchronous submission1
Each job-status poll, including a cached result0
Background execution of an accepted job0 additional
Outgoing webhook delivery0 additional

There are currently no refunds. A processing submission can consume an API call and subsequently fail input validation, operation-scope checks, DI rate admission, or processing. A DI rate-limit rejection therefore deducts no request/unit tokens but may already have consumed an API call. Missing or invalid keys do not reach charging.

An exhausted API-call allowance returns 429 for processing submissions and processing does not start. You can still retrieve existing jobs, subject to authentication, access, and DI rate limits. A charging-service failure returns 500 and also stops processing. Check your organization's usage and plan allowance; waiting for DI units to refill does not replenish the separate API-call balance. Other applicable model or resource usage is metered separately.

File and Processing Limits

LimitBehavior
Synchronous file thresholdFiles up to 5 MiB can run synchronously; larger files automatically queue
Forced asynchronous modeasync: true queues any operation, including text and query-only requests
Synchronous timeout30 seconds by default; a timeout returns 504
Job lifetime24 hours from creation
Completed-result retentionUp to 1 hour after completion, capped by job expiry

Use asynchronous mode for long agentic tasks or processing that may exceed the synchronous timeout. A timed-out synchronous request is not automatically converted into a job; resubmitting creates a new request and charge.

DI currently enforces file size, not a page-count limit.

Response Headers

DI success and error responses include these headers:

HeaderMeaning
Request-IdTrace identifier to include in support requests
X-RateLimit-LimitTier request allowance per minute
X-RateLimit-RemainingWhole request tokens available after the admission decision
X-RateLimit-CostDI units deducted at admission; zero if not admitted
X-RateLimit-ResetEpoch seconds when the request allowance will be full, assuming no further requests
X-RateLimit-ComponentsAdmitted cost breakdown, such as parse=1, llm=2, summarize=1

X-RateLimit-Cost does not report the api_calls debit. A value of zero does not mean the request was free of API-call charges.

Before a rate-limit snapshot is available, X-RateLimit-Remaining and X-RateLimit-Reset are unknown. X-RateLimit-Limit is also unknown until the caller's tier is known. Cost is 0 and components are empty before admission or on a DI rate-limit rejection.

On a DI unit-limit rejection, request headers still describe the request allowance. The error's details includes scope: "units", unit_limit, unit_remaining, and requested_cost to explain the unit shortage.

Handling a 429

For a request-rate or unit-rate rejection, wait for the Retry-After header when supplied, then retry with backoff. The header gives seconds until the request can fit; X-RateLimit-Reset instead describes when the request allowance will be completely full.

Retry-After is not guaranteed for every 429, including an exhausted API-call balance or a request costing more units than the entire tier capacity. Inspect the error message and details. Avoid automatic retry loops that continue spending API calls on the same rejected request.

See errors and troubleshooting for the response envelope and other HTTP statuses.

On this page