# Create an intent

> Create an intent for a governed action.

`POST /v1/agent-api/intents`

The 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

| Field             | Type   | Required | Description                                                                                                                                                                                                                                                       |
| ----------------- | ------ | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Idempotency-Key` | string |          | Optional 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

| Status | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `200`  | Intent 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.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| `400`  | Input invalid, including an accountless send when multiple source accounts are allowed (`policy_send_account_required`)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| `403`  | Account not accessible under this policy, an accountless send has no allowed source (`policy_send_account_unavailable`)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| `404`  | Agent or referenced counterparty resource not found. Payment recipient failures may include `details.requiredRail`, which can be submitted in a create-counterparty intent                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| `409`  | Intent 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 state |
| `429`  | Too 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` seconds                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| `503`  | Non-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` seconds                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |

## Response fields

| Field                         | Type                                                                                                                                  | Required | Description                                                                                                                                                                                  |
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`                          | string                                                                                                                                | Yes      |                                                                                                                                                                                              |
| `accountId`                   | string                                                                                                                                |          | Resolved 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"` | Yes      |                                                                                                                                                                                              |
| `status`                      | `"pending"` \| `"processing"` \| `"completed"` \| `"blocked"` \| `"failed"`                                                           | Yes      |                                                                                                                                                                                              |
| `resolution`                  | `"completed"` \| `"blocked"` \| `"denied"` \| `"expired"` \| `"failed"` \| `"cancelled"` or string or null                            | Yes      | Exact 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. |
| `reasons`                     | array of string                                                                                                                       | Yes      |                                                                                                                                                                                              |
| `expiresAt`                   | string or null                                                                                                                        | Yes      |                                                                                                                                                                                              |
| `replayed`                    | boolean                                                                                                                               | Yes      |                                                                                                                                                                                              |
| `data`                        | object or null                                                                                                                        | Yes      |                                                                                                                                                                                              |
| `nextAction`                  | object                                                                                                                                |          |                                                                                                                                                                                              |
| `nextAction.type`             | `"submit_stamp"`                                                                                                                      | Yes      |                                                                                                                                                                                              |
| `nextAction.signingRequestId` | string                                                                                                                                | Yes      |                                                                                                                                                                                              |
| `nextAction.signer`           | object                                                                                                                                | Yes      |                                                                                                                                                                                              |
| `nextAction.preparedBody`     | object                                                                                                                                | Yes      |                                                                                                                                                                                              |
| `nextAction.movement`         | object                                                                                                                                |          |                                                                                                                                                                                              |
| `nextAction.steps`            | array of object                                                                                                                       |          |                                                                                                                                                                                              |
| `nextAction.totals`           | object                                                                                                                                |          |                                                                                                                                                                                              |
| `metadata`                    | object                                                                                                                                |          | Present while the intent waits for a person's approval: dataUrl is the console page where they decide it                                                                                     |
| `metadata.dataUrl`            | string or null                                                                                                                        | Yes      |                                                                                                                                                                                              |

## Example

### SDK

```ts
import { createCatenaClient } from "@catena/sdk"

// Reads CATENA_SECRET_KEY
const client = createCatenaClient()

const intent = await client.submitIntent({
  action: {
    type: "send",
    method: "ach",
    accountId: "acct_01JC2Y6ZQ8R4M7N9P3S5T6V8WX",
    counterpartyRailId: "cpr_01JC2Z1B4D6F8H0K2M4P6R8T1V",
    amount: "420.00",
    description: "Invoice INV-4471",
  },
})
```

### CLI

```sh
catena send --method ach --amount 420.00 \
  --account acct_01JC2Y6ZQ8R4M7N9P3S5T6V8WX \
  --rail cpr_01JC2Z1B4D6F8H0K2M4P6R8T1V \
  --description "Invoice INV-4471"
```

### Response `200`

```json
{
  "id": "int_01JC3B2K7W9D4F6H8J1M3P5R7T",
  "accountId": "acct_01JC2Y6ZQ8R4M7N9P3S5T6V8WX",
  "type": "send",
  "status": "processing",
  "resolution": null,
  "reasons": [],
  "expiresAt": null,
  "replayed": false,
  "data": null
}
```
