---
title: codespar_crypto_pay
description: Send or receive a crypto payment through a connected provider rail. Stablecoin checkout on Coinbase Commerce, BR rails on Bitso and Foxbit, and cross-border ramps via the on/offramp partner.
---

import { Callout } from "fumadocs-ui/components/callout";
import { Tabs, Tab } from "fumadocs-ui/components/tabs";

<MetaToolHeader tool="codespar_crypto_pay" />

Use it when the buyer or recipient settles in stablecoin or another crypto asset instead of fiat. For Pix, card, boleto or wire, that is [`codespar_pay`](/docs/concepts/meta-tools/pay).

## Actions

<MetaToolActions tool="codespar_crypto_pay" />

## Example

`direction: "receive"` on Coinbase Commerce: a hosted checkout the buyer settles in USDC. `country: "INTL"` is what selects that line (see Arguments); without it the intent defaults to `BR` and lands on the Bitso withdrawal line.

<Split min={380}>
<SplitPane label="Call · tools/call">

```json title="arguments"
{
  "name": "codespar_crypto_pay",
  "arguments": {
    "amount": 10,
    "currency": "USDC",
    "direction": "receive",
    "country": "INTL",
    "metadata": { "order_id": "order_0000" }
  }
}
```

</SplitPane>
<SplitPane label="Result">

