Skip to main content

Bitrefill Plugin

[!IMPORTANT] Complete Base MCP onboarding first (SKILL.md). Path 1 (connect→JWT) is the default for agent-commerce. Fall back to Path 2 (pay-per-call x402) for multi-wallet or stateless agents. Use Path 3 (CLI) or Path 4 (Bitrefill MCP) only when the user has an existing Bitrefill account. Keep buy-products out of Bitrefill MCP autoApprove.

Overview

Turn USDC on Base into everyday spending — inside the conversation. Bitrefill is the world’s largest crypto-native storefront for digital goods: gift cards (Amazon, Apple, Steam, Uber, and 1,500+ more), mobile refills in 180+ countries, and data eSIMs for travel. Pay with USDC on Base from your Base Account; codes and install links land in chat — often in seconds, sometimes within a few minutes (see Business domain). Why agents love it: one session can go from “I need a $25 Amazon US card” to a delivered PIN — search, pick a denomination, confirm, pay, poll, redeem — without leaving the thread. No Bitrefill signup on the default path: sign in once with your wallet, browse fee-free, pay only at checkout. Already on Bitrefill? Link an existing account via CLI or the Bitrefill MCP and shop your usual catalog the same way. Path selection, API routes, and Base MCP wiring: Detection · Submission

Detection

Path 1 — Connect → JWT (default): one wallet sign-in → session token (~2 h); browse/create/status without micro-fees; pay at checkout only. Path 2 — Pay-per-call x402: no session; HTTP 402 + micro-fee on each gated call. Path 3 — CLI: existing Bitrefill account via @bitrefill/cli (shell). Path 4 — Bitrefill MCP: existing account via https://api.bitrefill.com/mcp (OAuth, shell-less). After Base MCP is available (SKILL.md), pick a path: Agent-commerce (USDC on Base, no Bitrefill account):
  1. Base MCP sign + web_request + x402 payment tools available, agent can persist a JWT → Path 1.
  2. Otherwise, or multi-wallet / no session persistence → Path 2.
  3. Cannot run SIWX helpers (no shell/Node for checksum + message build) → Path 2 only; tell the user connect is unavailable.
Existing Bitrefill account:
  1. Shell + npx @bitrefill/cli@latest --helpPath 3.
  2. Bitrefill MCP tools exposed (search-products, buy-products, …) → Path 4.
  3. Neither → install per Path 4 setup below; stop if both fail.
Never scrape https://www.bitrefill.com (403 from datacenters). Paths 1–2: Base MCP web_request to allowlisted api.bitrefill.com (custom-plugins.md). Paths 3–4: Bitrefill CLI or Bitrefill MCP.

Path 4 setup (Bitrefill MCP)

https://api.bitrefill.com/mcp — OAuth at connector setup.
  • Cursor: .cursor/mcp.json or ~/.cursor/mcp.json:
    buy-products out of autoApprove.
  • Claude Code: claude mcp add bitrefill --url https://api.bitrefill.com/mcp
  • Reconnect/restart after install. MCP tools (verified): search-products, get-product-details, buy-products, submit-prepayment-step, list-invoices, get-invoice-by-id, update-order.

Auth and SIWX

Path 1 connect uses SIWX → JWT. Path 2 needs no auth. Post-purchase redemption codes on invoice/status require SIWX from the paying wallet (Path 1 JWT covers browse/status polling; if codes are missing, run SIWX for codes below). Path 3/4 use CLI/MCP OAuth.

EIP-55 checksum (required)

The address in the signed message and SIWX payload must be EIP-55 checksummed (mixed case). Lowercase addresses from get_wallets cause the API to reject the signature and return another 402. Always run toChecksumAddress before building the message. Base Account signatures are ERC-1271/6492 wrapped (~224 bytes). Pass the full signature unchanged; header type stays "eip191". Wallet reads and write approvals follow approval-mode.md.

SIWX timing

Challenge nonce expires in 5 minutes and is single-use. Fetch challenge → build message → sign → send header within that window. If connect returns 402 again, fetch a fresh challenge and repeat — do not reuse a stale nonce or signature.

