The owner doesn’t sign agent actions. A spending action carries three things instead: your partner API key (X-API-Key), the grant token (X-Grant-Token) and an Idempotency-Key. Each action returns a correlation_id. You follow it with GET /v1/status until it settles. Two things don’t need a grant: creating a deposit address, and swap quotes (dry: true).

Prerequisites

  • An ACTIVE agent with a live policy from Create an Agent, saved as AGENT_ID.
  • A grant token from Issue a Grant, saved as GRANT_TOKEN.
  • About 10 USDC on Base to send.
Every snippet below assumes this setup:
execute.ts
1

Fund the agent

Ask for a one-time deposit address. This needs only your API key and an Idempotency-Key: no grant, no owner signature, and no policy destination, budget or delay applies. Funds are credited to the agent’s own account. In this example, the agent receives 10 USDC from Base.origin_asset is the exact asset_id of the token you send, which fixes both the chain and the token. amount is optional. Without it, the address credits any payment at or above details.min_amount until details.expires_at.
The status is PENDING_DEPOSIT. Send the USDC on Base to details.deposit_address, with details.memo if it’s set, before details.expires_at.
There’s no refund address to choose. A new key creates a new address, so keep the key and reuse it to retry: the same key returns the same address. You can also fund the agent with a transfer from any NEAR Intents account to agent.wallet.near_account_id.
2

Check balances

Use balance_raw, in atomic units, for arithmetic and request amounts. balance is the exact decimal amount for display. available_raw and available are what a new request can still spend: the balance less queued or timelocked work not yet dispatched. Read them instead of working it out yourself. Use source=confidential for the confidential balance.
3

Quote a swap

Add dry: true to see the price without swapping. A quote needs no grant token and no idempotency key. It returns 200 instead of 202, moves nothing and charges no budget. The spending rules never refuse it, but they are checked: if the live swap would be refused for the schedule, budget or a limit, warnings says so with the same code. A frozen, archived or deleted account gets no quote.
The response is { "dry": true, "type": "swap", "quote": { … }, "spend": { … }, "fee": { … } | null, "warnings": [ … ] }. quote holds the route’s quote with snake_case fields and atomic amounts. spend shows what the USD budget would count and the budget left, fee what the route keeps, and warnings lists high_fee above 5% and any account rule the live swap would fail. See Executions. Check warnings before you execute. A quote without a rule warning is a snapshot, not a guarantee: other work can use the budget first.If a quote fails with provider_unavailable (the quote service did not answer), nothing was submitted. Check GET /v1/network, wait until one_click reports operational, and try again. route_unavailable means no route or liquidity for this pair or amount: try a different amount or pair under a new Idempotency-Key, since repeating the request will not help. A rule such as spend_budget_exceeded or policy_schedule_denied, or a balance too small for the amount (insufficient_balance, with available_amount), does not fail the quote. It appears in warnings, and the live swap is refused with that code.
4

Execute the swap

Send the same body without dry, and add the grant token and an Idempotency-Key. Optionally add min_amount_out, the minimum output sent to the provider. The quote does not apply it, and a swap reported below it never reads SUCCESS but NEEDS_REVIEW with amount_out_below_minimum. Create and store the key before you send, so a crash never leaves you guessing.
If the policy, destination rule, budget or grant refuses the request, you get an error and the swap never runs. A budget or limit refusal records nothing and charges nothing. The error code says what refused and its layer whose rule it was. See Status & Errors.
5

Transfer and withdraw

The policy lets the agent send only to alice.near, so these two actions use the owner’s account. A transfer goes to another NEAR Intents account. A withdraw goes to an address on any chain the route reaches, so it also takes chain. Preview a withdrawal first with dry: true. A preview runs under the grant and an idempotency key, like the withdrawal, and each agent gets 20 previews per rolling 24 hours. Every preview that reaches the provider uses one, even when it carries a rule warning.
An address the policy’s destinations rule doesn’t list fails with policy_destination_denied. For a withdrawal, the chain, address and memo must match a listed entry exactly. To allow a new destination, the owner signs a policy_update, and every live grant can use it at once. Amounts below the route’s minimum fail with amount_too_low.
6

Follow every action to its result

Every action returns 202 with a correlation_id. Poll GET /v1/status with it. These are the statuses you handle:
An UNCERTAIN action may already have executed. Never send it again under a new Idempotency-Key, or it may run twice. Keep polling the original correlation_id. A request that fails with a network error may also have reached the API: retry it with the same key and the same body, and you get the original result.
TypeScript SDK
A request that may have reached the wallet usually answers with status UNCERTAIN, but a server error can also follow a send. If error.retryable is true, send the same request with the same key after the wait: that covers server errors too, where the request may have taken effect. Without it, repeating will not help, but that alone does not prove nothing was sent. Codes such as spend_budget_exceeded or wallet_busy are refusals that sent nothing: the key replays the refusal and a later attempt needs a new key. After a server error or a lost response, keep the original key and read the status. availableAt is the earliest time to try again after a schedule or rate-limit refusal. The agent runs one money action at a time, so a second action sent while one runs fails with wallet_busy.For NEEDS_REVIEW, and for the full list of error codes, see Status & Errors.
You’ve now run the full path: an agent funded by a deposit, swapped inside rules its owner signed, and paid out. What the grant could do was always bounded by the policy.

Other actions

swap, withdraw, transfer and deposit also accept confidential: true to use the private balance. A private request never falls back to a public one.
You now have a funded agent that has swapped, transferred and withdrawn inside its owner’s rules, with each action followed to SUCCESS. That’s the whole flow.

Policies & Limits

Change the rules, budget, delay and schedule the owner signs.

Agent SDK

Every method, option and error field of the TypeScript client.