> ## Documentation Index
> Fetch the complete documentation index at: https://docs.unwall.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Send Payment

> Unified payment endpoint -- auto-routes to x402, USDC transfer, or fiat ACH based on the recipient.

The unified pay endpoint is the recommended way to send any payment through Unwall. It automatically detects the recipient type and routes to the appropriate rail:

* **URL** (e.g., `https://api.example.com/...`) -- routes to the x402 protocol
* **EVM address** (e.g., `0x742d...`) -- routes to on-chain USDC transfer
* **Bank details object** -- routes to fiat ACH off-ramp

<Note>
  Requires a bearer token with the `pay` permission. If the recipient is a URL, the token must also have the `x402` permission.
</Note>

## Request Body

<ParamField body="recipient" type="string | object" required>
  The payment recipient. Accepts one of three formats:

  * **URL** (string): An HTTPS URL for x402 protocol payments (e.g., `"https://api.example.com/v1/data"`)
  * **EVM address** (string): A `0x`-prefixed Ethereum address for USDC transfers (e.g., `"0x742d35Cc6634C0532925a3b844Bc9e7595f2bD28"`)
  * **Bank details** (object): An object with `name`, `account_number`, `routing_number`, and `email` for fiat ACH payments

  <Expandable title="Bank details object">
    <ParamField body="recipient.name" type="string" required>
      Recipient name. 1-200 characters.
    </ParamField>

    <ParamField body="recipient.account_number" type="string" required>
      Bank account number. 4-34 characters.
    </ParamField>

    <ParamField body="recipient.routing_number" type="string" required>
      ABA routing number. Exactly 9 digits.
    </ParamField>

    <ParamField body="recipient.email" type="string">
      Recipient email address. Up to 254 characters.
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="amount_usd" type="number">
  Payment amount in USD. Required for USDC transfer and fiat rails. Not used for x402 (the target API sets the price).
</ParamField>

<ParamField body="max_amount_usdc" type="integer">
  Maximum micro-USDC to pay for x402 requests (safety cap). 1 USDC = 1,000,000 micro-USDC. Only used when recipient is a URL.
</ParamField>

<ParamField body="description" type="string">
  Payment description for record-keeping. Max 500 characters.
</ParamField>

<ParamField body="idempotency_key" type="string">
  Unique key to prevent duplicate payments. Alphanumeric plus `_`, `-`, `:`, `.`. Max 255 characters.
</ParamField>

<ParamField body="method" type="string" default="GET">
  HTTP method for x402 requests. One of `GET`, `POST`, `PUT`, `DELETE`. Only used when recipient is a URL.
</ParamField>

<ParamField body="headers" type="object">
  Additional HTTP headers for x402 requests. Only used when recipient is a URL.
</ParamField>

<ParamField body="body" type="string">
  Request body for x402 `POST` or `PUT` requests. Only used when recipient is a URL.
</ParamField>

## Response

<ResponseField name="id" type="string" required>
  Unique transaction identifier.
</ResponseField>

<ResponseField name="status" type="string" required>
  Transaction status: `pending`, `processing`, `completed`, or `failed`.
</ResponseField>

<ResponseField name="rail" type="string" required>
  Payment rail used: `x402`, `usdc_transfer`, or `fiat`.
</ResponseField>

<ResponseField name="amount_charged" type="integer" required>
  Amount charged in rail-native units. Micro-USDC for `x402` and `usdc_transfer` rails, cents for `fiat` rail.
</ResponseField>

<ResponseField name="fee" type="integer" required>
  Platform fee charged in rail-native units.
</ResponseField>

<ResponseField name="currency" type="string" required>
  Currency of the amount: `usdc` or `usd`.
</ResponseField>

<ResponseField name="recipient" type="string" required>
  Recipient identifier (URL, EVM address, or recipient name).
</ResponseField>

<ResponseField name="tx_hash" type="string | null" required>
  On-chain transaction hash for USDC and x402 payments. `null` for fiat payments.
</ResponseField>

<ResponseField name="created_at" type="string" required>
  ISO 8601 timestamp of when the payment was created.
</ResponseField>

<ResponseField name="estimated_arrival" type="string | null" required>
  Estimated delivery time for fiat payments (e.g., "2-3 business days"). `null` for crypto rails.
</ResponseField>

<ResponseField name="response" type="object | null" required>
  For x402 payments only -- contains the proxied API response. `null` for other rails.

  <Expandable title="Response object">
    <ResponseField name="response.status_code" type="integer">
      HTTP status code from the target API.
    </ResponseField>

    <ResponseField name="response.headers" type="object">
      Response headers from the target API.
    </ResponseField>

    <ResponseField name="response.body" type="string">
      Response body from the target API.
    </ResponseField>
  </Expandable>
</ResponseField>

## Examples

### x402 Payment (URL recipient)

<CodeGroup>
  ```bash curl theme={null}
  curl -X POST https://api.unwall.xyz/v1/pay \
    -H "Authorization: Bearer aw_live_xxxxxxxxxxxx" \
    -H "Content-Type: application/json" \
    -d '{
      "recipient": "https://api.example.com/v1/data",
      "max_amount_usdc": 1000000,
      "description": "Fetch market data"
    }'
  ```

  ```python Python theme={null}
  import requests

  resp = requests.post(
      "https://api.unwall.xyz/v1/pay",
      headers={"Authorization": "Bearer aw_live_xxxxxxxxxxxx"},
      json={
          "recipient": "https://api.example.com/v1/data",
          "max_amount_usdc": 1000000,
          "description": "Fetch market data",
      },
  )
  result = resp.json()
  print(f"Paid {result['amount_charged'] / 1_000_000} USDC via {result['rail']}")
  ```

  ```typescript TypeScript theme={null}
  const resp = await fetch("https://api.unwall.xyz/v1/pay", {
    method: "POST",
    headers: {
      Authorization: "Bearer aw_live_xxxxxxxxxxxx",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      recipient: "https://api.example.com/v1/data",
      max_amount_usdc: 1000000,
      description: "Fetch market data",
    }),
  });
  const result = await resp.json();
  console.log(`Paid ${result.amount_charged / 1_000_000} USDC via ${result.rail}`);
  ```