Connect → JWT (Path 1)

  1. web_request POST https://api.bitrefill.com/x402/connect with body {} and header Content-Type: application/json402 whose JSON body includes extensions["sign-in-with-x"].info (domain, uri, version, nonce, issuedAt, expirationTime, statement, resources) and supportedChains.
  2. get_wallets → wallet address.
  3. Pick Base: { chainId: "eip155:8453", type: "eip191" } from supportedChains.
  4. Build EIP-4361 message with SIWX helpers below (toChecksumAddressbuildSiweMessage). The uri in the challenge for connect is https://api.bitrefill.com/x402/connect.
  5. sign with type: "personal_sign", data: { message: <exact string> } → follow approval-mode.mdsignature.
  6. Build decomposed payload (not { message, signature }), base64-encode → sign-in-with-x request header (see payload shape below).
  7. web_request POST https://api.bitrefill.com/x402/connect with body {}, Content-Type: application/json, and header sign-in-with-x: <base64>200 with { token, token_header: "X-Access-Token", expires_in } (default ~7200 s).
  8. Store token in memory only. Attach X-Access-Token: <token> (raw JWT, no Bearer) on every subsequent gated web_request. Re-connect when expired.

SIWX for codes (after invoice/pay)

When invoice/status returns delivery complete but no redemption_info, or Path 2 without JWT:
  1. web_request GET https://api.bitrefill.com/x402/invoice/status?invoice_id=<uuid>402 with SIWX challenge (save the full JSON body).
  2. Build message from challenge infouri must match the challenged route (includes ?invoice_id=).
  3. sign → follow approval-mode.md within 5 minutes.
  4. web_request same URL with sign-in-with-x header → 200 with redemption_info.orders[].redemption_info (code, pin, extra_fields).
  5. 403 → signing wallet is not the invoice payer. Sign with the wallet that paid.
my/orders and my/esims use the same SIWX flow (Path 1 JWT also works on these routes).

Decomposed SIWX payload

Base64 of this JSON (send as sign-in-with-x header):
Chain ID is numeric (8453) inside the signed message but CAIP-2 (eip155:8453) in the payload.

SIWX message shape

SIWX helpers (no external libraries)

Verified against siwe@2.3.2 and @x402/extensions@2.3.0. Run in Node 18+ or any JS shell. JavaScript:
Run the JavaScript block in Node (node -e '…') or any harness with BigInt. Do not hand-type checksummed addresses. If no JavaScript runtime is available, use Path 2 (no connect SIWX) or obtain checksum/message from a one-line Node invocation before calling sign.

Business domain

Bitrefill API names do not match everyday ecommerce wording — map them when talking to users:
API termMeansUser-facing
invoicePrice-locked checkout (cart + total), not a billing document”your order” / “checkout”
orderOne cart line item (one product/denomination)“item”
Flow: invoice/createinvoice/pay → backend async fulfillment of each order. Gift-card codes are often near-instant; some products take minutes. Poll invoice/status until delivery_status is all_delivered — do not treat payment confirmation as delivery. If an item is still not fulfilled after 3 hours, or the user hits any service issue, point them to help.bitrefill.com.

Endpoints

Base URL: https://api.bitrefill.com (no /api prefix on x402 routes). Every gated response embeds next_step: { url, body } chaining search → detail → create → pay → status. 402 envelope: payment-required header is base64 JSON, mirrored into the JSON body.
MethodPathCostAuth (no JWT)
GET/x402/gift-cards/search?q=&country=$0.002x402
GET/x402/esims/search?q=$0.002x402
GET/x402/topups/search?q=$0.002x402
GET/x402/checkout/info$0.001x402
GET/x402/products/detail?slug=$0.001x402
POST/x402/invoice/create$0.002x402
POST/x402/invoice/payinvoice amountx402 (never JWT-waived)
GET/x402/invoice/status?invoice_id=$0.001 or SIWXx402 or SIWX
POST/x402/connectfreeSIWX → JWT
GET/x402/my/ordersfreeSIWX or JWT
GET/x402/my/esimsfreeSIWX or JWT
With valid X-Access-Token, the gate bypasses micro-fees and SIWX on all gated routes except /x402/connect (cannot mint with a token) and invoice/pay (invoice amount never waived). Repeat reads: paying a route once grants that wallet fee-free access to the same path for 30 days. SIWX routes still need a signature per request when not using JWT.

