ROZO Checkout for AI agents
ROZO Checkout lets an AI agent pay an OpenRouter invoice — a Coinbase payment link — with BTC over Lightning, or USDT/USDC on Solana, BNB Chain, Ethereum, Polygon, Base and Stellar, instead of the Base USDC the link expects. Every endpoint below is public HTTP: no API key, no account, no browser and no wallet-connect popup, so the whole payment fits inside a script or a tool call.
The one command
If your agent can run a shell command, this is the entire integration. It quotes the link, creates the order, shows you what will be sent and how long it stays valid, and waits until the invoice is settled.
npx @rozoai/checkout pay https://payments.coinbase.com/payment-sessions/paymentSession_3230343499xxx
That URL is your OpenRouter payment link, copied from OpenRouter's Buy Credits → Crypto flow. The trailing xxx is only there to mark it as an example — yours will end in real characters.
On a terminal it asks which coin you want to pay with. You can paste your wallet address at the prompt and it will mark which coins you can actually afford — a display-only hint that never changes what gets signed — and it remembers that address and your coin for next time. Then it prints a deposit address you pay from any wallet: no private key, no environment variable, no configuration.
Already know your coin, or writing a script? Name it and skip the question. Agents and scripts must always pass --with — the picker only appears on a terminal, and there is deliberately no default coin.
npx @rozoai/checkout pay https://payments.coinbase.com/payment-sessions/paymentSession_3230343499xxx --with usdt-solana
--with accepts usdt-solana, usdc-solana, usdt-bnb, usdc-bnb, usdt-ethereum, usdc-ethereum, usdt-polygon, usdc-polygon, usdc-base, usdc-stellar and btc-lightning — see the supported chains. Add --yes when stdin is not a TTY, and --json for exactly one JSON object on stdout. Everything below is this same payment expressed in whatever tool you already use.
Pick your tool
Open the one you use. For most tools the payload is identical — the npx command above, or pointing the agent at /llms.txt. In every one of them you pay from your own wallet and no key is involved; only the optional --send flag signs locally.
Claude Codeinstall the skill, or paste the one-liner
The repo is a Claude Code skill: it ships SKILL.md plus the executables under scripts/dist/. Clone it into your skills directory so Claude Code picks it up automatically.
git clone https://github.com/RozoAI/rozo-checkout-skill ~/.claude/skills/rozo-checkout
Or skip setup entirely and paste this into any session:
Pay this OpenRouter link with USDT on Solana using: npx @rozoai/checkout pay https://payments.coinbase.com/payment-sessions/paymentSession_3230343499xxx --with usdt-solana
Codex CLIAGENTS.md, or run it directly
Codex reads AGENTS.md from the project root. Add a standing instruction so it knows how to pay without being told each time:
## Paying OpenRouter invoices To pay a payments.coinbase.com link, run: npx @rozoai/checkout pay https://payments.coinbase.com/payment-sessions/paymentSession_3230343499xxx --with usdt-solana Full reference: https://checkout.rozo.ai/llms.txt
Or just run the command yourself in the session — it needs no configuration.
OpenCodeAGENTS.md, or run it directly
OpenCode also reads AGENTS.md from the project root, so the Codex snippet above works unchanged. The shortest path is still the command itself:
npx @rozoai/checkout pay https://payments.coinbase.com/payment-sessions/paymentSession_3230343499xxx --with usdt-solana
Cline.clinerules, or run it directly
Cline reads standing instructions from .clinerules in the project root. Drop the same rule in:
To pay an OpenRouter / Coinbase payment link, run: npx @rozoai/checkout pay https://payments.coinbase.com/payment-sessions/paymentSession_3230343499xxx --with usdt-solana Full reference: https://checkout.rozo.ai/llms.txt
Cline will ask before executing the command, which is the behaviour you want for a payment.
Cursor.cursor/rules, or run it directly
Add a project rule under .cursor/rules/ so the agent knows the command:
To pay an OpenRouter / Coinbase payment link, run: npx @rozoai/checkout pay https://payments.coinbase.com/payment-sessions/paymentSession_3230343499xxx --with usdt-solana Full reference: https://checkout.rozo.ai/llms.txt
Or run the command in Cursor's terminal — no rule needed.
Hermes Agentrun the one-liner in a session
Hermes Agent (Nous Research) has shell access and its own skill system. Start it with hermes and ask it to run the command:
Fetch https://checkout.rozo.ai/llms.txt, then pay this OpenRouter link: npx @rozoai/checkout pay https://payments.coinbase.com/payment-sessions/paymentSession_3230343499xxx --with usdt-solana
OpenClawopenclaw agent exec
OpenClaw's headless entry point runs a one-off task, which is a good fit for a payment you trigger from a script or a chat channel:
openclaw agent exec "Pay this OpenRouter link with USDT on Solana by running: npx @rozoai/checkout pay https://payments.coinbase.com/payment-sessions/paymentSession_3230343499xxx --with usdt-solana"
Pirun the one-liner in a session
Pi is a BYOK terminal agent whose built-in tools include bash, so it can run the command directly. Start it with pi and ask:
Pay this OpenRouter link with USDT on Solana by running: npx @rozoai/checkout pay https://payments.coinbase.com/payment-sessions/paymentSession_3230343499xxx --with usdt-solana
Terminal — no agent at allrun the scripts step by step
If you want to drive each step yourself, clone the repo and run the scripts. They are self-contained bundles — nothing to install beyond Node 18+.
git clone https://github.com/RozoAI/rozo-checkout-skill cd rozo-checkout-skill LINK="https://payments.coinbase.com/payment-links/pl_01YOURLINKID" # 1. Quote — read-only, costs nothing node scripts/dist/quote.js --url "$LINK" # 2. Create the order. No money moves; the full deposit address is # WITHHELD and you get a masked summary to review first. node scripts/dist/create-order.js --url "$LINK" --chain 900 --token USDT # 3. Only once you have decided to pay, re-run with --confirm to # release the full deposit block. node scripts/dist/create-order.js --url "$LINK" --chain 900 --token USDT --confirm # 4. Pay the deposit block from any wallet — no key, no configuration. # Send exactly the amount, token, chain and every other field it gives # you, copied from the JSON and never retyped. # 5. Watch it settle node scripts/dist/status.js --rozo-payment-id <rozoPaymentId> --watch --timeout 600
Each script prints exactly one JSON object on stdout; exit 0 success, 1 refused or failed (read error.code), 2 usage, 3 submitted but unconfirmed.
Paying from your own wallet is the default and needs no key. If you would rather this machine signed for you — EVM chains and Solana only — use send-evm.js or send-sol.js. On Solana they use the ~/.config/solana/id.json that solana-keygen already wrote; on EVM an encrypted V3 keystore whose passphrase is prompted, never passed as a flag. A raw environment key still works for unattended runs. That path has one limit: a single payment may not exceed $1,100, with no override. Larger invoices go through the keyless path above.
States run awaiting_deposit → payin_detected → payin_confirmed → bridging → paying_coinbase → settled. Your on-chain transaction confirming is not the end — keep polling until settled.
Any other agentpoint it at /llms.txt
Any agent that can fetch a URL and run a command can do this. One line, no setup:
Fetch https://checkout.rozo.ai/llms.txt into your context, then use it to pay this OpenRouter link: https://payments.coinbase.com/payment-sessions/paymentSession_3230343499xxx
If the agent has no shell but can make HTTP requests, drive the four raw calls below directly.
Raw HTTP, for any framework
Four calls, all public and keyless. This is the layer the CLI and the skill sit on, so any framework — LangChain, an OpenAI tool call, a cron job — can drive it directly.
MPP="https://apiserver.mpprouter.dev/v1/services/rozo-agent-api" INTENTS="https://intentapiv4.rozo.ai/functions/v1/payment-api" LINK="https://payments.coinbase.com/payment-links/pl_01YOURLINKID" # 1. Quote: merchant, amount, expiry, and a ~60-second quoteReceipt. # callerPays always equals the invoice amount; discount is always "0". curl -s -X POST "$MPP/quote-invoice" \ -H 'content-type: application/json' \ -d "{\"url\":\"$LINK\"}" # 2. Create a bridge order for, say, USDT on Solana. # Creates an order but moves no money; an unfunded order simply expires. curl -s -X POST "$MPP/create-invoice" \ -H 'content-type: application/json' \ -d "{\"url\":\"$LINK\",\"source\":{\"chainId\":\"900\",\"tokenSymbol\":\"USDT\"}}" # 3. Authoritative deposit instructions, using the rozoPaymentId above. # Pay EXACTLY source.amount of the requested token on the requested chain # to source.receiverAddress, including source.receiverMemo when present. # For Lightning, pay the BOLT11 in source.lnInvoice. curl -s "$INTENTS/payments/<rozoPaymentId>" # 4. Fulfilment status, using the Coinbase linkId. curl -s "$MPP/invoice-status?payment_id=pl_01YOURLINKID"
create-invoice is rate-limited per IP (about 30/hour); the read endpoints are not. The Coinbase link is settled only when the router reports paid / coinbase.settled — an intents status of payment_completed alone is the bridge lifecycle, not final settlement.
Errors worth encoding: 409 link already used · 410 link expired · UNSUPPORTED_SOURCE (the response's supported object lists valid chain/token pairs; Lightning is supported but omitted from that list) · RATE_LIMITED per-IP creation cap, retry later.
What you need
A wallet holding one supported token, on one of these chains. Native gas coins are not accepted: SOL, ETH, BNB and MATIC will not settle, and neither will on-chain BTC.
| Chain | Chain id | Tokens | Note |
|---|---|---|---|
| Ethereum | 1 | USDC, USDT | 6 decimals |
| BNB Chain | 56 | USDC, USDT | 18 decimals — the usual source of off-by-1012 bugs |
| Polygon | 137 | USDC, USDT | 6 decimals |
| Base | 8453 | USDC | 6 decimals |
| Solana | 900 | USDC, USDT | 6 decimals; SPL. Native SOL is not supported |
| Stellar | 1500 | USDC | 7 decimals; the deposit memo is required, and its type is MEMO_TEXT — even when the memo is all digits. Choosing MEMO_ID in your wallet produces a different memo and the payment is not matched |
| Bitcoin Lightning | lightning | BTC | amounts are integer satoshis, paid via a BOLT11 invoice |
- Node 18 or newer for the CLI and skill paths (
node -v). The raw HTTP path needs nothing but an HTTP client. - The Coinbase link, e.g.
https://payments.coinbase.com/payment-links/pl_01YOURLINKID. - No account and no API key. Every endpoint on this page is public.
- No key for the default path. Paying the deposit address from your own wallet needs no private key, no environment variable and no configuration at all. Only the optional
--sendflag signs locally, taking its key from~/.config/solana/id.jsonon Solana or an encrypted keystore (passphrase prompted) on EVM; a raw environment key still works for unattended automation, and a key is never accepted on the command line. That signing path caps a single payment at $1,100; anything larger goes through the keyless path.
Which wallet do I need?
One wallet, on one chain — not one per chain. Pick whichever coin from the table above you already hold, and pay from wherever it already lives.
- Any wallet works, and so does an exchange withdrawal. The default path just prints a deposit block; you send exactly that amount of that token, on that chain, to that address. Nothing connects to this site and nothing is approved in a browser. In practice people use MetaMask or Rabby on the EVM chains, Phantom or Solflare on Solana, and a Lightning wallet such as Phoenix or Wallet of Satoshi for BTC.
- Stellar is the one to be careful with. Its deposits route through a shared address plus a memo, so whatever you send from — exchange or wallet — must let you set a memo. Omit it and the payment is lost. The memo type is always
MEMO_TEXT, even when the memo is all digits:65371582is text, not an id. PickMEMO_IDin your wallet and it becomes a different memo that will never match. The deposit block states the type asreceiverMemoType— send it exactly as given. - Lightning pays an invoice, not an address. You scan or paste the BOLT11 string from the deposit block; there is no address to send to.
- Only
--sendneeds a key, and it covers EVM chains and Solana only — there is no--sendfor Stellar or Lightning. It signs locally: on Solana from the~/.config/solana/id.jsonthatsolana-keygenalready wrote, on EVM from an encrypted keystore whose passphrase is prompted. A raw key in the environment still works for unattended automation. Everything else on this page is keyless.
Safety, honestly
Paying the wrong amount, the wrong token, the wrong network, or paying twice is usually unrecoverable. These are the rails that matter most; encode them even if you are writing your own client.
- Deposit addresses are one-time and quote-bound. Never reuse an address from an old order, a cached response, or a document. Re-fetch the deposit instructions in the same run, right before you send.
- Respect expiry with margin. Do not send if now is past the earlier of the order expiry and the Coinbase link expiry, minus a per-chain margin: 10 minutes on EVM and Stellar, 5 minutes on Solana. A Lightning BOLT11 needs at least 10 minutes of validity left. The deposit block, the confirmation summary and
statusall report the time left as a plain duration — expires in 47m — rather than a timestamp you have to convert. An order you never fund simply expires and costs nothing, so letting one lapse and starting again is always safe. - Never pay a funded order twice. Creating an order for a link that already has an unexpired order returns that existing order — even if it has already been funded, and even if it uses a different chain or token than you asked for. Verify the returned source matches your request, and require the order to be unpaid before sending. Once any money has left your wallet, do not retry into a new order: keep the
linkId, therozoPaymentIdand every transaction hash, keep polling, and get a human to reconcile it. - There is no discount. You pay the invoice amount —
callerPaysalways equals it anddiscountis always"0". Take the flagship case: $1,000 of OpenRouter credits bills as a $1,050.00 invoice once OpenRouter's own 5% crypto fee is added, and $1,050.00 is what you owe. The deposit you send reads a little higher still, because it carries the bridge and source-chain fees on top. Check the displayed deposit amount before you go on. - Re-check payability immediately before broadcasting. The Coinbase link can be consumed by another payer at any moment.
The full list — two-phase confirmation, the money-detected rule, the compromised-address blacklist, send-once locking across processes, hot-wallet caps and address masking — is documented under Safety design in the GitHub repo.
Pay your first invoice
One command, no account, no API key. SKILL.md is written for the agent, QUICKSTART.md for the developer wiring it up.
Open rozo-checkout-skill Read /llms.txt