Authentication
Authenticate every data request with an API key.
All data endpoints require an API key. Create and manage keys in the dashboard.
Sending your key
Two equivalent options — pick one:
curl "https://api.extractr.dev/ra/search?q=berlin" \
-H "X-API-Key: ext_live_YOUR_KEY"Key format
Secret keys look like:
ext_live_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0- The
ext_live_prefix is followed by 40 hex characters. - The full secret is returned exactly once, when the key is created. Only a display prefix (e.g.
ext_live_a1b2) is stored — if you lose the secret, create a new key.
Revoking and rotating
Revoke a key any time from the dashboard; it stops working immediately. To rotate without downtime:
- Create a new key.
- Deploy the new key to your services.
- Revoke the old key.
Billing is per account rather than per key, so you can freely create one key per service or environment.
Keep keys server-side
Never ship an API key in client-side code. Anyone with the key can spend your credits. Proxy extractr calls through your backend.
Key scopes
By default a key can call every provider, including ones added after it was created. You can instead restrict a key to named providers — useful when a key goes somewhere you control less tightly, such as an AI agent over MCP or a service that only needs one data source.
Set scopes when creating a key, or edit them later from API Keys → Edit name & access. Changing scopes does not change the secret, so you can tighten a key's reach without redeploying it.
A request from a key whose scopes exclude the provider is rejected with 403 insufficient_scope before any credit is reserved, so it costs nothing:
{
"error": {
"code": "insufficient_scope",
"message": "This API key is not permitted to call the instagram provider."
}
}Scoping is a blast-radius control, not a security boundary between your own services — every key still bills to the same account and shares the same balance.
Rate limits
Every provider enforces a per-key request ceiling, and providers backed by a scarce upstream resource (currently Instagram, eBay and Vinted) set tighter per-key limits plus an account-independent pool cap protecting the shared egress. Normal integrations sit well below these.
Windows are fixed: one minute for the sustained per-key ceiling and for the pool. Keys on a tier with a burst allowance also get a 10-second window of twice the sustained rate, so a poller can catch up after a stall without being able to spend a whole minute's quota in one second.
Reading your limits
Every response that reaches the limiter — successes and errors alike — carries the live numbers for the provider you called, so a client can pace itself from the headers instead of hard-coding ours:
| Header | Meaning |
|---|---|
X-RateLimit-Limit | Your sustained ceiling per minute for this provider. |
X-RateLimit-Remaining | Requests left in the current one-minute window. |
X-RateLimit-Reset | UTC epoch seconds at which that window resets. |
X-RateLimit-Tier | Your key's tier: standard, or firehose. |
X-RateLimit-Burst-Limit / -Remaining / -Reset | The 10-second burst window. Only sent on tiers that have one. |
Exceeding a limit returns 429 rate_limited with a Retry-After header
(seconds until the rejecting window resets) and X-RateLimit-Scope naming which
window said no: key (your sustained ceiling), burst (your 10-second window)
or pool (the provider is at capacity across all customers). A 429 costs no
credits and never touches the upstream.
Tiers
Every key starts on standard — the provider defaults above. firehose is a
tier extractr assigns per key for first-party and partner pipelines that must
never queue: it raises the sustained ceiling on specific providers and adds the
burst window. If you need it, get in touch with
your expected request rate per provider.
Failure modes
| Situation | Status | Code |
|---|---|---|
| No key supplied | 401 | unauthorized |
| Key malformed, revoked or unknown | 401 | invalid_api_key |
| Key not scoped for the provider | 403 | insufficient_scope |
| Too many requests | 429 | rate_limited |
See Errors for the response shape.