Payment (Base USDC)

FieldValue
Network (CAIP-2)eip155:8453
USDC0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913
payTo0x480CD46E6faDe651a0437DeaddA53D5c8e7D846A
All checkout and x402 pay flows use USDC on Base only.

package_value (critical)

Use the exact string from products/detail packages[].package_value — do not transform.
TypeFormatExample
Gift cardsBare integer string"10", "50"
Top-upsBare integer string"5", "20"
eSIMsDescriptive label"1GB, 7 Days", "Unlimited, 15 Days"
Wrong package_value → HTTP 500 on invoice/create (no charge). Confirm no charge before retry (see Notes).

Request shapes

invoice/create — gift card:
Top-up with phone (recipient_required: true on detail):
Response: { "invoice_id", "price_usdc", "price_usd", "expires_in_minutes", "next_step" }. invoice/pay{ "invoice_id": "<uuid>" }. Success: { "success": true, "status": "payment_confirmed", "transaction", "next_step" }. invoice/status — without SIWX/JWT: status fields only. With SIWX from payer or Path 1 JWT: adds redemption_info.orders[].redemption_info (code, pin, extra_fields).

Surface routing

CapabilityPath 1Path 2Path 3Path 4
Connect / JWTsign + web_request /connect
Search / browseweb_request + X-Access-Tokenx402 pay per routeCLIsearch-products
Product detailweb_request + tokenx402CLIget-product-details
Invoice createweb_request + tokenx402CLI / MCPbuy-products
Pay invoiceBase MCP x402 toolsSamex402 or sendSame
Poll statusweb_request + tokenx402 or token-less poll + SIWX for codesCLIget-invoice-by-id
Redemption codesJWT or SIWX on invoice/statusSIWX from payerCLIget-invoice-by-idorders[].redemption_info
Order historyweb_request /my/orders + tokenSIWX per requestCLIlist-invoices

Claude show_widget

On claude.ai, render search/detail/invoice/status via the built-in show_widget tool — inline in chat, not Artifacts, not HTML in prose. Narrative stays in the message; only the visual goes in widget_code (title: snake_case). Fragment order: <style> → HTML → <script>. No html/head/body. Host CSS vars only (var(--color-*)); no font-family; no shadows/gradients/blur/transition: all. Body ≥16px; interactive min-height: 44px. One primary + one secondary CTA. Primary follows next_step (“See details for …” → “Buy … on …” → “Confirm and pay … USDC” → “Check delivery status”); wire it with sendPrompt(...). Secondary is lateral escape only. Selection: transparent 2px border + outline at rest; selected var(--color-border-info) + var(--color-background-info). Pre-select defaults so primary is actionable on first paint.

Orchestration

Path 1: Connect → browse → buy (default)

  1. Connect — SIWX flow above → store JWT and expires_in. Do this once per session.
  2. Confirm funds — when needed, check USDC on Base before pay.
  3. Searchweb_request GET /x402/gift-cards/search?q=<term>&country=<ISO> with X-Access-Token. Take slug from products[]. (Or esims/search, topups/search.)
  4. Detailweb_request GET /x402/products/detail?slug=<slug> + token. Confirm in_stock, currency, packages[], recipient_required.
  5. Createweb_request POST /x402/invoice/create + token with { "items": [{ "product_id": "<slug>", "package_value": "<exact>" }] } (+ refill_input if top-up). Read invoice_id, price_usd.
  6. Confirm with user — show exact USDC total, product, denomination. Get explicit approval to pay.
  7. Pay — x402 on POST https://api.bitrefill.com/x402/invoice/pay with { invoice_id }, maxPayment just above price_usdapproval-mode.md → complete x402 request.
  8. Pollweb_request GET /x402/invoice/status?invoice_id=<id> + token until delivery_status is all_delivered.
  9. Codes — if redemption_info missing, run SIWX for codes with the paying wallet. Deliver code / pin securely (Risks & Warnings).

