Skip to main content
HomeLanding pagesHow to add crypto payments to an API
LANDING PAGE

How to add crypto payments to an API

7 min read·Last updated June 2, 2026

The clean way to add crypto payments to an API is USDC on Base, charged per call with x402. Mount createX402Plugin or createX402Middleware from @blockchain0x/x402 on the routes you want paid; the adapter returns a 402 with a price and verifies the X-Payment header before your handler runs. That beats posting a wallet address because you know which call was paid.

What adding crypto payments means

You want your API to accept crypto, so a caller pays in a digital currency rather than a card. For an API, accepting crypto really means two things: receiving the funds, and knowing which request a payment was for so you can gate access. The first is easy; the second is where most naive approaches fall down, and it is the part that decides whether your crypto payments actually work as a paywall rather than just a tip jar.

The clean answer for an API, especially one called by programs and agents, is USDC on Base charged per request through x402. This page explains why that is the right approach and how it compares to the obvious-but-weaker alternative, then wires it. For the focused x402 mechanics see how-to-add-x402-to-my-api, and for the stablecoin angle see how-to-accept-stablecoin-payments-as-agent. The payment API product page is the broader reference.

The naive way and why it falls short

The first idea most people have is to post a wallet address and ask callers to send crypto to it. It receives money, so it feels like accepting crypto payments, but it breaks as an API paywall for one reason: a bare transfer to an address carries no link to a specific API request.

When USDC lands at your address, you know someone paid, but not which call it was for, not whether it covered the price of the route they want, and not how to let exactly that request through. You end up building a reconciliation layer to match payments to requests, and racing to gate access after the fact. It also pushes volatility and chain choice onto the caller, and gives them no standard way to know the price before paying. Posting an address is fine for tips or donations. As the payment layer for an API that gates access per call, it is the wrong tool, because the one thing an API paywall needs, tying a payment to a request, is the one thing it does not give you.

Prerequisites

  • A Blockchain0x account with an agent created, so you have a wallet and a payToAddress.
  • A sk_test_ key and a paymentRequestId for each priced route.
  • An existing Fastify or Express API on Node 18+. The SDK targets >=18.
BASH
export B0X_API_KEY=sk_test_...
export B0X_PAYTO_ADDRESS=0x...

The modern way: x402 per call

x402 fixes exactly the gap the address approach leaves. The API answers an unpaid request with HTTP 402 and a quoted price; the caller pays in USDC and retries the same request with proof; the API verifies and serves. Because the payment rides on the request, it is tied to that request by construction. You know what was paid for, you know it covered the price, and you let through exactly that call. No reconciliation layer, no after-the-fact matching.

It settles in USDC on Base, so you price in dollars without token volatility, and the caller sees the price in the 402 before paying. For an API whose callers are programs, this is the difference between accepting crypto and actually running a crypto paywall.

Wire it

Mount the adapter on the routes you want paid. Fastify:

TYPESCRIPT
import { createClient } from "@blockchain0x/node";
import { createX402Plugin } from "@blockchain0x/x402/server/fastify";

const sdk = createClient({ apiKey: process.env.B0X_API_KEY! });

await app.register(createX402Plugin, {
  sdk,
  defaultNetwork: "testnet",
  pricing: {
    "POST /v1/translate": { amountUsdc: "0.02", payToAddress: process.env.B0X_PAYTO_ADDRESS!, paymentRequestId: "pr_translate" },
  },
});

app.post("/v1/translate", existingTranslateHandler); // runs only once paid

Express is the same with createX402Middleware({ sdk, defaultNetwork, pricing }) passed to app.use. Your handler is unchanged; the adapter gates its route, returns the 402 to unpaid callers, and verifies the X-Payment header through the SDK before your handler runs.

What you get that an address does not

It is worth naming the concrete wins over posting an address, because they are the reason to do it this way.

