Rate limits
Per-key budgets, standard headers, and how to back off.
Rate limits protect the platform and keep one integration’s burst from degrading another’s. Limits are enforced per (organization, API key) with a sliding 60-second window, so a burst at the tail of one minute can’t double-dip into the next.
Policies
Different endpoints carry different budgets, each measured in requests per minute, per API key:
The upload budget is sized around the batch endpoints, which is how a large
batch should move: POST /api/documents/presigned-urls-batch takes 100 files
per call, POST /api/documents/confirm-uploads 250 job ids, and
POST /api/documents/status-batch 200, so a 4,000-document batch is about
sixty requests plus polling. Note that the limit governs API requests, not
document processing throughput. Extraction is asynchronous and queued
independently.
There is also one fence per source IP address: 20,000 requests per five minutes, counted across every key and every user behind that address. Past it the edge answers 403 for up to five minutes, with no rate-limit headers. It sits well above what a few keys and a browser office share on one egress; if your traffic can approach it, give each workload its own key and, where you can, its own address.
Need more? Rate limits are set by SpreadSpace per key. Contact us and we’ll raise the general budget for your integration. They are not self-service.
Response headers
Every response carries standard headers:
Legacy X-RateLimit-Limit / X-RateLimit-Remaining / X-RateLimit-Reset
(epoch-seconds reset) are emitted alongside during a deprecation window.
Prefer the unprefixed names.
When you exceed a limit
You get 429 Too Many Requests with a Retry-After header (seconds) and
the standard error envelope:
A 429 can also come from a usage throttle rather than the per-minute limiter
(for example a workspace-level throttle); those responses carry Retry-After
too, and omit RateLimit-Remaining so a remaining budget is never implied.
Handle 429s by honoring Retry-After, with jitter:
The official SDKs do this for you: they honor Retry-After and retry
automatically.
Design guidance
- Watch
RateLimit-Remainingand throttle proactively instead of reacting to 429s. - Batch where batch endpoints exist:
POST /api/documents/status-batchreplaces N status polls;POST /api/documents/confirm-uploadsreplaces N confirms. - Prefer webhooks to polling for job completion: a
job.completedpush costs you zero budget. - One key per workload (backend, ETL, webhook receiver). Limits are per-key, so isolating workloads means a runaway ETL job can’t starve your production ingest path, and gives each its own telemetry in the dashboard.