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 asX-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.
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.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 When the status is
signed_data, then follow the correlation_id.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 asX-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.
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 isnullfor 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 agrant_revoke intent. Only that grant stops. Other grants, the policy and the funds are untouched.
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.