You get payment tied to request: every paid call is verifiably for that call at that price, so gating is automatic, not reconciled. You get a quoted price: the caller learns the cost from the 402 instead of guessing, which is what lets an agent decide whether to pay. You get dollar pricing: USDC means your 0.02 is two cents regardless of market moves. You get no key handling: you configure a payToAddress and the adapter verifies through the SDK, rather than running wallet infrastructure. And you get a standard callers already speak: any x402 runtime pays your API with no custom integration. Posting an address gives you none of these; it gives you a pile of incoming transfers you have to make sense of.

Crypto payments versus a card

Adding crypto does not mean ripping out card payments, and it is worth being clear about when each one wins so you add crypto for the right reasons.

A card is the better rail when your payer is a human buying occasionally, when amounts are large, or when you need consumer protections like chargebacks. The card networks are built for that, and crypto would only add friction. Crypto, specifically USDC on Base via x402, wins when your payer is a program making many small payments with no human to onboard. A card cannot economically authorize a half-cent charge, and an agent cannot fill in a checkout form, so for machine traffic crypto is not a preference, it is the only rail that fits.

The practical answer for many APIs is both, on different routes: keep card-based access for your human customers and add x402 to the endpoints that agents call. They do not interfere, because each lives on its own routes, and you are extending the API to a new kind of payer rather than migrating your existing one. Add crypto where the traffic is machine-driven, and leave the human path on whatever already serves it well.

Test on Base Sepolia

Run it on testnet first. With defaultNetwork: "testnet" and a sk_test_ key, call a priced route with no X-Payment header and confirm the 402 quotes the right amount; pay it from a test wallet and confirm your handler runs; confirm unpriced routes still return normally. When the paid and free paths both behave, set defaultNetwork to mainnet and swap to a sk_live_ key for Base.

Common pitfalls

Three traps.

Treating an address as a paywall. Receiving at an address is not gating access. Use x402 so payment is tied to the request; reserve bare addresses for tips and donations.

Pricing in a volatile token. Quote in USDC so a two-cent route stays two cents. Pricing API access in a volatile asset makes your prices move for no reason.

Flipping a live route to 402 without notice. Moving an existing free endpoint behind the paywall breaks non-x402 clients. Roll it out as a breaking change on a new path with deprecation.

What you get today

Mount the adapter on one route, confirm an unpaid call gets the 402 and a paid call runs, and you are accepting crypto payments the way an API should, tied to requests, priced in dollars, with no key handling. For the focused x402 mechanics see how-to-add-x402-to-my-api. Pricing is on the pricing page.

FAQ

Frequently asked questions.

What is the simplest way to accept crypto on an API?

Posting a wallet address technically works for receiving, but it does not tell you which API call a payment was for, so it cannot gate access per request. The clean way is x402: the API returns a 402 with a price, the caller pays in USDC, and the verified payment is tied to that exact request. You accept crypto and know what it bought.

Which crypto do callers pay in?

USDC on Base, a dollar-pegged stablecoin with 6 decimals. It is the only settlement token in the current exact-usdc scheme. Using a stablecoin means you price in dollars and are not exposed to token volatility between the quote and the payment, which matters for an API charging small amounts.

Do I need to handle wallets or private keys?

No. Your API receives into the agent wallet provisioned for you, and you never hold keys. The adapter verifies payments through the SDK; you configure a payToAddress and a price per route. The crypto mechanics happen on the payer side and in settlement, not in your handler.

Is this only for AI agents?

It fits agent and machine traffic best, because those callers pay per request automatically. A human-facing API can use it too, but humans are often better served by a card. The sweet spot is an API whose callers are programs making many small paid calls, where x402 prices traffic a card cannot.

How is this different from the x402 guide?

This page is the crypto-payments entry point: why USDC-on-Base-via-x402 is the right approach and how it compares to just sharing an address. how-to-add-x402-to-my-api is the focused x402 mechanics. If you already know you want x402, start there; if you are deciding how to accept crypto at all, start here.

Create your free agent wallet in 5 minutes.

First payment confirmed in under ten minutes. Free to start.