Skip to main content
A key holds a set of scopes, and a route refuses any key that does not hold the one it needs. There are seven names in the vocabulary: the umbrella scopes read, write and admin, and the fine-grained scopes graph:write, memory:forget, subjects:provision and usage:read. GET /v1/me returns the scopes a key actually holds. Start there when a call returns 403.

The vocabulary

Satisfaction is transitive down that middle column. A requirement is met by the scope itself or by any scope that satisfies it, so a write key passes a memory:forget check, and a memory:forget key passes a graph:write one.
The three umbrella scopes are not cumulative. write does not satisfy a read requirement, and admin satisfies neither read nor write. They are three separate grants that happen to be named like a ladder.In practice this means you list every umbrella you need. A key minted with ["write"] alone can call POST /v1/ingest and then fail with 403 on GET /v1/ingest/{job_id}/status, because polling is a read route. Mint ["read", "write"] for anything that writes and then checks its work. Sandbox keys are minted ["read", "write"] for exactly this reason.

Three implications worth knowing

This is the point of splitting them. A key with graph:write can edit the knowledge graph, assert relations, supersede beliefs and restore a node someone tombstoned. It cannot forget anything: DELETE /v1/graph/nodes/{node_id} and DELETE /v1/graph/edges/{edge_id} both require memory:forget, and graph:write alone cannot remove structure.That lets you mint a curation key for an agent or an internal tool that is allowed to improve the graph and is structurally incapable of erasing it. A write key holds both, so if you want the separation you have to ask for it explicitly.
The implication runs one way. Anything able to erase a node is also able to edit one, so memory:forget satisfies a graph:write requirement. The reverse is what the previous section rules out. If you want an erase-only credential, there is no such thing: erasure is the strictly wider grant.
GET /v1/usage aggregates every subject’s usage into one billing view, so it is not a read surface. It requires usage:read, which an admin key also qualifies for. A plain read key is refused.POST /v1/exports follows the same posture: an export at scope: "user" needs write, while scope: "org" exports every member’s data and additionally requires admin. GET /v1/team is a read route, because it returns the same fields GET /v1/me already gives you, but enumerating the members with GET /v1/team/members requires admin.

What each route needs

The routes below need more than read. Everything else in /v1 is a read surface, and GET /v1/me needs only a valid key.

Write

Graph mutation and erasure

Node history is read-shaped but sits on the write-managed family, because it reads the mutation record rather than the content.

Admin

GET /v1/subjects and GET /v1/subjects/{subject_id} are read routes. Only provisioning and erasure need subjects:provision.
Signed-in dashboard sessions may mint keys without holding admin. The requirement applies to API keys calling POST /v1/keys, which is what stops a write key from minting itself a way around its own scopes.

Minting a narrower key

POST /v1/keys takes an optional scopes array. Omit it and the new key inherits the caller’s scopes. Name a subset and the new key is narrower. Name a scope the caller does not hold and the mint is a 403, so minting can never escalate.
That key can read, edit the graph and supersede beliefs. It cannot forget a node, provision a subject, mint another key or see org-wide usage. It is the shape most agent integrations should use.

Sandbox keys ignore all of this

A sandbox key is minted with read and write, fixed, not caller-selectable. There is no way to widen or narrow it, because a test credential must never be able to mint keys, provision subjects or erase real data. See Sandbox.

What a refusal looks like

A key that authenticates but lacks the scope gets 403 with permission_denied, not 401. The same status covers a subject selector that was never provisioned, so read the detail before assuming which one you hit.
403 application/problem+json
The code is always the tail of the type URI, so documentationUrl resolves to a real page on this site. See Errors for the full envelope.

Next

Authentication

Headers, minting, revocation, and what a leaked key can and cannot reach.

One memory per end user

Where subjects:provision is the scope you actually need.