extractr docs

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:

  1. Create a new key.
  2. Deploy the new key to your services.
  3. 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) set tighter limits plus an account-independent cap protecting the shared pool. Normal integrations sit well below these.

Exceeding a limit returns 429 rate_limited with a Retry-After header, and costs no credits. X-RateLimit-Limit and X-RateLimit-Remaining accompany the rejection.

Failure modes

SituationStatusCode
No key supplied401unauthorized
Key malformed, revoked or unknown401invalid_api_key
Key not scoped for the provider403insufficient_scope
Too many requests429rate_limited

See Errors for the response shape.

On this page