</CodeGroup>

```json Response (200 OK) theme={null}
{
  "id": "tx_x402_abc123",
  "status": "completed",
  "rail": "x402",
  "amount_charged": 500000,
  "fee": 7500,
  "currency": "usdc",
  "recipient": "https://api.example.com/v1/data",
  "tx_hash": "0x1a2b3c4d5e6f7890abcdef1234567890abcdef1234567890abcdef1234567890",
  "created_at": "2026-03-11T14:30:00Z",
  "estimated_arrival": null,
  "response": {
    "status_code": 200,
    "headers": {
      "content-type": "application/json"
    },
    "body": "{\"data\": [{\"id\": 1, \"value\": \"premium result\"}]}"
  }
}
```

### USDC Transfer (EVM address recipient)

<CodeGroup>
  ```bash curl theme={null}
  curl -X POST https://api.unwall.xyz/v1/pay \
    -H "Authorization: Bearer aw_live_xxxxxxxxxxxx" \
    -H "Content-Type: application/json" \
    -d '{
      "recipient": "0x742d35Cc6634C0532925a3b844Bc9e7595f2bD28",
      "amount_usd": 50.00,
      "description": "Vendor payment"
    }'
  ```

  ```python Python theme={null}
  import requests

  resp = requests.post(
      "https://api.unwall.xyz/v1/pay",
      headers={"Authorization": "Bearer aw_live_xxxxxxxxxxxx"},
      json={
          "recipient": "0x742d35Cc6634C0532925a3b844Bc9e7595f2bD28",
          "amount_usd": 50.00,
          "description": "Vendor payment",
      },
  )
  result = resp.json()
  print(f"Sent {result['amount_charged'] / 1_000_000} USDC to {result['recipient']}")
  ```

  ```typescript TypeScript theme={null}
  const resp = await fetch("https://api.unwall.xyz/v1/pay", {
    method: "POST",
    headers: {
      Authorization: "Bearer aw_live_xxxxxxxxxxxx",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      recipient: "0x742d35Cc6634C0532925a3b844Bc9e7595f2bD28",
      amount_usd: 50.0,
      description: "Vendor payment",
    }),
  });
  const result = await resp.json();
  console.log(`Sent ${result.amount_charged / 1_000_000} USDC to ${result.recipient}`);
  ```
</CodeGroup>

```json Response (201 Created) theme={null}
{
  "id": "tx_usdc_def456",
  "status": "processing",
  "rail": "usdc_transfer",
  "amount_charged": 50000000,
  "fee": 750000,
  "currency": "usdc",
  "recipient": "0x742d35Cc6634C0532925a3b844Bc9e7595f2bD28",
  "tx_hash": "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890",
  "created_at": "2026-03-11T14:35:00Z",
  "estimated_arrival": null,
  "response": null
}
```

### Fiat ACH Payment (Bank details recipient)

<CodeGroup>
  ```bash curl theme={null}
  curl -X POST https://api.unwall.xyz/v1/pay \
    -H "Authorization: Bearer aw_live_xxxxxxxxxxxx" \
    -H "Content-Type: application/json" \
    -d '{
      "recipient": {
        "name": "Acme Supplies Inc",
        "account_number": "9876543210",
        "routing_number": "021000021",
        "email": "billing@acme.com"
      },
      "amount_usd": 2500.00,
      "description": "Monthly supply order #47"
    }'
  ```

  ```python Python theme={null}
  import requests

  resp = requests.post(
      "https://api.unwall.xyz/v1/pay",
      headers={"Authorization": "Bearer aw_live_xxxxxxxxxxxx"},
      json={
          "recipient": {
              "name": "Acme Supplies Inc",
              "account_number": "9876543210",
              "routing_number": "021000021",
              "email": "billing@acme.com",
          },
          "amount_usd": 2500.00,
          "description": "Monthly supply order #47",
      },
  )
  result = resp.json()
  print(f"Payment {result['id']} — arrives {result['estimated_arrival']}")
  ```

  ```typescript TypeScript theme={null}
  const resp = await fetch("https://api.unwall.xyz/v1/pay", {
    method: "POST",
    headers: {
      Authorization: "Bearer aw_live_xxxxxxxxxxxx",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      recipient: {
        name: "Acme Supplies Inc",
        account_number: "9876543210",
        routing_number: "021000021",
        email: "billing@acme.com",
      },
      amount_usd: 2500.0,
      description: "Monthly supply order #47",
    }),
  });
  const result = await resp.json();
  console.log(`Payment ${result.id} — arrives ${result.estimated_arrival}`);
  ```
</CodeGroup>

```json Response (201 Created) theme={null}
{
  "id": "tx_fiat_ghi789",
  "status": "processing",
  "rail": "fiat",
  "amount_charged": 250000,
  "fee": 3750,
  "currency": "usd",
  "recipient": "Acme Supplies Inc",
  "tx_hash": null,
  "created_at": "2026-03-11T14:40:00Z",
  "estimated_arrival": "2-3 business days",
  "response": null
}
```
