A grant says who may act for an agent: your backend creates a token (ngt_…), the owner signs for it once, and your backend sends it on every agent action. What a grantee may do is the agent’s policy, the same for every grant.
At a glance
  • Token: ngt_ plus 32 random bytes in base64url, created by your backend and sent as X-Grant-Token. The API never sees it at issue time and never returns it.
  • Commitment: the SHA-256 hex of the token. The only part the owner signs and the API stores.
  • Signatures: one owner signature to issue a grant, one to revoke it.
  • Label and expiry: 1–64 characters shown to the owner and on every action; expiry at most 365 days ahead.
  • Limit: 50 live grants per agent. Use one per user session, assistant or bot, so you can stop one without touching the others.
A grant token works like a password for spending within the policy. Store it encrypted on your backend. Never put it in a browser, a mobile app or a model prompt.

Issue a grant

1

Create the token and its commitment

Your backend makes a fresh token for every grant. Never reuse a token: the API refuses a commitment that already backs another grant (grant_credential_reused).
2

Generate a grant_issue intent

label, credential (the commitment) and expires_at are the grant. The agent must be ACTIVE.
The response carries intent: { standard, payload }, a preview and the expires_at of the signing window.
3

The owner signs intent.payload unchanged

Your frontend has the owner’s wallet sign intent.payload with the standard in intent.standard. See Owner Signing.
4

Submit and wait

Send the wallet’s output back as signed_data, then follow the correlation_id.
When the status is SUCCESS, details.grant holds the new grant, including its grant_id. Save the grant_id with the token: you need it to revoke the grant.

Use a grant

Send the token as X-Grant-Token on the calls that act under a grant: swap, withdraw, transfer, shield, unshield, recover and the native/… routes. Every call also sends your partner API key.
Deposit addresses and swap quotes (swap with dry: true) need only the API key. A withdrawal preview runs under the grant, like the withdrawal. See Executions for each action.
  • Every status carries grant: { id, label }, the grant that authorized it. It is null for owner-signed work and for deposit addresses.
  • Idempotency keys are scoped to the grant. The same key under two grants is two separate actions.
  • A new partner API key keeps using existing grant tokens. Revoking an API key stops work that was sent through that key and has not reached its dispatch commitment.
  • Changing the policy never needs a new grant. Issuing or revoking a grant never changes a rule.

When a grant stops working

An expired grant is not renewed. Issue a new one with a new token.

List grants

GET /v1/agents/{agent_id}/grants returns every grant, including revoked and expired ones, newest first.

Revoke a grant

The owner revokes one grant with a grant_revoke intent. Only that grant stops. Other grants, the policy and the funds are untouched.
Sign and submit it like any owner intent. When the status is SUCCESS, details reports: Anything that had not reached its dispatch commitment is refused: new calls with the token fail with agent_grant_required, and an action still waiting for its timelock fails with authorization_stale when it comes due. To stop a queued action while keeping the grant, the owner cancels it with an execution_cancel intent.
Lost a token? It cannot be recovered. Issue a new grant with a new token and revoke the old one.

Limits and errors

The full list of codes is in Status & Errors.