Get started

Scopes

What each API-key scope unlocks, and how to handle a missing one.

A scope is a permission stamped onto the key when you create it — "this key may search", "this key may read usage". Each key holds its own set, granted independently, so a key that searches fine can still 403 on Record Lookup.

ScopeGrants access to
dsp.search.readPOST /v1/search, POST /v1/similar, all four POST /v1/relationships* routes, all three POST /v1/org-chart* routes, GET /v1/coverage, GET /v1/search/filters/{name}, GET /v1/search/filters/{category}/{name}, GET /v1/sorts/{category}
dsp.entities.readPOST /v1/entities/* (all nine category routes)
dsp.usage.readGET /v1/credits, GET /v1/keys/usage, GET /v1/usage/history, GET /v1/usage/history/{run_id}, GET /v1/usage/metrics, POST /v1/billing/top-up/intents, GET /v1/billing/top-up/intents/{topup_id}
dsp.agents.readGET /v1/agents/runs, GET /v1/agents/runs/{run_id}, GET /v1/agents/runs/{run_id}/results, GET /v1/agents/runs/{run_id}/events
dsp.agents.writePOST /v1/agents/runs and POST /v1/agents/runs/{run_id}/cancel, which need this scope. It also grants every dsp.agents.read route, so a key that starts runs can always read them back

Some routes accept more than one scope. Any one of the listed scopes is enough:

RouteAccepts
POST /v1/feedback, GET /v1/feedback, PUT /v1/feedback/votes, GET /v1/feedback/votesdsp.search.read or dsp.usage.read
All /v1/lists* routes, and POST /v1/search/exportdsp.search.read or dsp.entities.read
POST /v1/members/resolvedsp.search.read or dsp.agents.write

Feedback accepts either scope because anyone who can produce a result or read back a run should be able to report one, and reporting is free. GET /v1/feedback/tags needs no credential at all.

These five scopes are the entire ceiling; no credential of any kind can hold more.

Why relationships and org charts use the search scope

Relationships and org charts share the search scope rather than holding one of their own: they read the same data you are already entitled to, from a neighbouring corpus. They are metered separately — as dsp.relationships, dsp.relationships.ask and dsp.org_chart — because a billing action is what a call is charged as, never a credential you grant.

A missing scope returns a 403. The detail lists every scope the route accepts, any one of which would have been enough:

{
  "status": 403,
  "code": "auth.insufficient_scope",
  "title": "Insufficient scope",
  "detail": "This credential holds none of: dsp.entities.read."
}