Result shape: see runtime. The tool document says the Coinbase Commerce line returns a hosted checkout, and names no result field. The published document is [`/v1/meta-tools.json`](https://api.codespar.dev/v1/meta-tools.json).

</SplitPane>
</Split>

## When to use

- **Stablecoin checkout** (the buyer pays in USDC on a hosted page): `direction: "receive"`, `country: "INTL"`. The buyer is anonymous until they hit the hosted URL, so `counterparty` can be omitted.
- **An on-chain USDC payout** to an external address: `direction: "send"`, `country: "BR"` (the Bitso withdrawal line), with `counterparty.address` and `counterparty.country`.
- **Fiat ↔ USDC ramps** through the on/offramp partner: `rail: "onramp"` (a buyer sends Pix BRL, US wire or EUR SEPA and the operator's USDC wallet receives the stablecoin leg) or `rail: "offramp"` (the operator sends USDC and the recipient receives fiat on a pre-registered bank account), both with `country: "INTL"`. A cross-border purchase chains the two.
- **Match the direction to the rail yourself.** The router's money-direction guard runs only for `codespar_pay`, so a `receive` that resolves to the send-only Bitso line is dispatched, not refused.

## Arguments

The published schema declares six fields. Two more (`rail`, `country`) are read by the router and not declared; an agent working from the schema alone never passes them and every call resolves to the Bitso line.

| Field | Type | Required | Description |
|---|---|---|---|
| `amount` | `number` | Yes | Amount in the target currency's major unit (decimal) |
| `currency` | `string` | Yes | `USDC` or `USDT`, the only assets with catalog lines. The schema also names `BTC`, `ETH` and `MATIC`; no provider line carries them, so they refuse with `no_eligible_providers` |
| `direction` | `string` | Yes | `send` or `receive` |
| `counterparty` | `object` | For `send` | Recipient (send) or buyer (receive). For `send` it is required and must include `country` (ISO 3166-1 alpha-2) so the router and audit log can track cross-border flows; `address` for an on-chain destination, `bank_account_id` for an offramp. For `receive` it is optional |
| `network` | `string` | No | Blockchain network hint passed to the provider: `ethereum`, `polygon`, `base`, `solana`, `bitcoin` |
| `metadata` | `object` | No | Provider-specific overrides, e.g. `fiat_currency` on the ramp rails, `source_wallet_id`, `destination_tag` |
| `rail` | `string` | No | Routing override, honoured by the router but **not declared in the published schema** (ent#1181). Defaults to `stablecoin`; `stablecoin-checkout` for Coinbase's reusable checkout; `onramp` / `offramp` for the fiat conversion rails |
| `country` | `string` | No | Routing key for the eligibility lookup, also **not in the published schema** (ent#1181): `BR` (default) for Bitso and Foxbit, `INTL` for Coinbase Commerce and the on/offramp partner |

## Errors and what to do

| Error | Cause | What to do |
|---|---|---|
| `invalid_args` | `direction: "send"` without `counterparty.country`, or a `direction` outside `send` / `receive`. Nothing is dispatched. | Add the recipient's country; it lands in the audit log and in provider metadata when the rail supports it. |
| `no_eligible_providers` | A `(rail, currency, country)` triple with no catalog line (`BTC`, `ETH`, `MATIC`; a wrong `country`), or whose provider is not connected on this project. Nothing is dispatched. | Pick a triple from Notes; connect the provider via [`codespar_manage_connections`](/docs/concepts/meta-tools/manage-connections). |
| A `receive` dispatched to a send-only line | The direction guard does not run for this tool. | Pass `country: "INTL"` (Coinbase Commerce) or `rail: "onramp"` for receives. |

## Money and mandate

`direction: "send"` moves real money through the connected provider (a Bitso withdrawal, a Foxbit order, an offramp transfer) and follows your key's environment: a `csk_test_` key hits the provider's sandbox, a live key moves real money. `direction: "receive"` creates a hosted checkout or deposit instructions and nothing moves until the buyer pays. These are provider rails, not on-chain settlement by CodeSpar: the x402 / CDP wallet path is a different surface with its own network gate, described in [the gate](/docs/concepts/gate). The wallet's USDC slot and its per-currency cap are described on [`codespar_wallet`](/docs/concepts/meta-tools/wallet).

## Related

- [`codespar_pay`](/docs/concepts/meta-tools/pay): the fiat rails
- [`codespar_charge`](/docs/concepts/meta-tools/charge): the fiat inbound counterpart
- [`codespar_wallet`](/docs/concepts/meta-tools/wallet): the multi-slot wallet, including the USDC slot
- [hmac_signed auth](/docs/concepts/authentication#provider-auth-schemes): the Bitso and Foxbit authentication pattern
- [Crypto Pay Agent cookbook](/docs/cookbooks/crypto-pay-agent): end-to-end stablecoin example
- [Async settlement](/docs/api/sessions#async-settlement)

## Notes

**Rails.** The six catalog lines for `codespar_crypto_pay`. The router matches `(rail, currency, country)` exactly; there is no wildcard fallback.

| Rail | Currency | Country | Provider | Direction | Notes |
|---|---|---|---|---|---|
| `stablecoin` (default) | USDC | INTL | Coinbase Commerce | receive | `/charges`; returns a hosted payment URL |
| `stablecoin` | USDC | BR | Bitso | send | `/withdrawals`, USDC wallet → external address. Outbound only |
| `stablecoin` | USDT | BR | Foxbit | send / receive | `/orders`, market or limit on `usdtbrl` |
| `stablecoin-checkout` | USDC | INTL | Coinbase Commerce | receive | Reusable hosted checkout (vs one-shot `/charges`) |
| `onramp` | USDC | INTL | On/offramp partner | receive | Fiat → USDC (Pix BRL / wire USD / SEPA EUR). Returns the Pix copia-e-cola or wire instructions |
| `offramp` | USDC | INTL | On/offramp partner | send | USDC → fiat on a pre-registered bank account |

There is no `stablecoin-payout` rail: an on-chain USDC payout is `rail: "stablecoin"`, `country: "BR"`, `direction: "send"`.

**Cross-border purchase (BR buyer → US merchant).** Two calls: an `onramp` receive (`country: "INTL"`, `counterparty: { country: "BR" }`, `metadata: { fiat_currency: "BRL" }`) that returns the Pix copia-e-cola the buyer settles, then an `offramp` send (`country: "INTL"`, `counterparty: { country: "US", bank_account_id }`, `metadata: { fiat_currency: "USD" }`) that pays the merchant by wire. No card flag, no IOF, no SWIFT.

**Operator setup.** Coinbase Commerce: `api_key` auth with the `X-CC-Api-Key` header, optional shared secret for webhook verification. Bitso and Foxbit: `hmac_signed` auth; the operator stamps API key and secret and the runtime signs each request with HMAC-SHA256 over `nonce + method + path + body`. On/offramp partner: `api_key` auth with a raw `Authorization: <api_key>` header (no Bearer prefix); the operator pre-funds a USDC wallet and the runtime injects its id as `sourceWalletId`.

**Async settlement.** Crypto rails settle on-chain; latency varies by chain (seconds on Base and Polygon, minutes on Bitcoin). The flow mirrors `codespar_charge`: the call returns an id and a pending status (and, for receives, the hosted URL), the buyer pays or the transfer executes, the provider webhook lands and is correlated by `idempotency_key`, and `session.paymentStatus(id)` returns `succeeded`, `expired` (abandoned) or `failed` (chain error).

**Result shape (SDK), as previously documented.** `{ id, status, amount, currency, network?, direction, hosted_url?, addresses?, pix_deposit_code?, crypto_deposit_address?, raw? }` under `data` (reading `charge.hosted_url` instead of `charge.data.hosted_url` yields `undefined`). This revision did not re-verify that list against the runtime.

**From the SDK.** There is no typed wrapper; `session.execute("codespar_crypto_pay", arguments)` takes the same arguments as the MCP call.