Path 2: Pay-per-call x402

  1. Confirm USDC on Base when needed.
  2. For each gated step: web_request → 402 → x402 pay that URL/method/body, maxPayment: "0.01"approval-mode.md.
  3. Follow next_step through detail → create → pay.
  4. Invoice pay: maxPayment just above price_usd.
  5. Poll status; SIWX for codes from paying wallet.

Path 3: CLI

T3 (login/verify) for list-orders. Create with --payment_method usdc_base. Pay the Base invoice — once buy-products returns invoice_id, agent picks one (follow agent_instructions):
  1. x402 — pay x402_payment_url via Base MCP x402 tools → approval-mode.md.
  2. Direct sendsend to payment_info address/amount on baseapproval-mode.md → poll CLI/get-invoice-by-id until paid.
Confirm amount and destination with the user. Poll until fulfilled (see Business domain).

Path 4: MCP

Install + OAuth → search-productsget-product-details → user approves → buy-products with payment_method: "usdc_base" → pay → poll → redeem. Pay the Base invoice — same as Path 3: x402 on x402_payment_url or send to payment_info. Poll get-invoice-by-id until invoice_status is payment_confirmed, then until invoice_status: complete / orders_delivery_status: all_delivered. Redemption: orders[].redemption_info.

Submission

Bitrefill uses Base MCP for reads, SIWX, x402, and direct USDC — not send_calls. Read tool names and schemas from the MCP catalog (SKILL.md).
Bitrefill stepBase MCPBitrefill-specific
Paths 1–2 API callsweb_requestHost api.bitrefill.com (allowlisted). Headers: X-Access-Token (raw JWT, not Authorization), sign-in-with-x, Content-Type. HTTP routing: custom-plugins.md
SIWX connect / codesget_wallets, signDecomposed SIWX payload in sign-in-with-x header — see Auth. EIP-55 checksum required
x402 micro-fees, invoice/pay, Path 3/4 x402_payment_urlx402 tools from MCP catalogmaxPayment: "0.01" for micro-fees; slightly above invoice price_usd for pay
Path 3/4 direct USDCsend{ chain: "base", asset: "USDC", recipient, amount } from payment_info
All write paths: approval-mode.md. On 402 responses, pay the Base USDC (eip155:8453) entry from accepts[].

Example prompts

$25 Amazon US — Path 1: Connect → JWT → search + token → detail → create → confirm → x402 pay → poll → deliver code. Browse, no session — Path 2: x402 micro-fee on each search/detail/create; SIWX for codes after pay. Existing account — Path 3/4: CLI or MCP catalog → Base USDC invoice → x402 or send → poll → redeem.

Risks & Warnings

  • pii — Redemption codes, eSIM QR URLs, PINs are bearer credentials. Never log, commit, or paste in public channels. Return codes only when the user explicitly asks.
  • irreversible — Digital goods are non-refundable once fulfilled. Confirm product, denomination, price, and payment before pay.
  • Invoice expiry — ~15 min price lock. Stale pay URL → create a new invoice.
  • Connect tokenX-Access-Token is a bearer secret (~2 h). Never echo in chat. Re-connect when expired.
  • EIP-55 checksum — mandatory for every SIWX flow; use helpers above.
  • CLI session~/.config/bitrefill-cli/<host>.v1.json is sensitive.

Notes

  • Country codes: Alpha-2 uppercase (US, IT).
  • X-Access-Token header only — Base MCP strips Authorization.
  • Fee schedule: search 0.002detail/checkout0.002 · detail/checkout 0.001 · create 0.002status0.002 · status 0.001.
  • Connect JWT TTL: default 120 minutes.
  • HTTP 500 on invoice/create — wrong package_value; retry without paying until onchain history confirms no charge.
  • 402 after SIWX send — stale nonce, wrong checksum, or malformed payload; re-fetch challenge and re-sign within 5 minutes.
  • 403 on SIWX route — wrong wallet; sign with the invoice payer.
  • INVOICE_NOT_PAYABLE on pay — already settled; poll status instead.
  • Docs: github.com/bitrefill/agents, docs.bitrefill.com