Intents
Create an intent
Create an intent for a governed action.
POST
/v1/agent-api/intentsThe SDK's submitIntent and the CLI's action commands create the intent for
you. If the server asks the agent to co-sign a wallet payment, both clients will
also sign and submit it in the same call.
Headers
Idempotency-KeystringOptionalOptional operation identifier. Reuse the same value only when retrying the same logical submission. Without it, each request is a new submission with no request-idempotency guarantee. Separate x402/MPP approval correlation and nonce-reuse rules still apply.
Body parameters
Below are the shapes that action can take. The idempotencyKey field is
optional, and when you send it, the Idempotency-Key header takes the same
value.
action.type |
method |
Required fields | Optional fields |
|---|---|---|---|
send |
ach |
counterpartyRailId, amount |
accountId, description, memo |
send |
wire |
counterpartyRailId, amount |
accountId, description, memo |
send |
on-chain |
counterpartyRailId, amount |
accountId, description |
transfer |
accountId, toAccountId, amount |
memo, description |
|
create_counterparty |
name, one of rail or email |
||
request_counterparty_details |
counterpartyId, methods |
||
x402 |
accountId, paymentRequirements |
resource, authorization, signedOffer |
|
mpp |
accountId, challenge |
resource |
|
policy_override |
schemaVersion, operations, durationSeconds, reason |
Responses
200Intent created and evaluated. A
send or wallet-source transfer from a non-custodial wallet account returns an additional nextAction object (a submit_stamp envelope) with the unsigned body to stamp and submit to POST /intents/{intentId}/submit-stamp.400Input invalid, including an accountless send when multiple source accounts are allowed (
policy_send_account_required)403Account not accessible under this policy, an accountless send has no allowed source (
policy_send_account_unavailable)404Agent or referenced counterparty resource not found. Payment recipient failures may include
details.requiredRail, which can be submitted in a create-counterparty intent409Intent conflicts, including idempotency-key reuse with changed request parameters, an inferred source that changed during submission (
policy_send_account_changed), another payment from the same wallet still being approved (movement_wallet_approval_open; details.heldUntil is when the payment holding the wallet frees it, with the seconds until then in Retry-After, and is null when that cannot be told, as while that payment is being signed; wait until then, or a few seconds when it is null, then send the request again, on a new idempotency key when details.intentCancelled is true, because this request's intent was cancelled and its key answers with that cancelled intent, and on the same key when it is false, because the intent is still open (if it has been cancelled since, that resend returns it and nothing moved, so start again on a new key); details.blockingIntentId names the payment holding the wallet when it is one of your own intents, and cancelling it frees the wallet at once), a retried send that now crosses networks while its earlier request is still open (cross_chain_send_movement_required; have the earlier request denied or let it expire, or have Catena support close it if it was already approved, then start the payment again on a new idempotency key), a network Catena has made temporarily unavailable (onchain_network_closed, with no Retry-After; the request changed nothing and payments already in progress complete; do not retry on that network, and use one named in details.alternatives instead), or an existing payment details request with safe invitation state429Too many bank payments were requested for the organization (
rate_limited). Each bank payment counts against a per-organization budget of 60 a minute by default, shared by its agents and members, with no daily cap; send the request again after the Retry-After seconds503Non-custodial wallet sending is not enabled, or a service the request needs is temporarily unavailable (
movement_admission_paused, or temporarily_unavailable with the service in details). The request changed nothing, and payments already in progress complete; send it again after the Retry-After secondsResponse fields
idstringRequiredaccountIdstringOptionalResolved source account, pinned when the intent was created. Omitted for actions without an account.
type"send" | "transfer" | "create_counterparty" | "request_counterparty_details" | "x402" | "mpp" | "policy_override"Requiredstatus"pending" | "processing" | "completed" | "blocked" | "failed"Requiredresolution"completed" | "blocked" | "denied" | "expired" | "failed" | "cancelled" or string or nullRequiredExact terminal outcome, or null while the intent is nonterminal. Known values are completed, blocked, denied, expired, failed, and cancelled; clients must preserve future nonblank strings.
reasonsarray of stringRequiredexpiresAtstring or nullRequiredreplayedbooleanRequireddataobject or nullRequirednextActionobjectOptionalnextAction.type"submit_stamp"RequirednextAction.signingRequestIdstringRequirednextAction.signerobjectRequirednextAction.preparedBodyobjectRequirednextAction.movementobjectOptionalnextAction.stepsarray of objectOptionalnextAction.totalsobjectOptionalmetadataobjectOptionalPresent while the intent waits for a person's approval: dataUrl is the console page where they decide it
metadata.dataUrlstring or nullRequired