Skip to main content

Crypto Pay Agent

Generate a stablecoin payment URL via codespar_crypto_pay (Coinbase Commerce default), share with the user, watch for settlement webhook or paymentStatus.

1 min read · updated
View MarkdownEdit on GitHub
TIME
~10 min
PROVIDER
OpenAIgpt-4o
SERVERS
coinbase-commercez-api

The simplest crypto-rail agent. The operator wants to accept stablecoin (USDC) for a B2B invoice. The agent calls codespar_crypto_pay, gets back a hosted Coinbase Commerce payment URL, shares it via WhatsApp, and waits for settlement.

Prerequisites

npm install @codespar/sdk @codespar/openai openai
.env
CODESPAR_API_KEY=csk_live_...
OPENAI_API_KEY=sk-...

You need an active Coinbase Commerce account (default rail for stablecoin USD) and a Z-API connection for WhatsApp notification. Bitso is the BR fiat-onramp alternative — see Variations below.

Full agent code

crypto-pay-agent.ts
import { CodeSpar } from "@codespar/sdk";

const cs = new CodeSpar({ apiKey: process.env.CODESPAR_API_KEY });

async function cryptoInvoice(
  userId: string,
  amountUSD: number,
  buyer: { name: string; phone: string }
) {
  const session = await cs.create(userId, {
    servers: ["coinbase-commerce", "z-api"],
  });

  try {
    // 1. Generate a Coinbase Commerce hosted payment URL
    const charge = await session.execute("codespar_crypto_pay", {
      amount: amountUSD.toFixed(2),
      currency: "USDC",
      method: "stablecoin",
      metadata: { buyer_name: buyer.name },
    });

    console.log("Payment URL:", charge.payment_url);
    console.log("tool_call_id:", charge.tool_call_id);

    // 2. Share the payment URL with the buyer via WhatsApp
    await session.execute("codespar_notify", {
      recipient: buyer.phone,
      channel: "whatsapp",
      message:
        `Olá ${buyer.name}, sua fatura de ${amountUSD} USDC está pronta. ` +
        `Pague em qualquer rede suportada: ${charge.payment_url}`,
    });

    // 3. Wait for settlement
    let status = await session.paymentStatus(charge.tool_call_id);
    while (status.status === "pending") {
      await new Promise((r) => setTimeout(r, 5000));
      status = await session.paymentStatus(charge.tool_call_id);
    }

    if (status.status === "succeeded") {
      await session.execute("codespar_notify", {
        recipient: buyer.phone,
        channel: "whatsapp",
        message: `Recebido! Obrigado, ${buyer.name}.`,
      });
      return { ok: true, settled_at: status.settled_at };
    }

    return { ok: false, reason: status.status };
  } finally {
    await session.close();
  }
}

Why crypto?

Two real reasons LATAM operators reach for the crypto rail:

  1. Cross-border B2B settlement — a Brazilian SaaS billing a US customer wants USDC instead of paying Stripe's 4-6% on a card transaction. Coinbase Commerce hosts the payment page, the operator gets stablecoin, can hold or off-ramp later.
  2. Bitso fiat-onramp — a Brazilian operator wants to accept BRL on the front end but settle internally in crypto for treasury reasons. Bitso bridges BRL ↔ crypto natively.

Settlement model

Crypto settles on-chain, latency varies by chain:

ChainTypical settlement
USDC on Polygon / Arbitrumseconds
USDC on Ethereum L11-5 minutes
BTC10-30 minutes (3 confirmations)

Coinbase Commerce normalizes all of these — its webhook fires once the chain has reached the configured confirmation depth. CodeSpar's paymentStatus returns pending until that webhook lands.

For long settlement windows (BTC), prefer the streaming variant:

await session.paymentStatusStream(charge.tool_call_id, {
  onUpdate: (s) => {
    if (s.status === "succeeded") releaseGoods();
  },
});

Variations

Bitso (BR fiat-onramp)

Swap the server to bitso. Bitso uses an hmac_signed auth pattern — see hmac_signed auth for the operator setup. The args shape is the same; pass currency: "BRL" and the buyer pays BRL while the operator's settlement lands in crypto.

Outbound stablecoin payout

Pass recipient.wallet_address to send stablecoin OUT to a vendor wallet — the agent receives the on-chain transaction once broadcast. Useful for paying remote contractors in USDC.

Webhook-triggered ship

After settlement, chain codespar_ship to generate a label automatically. The same pattern as the Webhook Listener cookbook, just with codespar_crypto_pay as the upstream.

Next steps

Edit on GitHub

Last updated on