Skip to main content

codespar_crypto_pay

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.

6 min read
View MarkdownEdit on GitHub
Buy-sideYour agent is the spender: money leaves the wallet it governs, under a signed mandate.

On-chain spend and cross-border ramps (testnet today).

tool codespar_crypto_pay2 actions1 moves moneyalways required amountcurrencydirection

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.

Actions

directionWhat it doesMoneyNeeds
sendSend crypto to a counterparty through a connected provider rail (Bitso withdrawal, Foxbit order, offramp)moves moneycounterparty
receive
example below
Create a hosted crypto checkout or deposit instructions the buyer settles; nothing moves until they payno

Unknown direction: refused; `direction` accepts only `send` or `receive`. Measured 2026-09-09.

Names come from the published tool document (/v1/meta-tools.json, the same list the MCP server answers to tools/list); the one-line summaries and the money class are kept in the docs repository and checked against it on every build.

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.

Call · tools/call
arguments
{
  "name": "codespar_crypto_pay",
  "arguments": {
    "amount": 10,
    "currency": "USDC",
    "direction": "receive",
    "country": "INTL",
    "metadata": { "order_id": "order_0000" }
  }
}
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.

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.

FieldTypeRequiredDescription
amountnumberYesAmount in the target currency's major unit (decimal)
currencystringYesUSDC 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
directionstringYessend or receive
counterpartyobjectFor sendRecipient (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
networkstringNoBlockchain network hint passed to the provider: ethereum, polygon, base, solana, bitcoin
metadataobjectNoProvider-specific overrides, e.g. fiat_currency on the ramp rails, source_wallet_id, destination_tag
railstringNoRouting 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
countrystringNoRouting 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

ErrorCauseWhat to do
invalid_argsdirection: "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_providersA (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.
A receive dispatched to a send-only lineThe 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. The wallet's USDC slot and its per-currency cap are described on codespar_wallet.

Notes

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

RailCurrencyCountryProviderDirectionNotes
stablecoin (default)USDCINTLCoinbase Commercereceive/charges; returns a hosted payment URL
stablecoinUSDCBRBitsosend/withdrawals, USDC wallet → external address. Outbound only
stablecoinUSDTBRFoxbitsend / receive/orders, market or limit on usdtbrl
stablecoin-checkoutUSDCINTLCoinbase CommercereceiveReusable hosted checkout (vs one-shot /charges)
onrampUSDCINTLOn/offramp partnerreceiveFiat → USDC (Pix BRL / wire USD / SEPA EUR). Returns the Pix copia-e-cola or wire instructions
offrampUSDCINTLOn/offramp partnersendUSDC → 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.

codespar_crypto_pay | CodeSpar