The numbers
These are per-API-key. Multiple keys for the same partner don’t multiply; we enforce limits per-key and aggregate them at the partner level (so creating 10 keys to bypass the limit doesn’t work).
If you need more, talk to us. We provision dedicated capacity at a higher tier for high-volume integrations — typically banks running large origination workflows.
How rate-limit signaling works
Every response carries three headers:
When you exceed the limit, we return
429 Too Many Requests:
Retry-After header tells you how long to wait before retrying.
Bucket algorithm
We use a token bucket per API key, refilled at the sustained rate. The bucket capacity is the burst limit.- Snapshot reads: bucket capacity 200, refill rate 100/sec → you can burst up to 200 in 5 seconds, then drop to 100/sec sustained.
- Disbursements: bucket capacity 60, refill rate 30/sec → similar logic.
What counts as a request
- ✅ Snapshot fetches.
- ✅ Consent link generation.
- ✅ Disbursement initiation.
- ✅ Webhook subscription management.
- ❌ Webhooks delivered to you (you’re not requesting; we are).
- ❌ Failed auth (401, 403) — these are still rate-limited but at a much lower per-key threshold (10/min) to prevent brute force.
- ❌ Idempotent retries against the same
Idempotency-Key— only the first attempt counts.
Idempotency keys and retries
For write operations (disbursement, webhook subscription management), you can include anIdempotency-Key header. We dedupe on it for 24 hours.
If you retry a request after a 5xx response, including the same Idempotency-Key, we recognise it as a retry and either complete the original request (if it succeeded behind the scenes) or fail-safe (returning the original error if it permanently failed).
Idempotent retries don’t consume additional rate-limit tokens.
When you hit the limit
Three patterns. Pick what fits your architecture. Exponential backoff with jitter. The classic. On 429, waitRetry-After + random(0, 2) seconds, then retry.
What if I need higher limits?
A few options.
Most production partner integrations operate well under 100 RPS on average — the limit is sized to handle peak underwriting load (e.g., 30-50 simultaneous loan applications in a busy hour). If you’re brushing it, that’s usually a sign your access patterns can be optimized (cache snapshots within their freshness window, batch consent generations).
Errors that look like rate limits but aren’t
Sometimes you’ll see 5xx errors from us during a normal-looking traffic pattern. A few common causes:- A OPay upstream call took >10 seconds. We retry on our side; the partner API surface waits up to 30s for the underlying operation before timing out.
- A database read replica is rebalancing. A small window of elevated latency, sometimes a 5xx, never longer than a few seconds.
- Our standing model is recomputing for the user. Snapshot reads against a user whose score is recomputing wait for the recompute. Usually under 100ms, occasionally up to 2s.
Monitoring your own usage
The Partner Portal dashboard shows your per-key request counts, success rate, and rate-limit hits over the last 24h, 7d, 30d. We surface a leading indicator at 80% utilisation: if you’re consistently using >80% of your sustained limit, we’ll send you a heads-up email suggesting you talk to us about higher capacity. You can also query usage via the API:Next
Overview
Back to the Partner hub.
API Reference
Complete REST reference for every Partner API endpoint.