Frontier
x402 payments Frontier
Use x402 for machine-to-machine payments.
x402 is a protocol for internet payments. When a client requests a paid resource, your server returns an HTTP 402 response with payment details, including a Stripe deposit address. The client pays, then retries the request with authorization. After the facilitator settles the payment on-chain, Stripe records it as a PaymentIntent. This feature is available to businesses with physical locations in all US states except New York, and in more than 30 countries.
Note
To accept card payments alongside stablecoin payments, you should also integrate with the Machine Payments Protocol (MPP).
Before you begin
Regional considerations United States
Stablecoin payments are available to businesses in all US states, except New York. For businesses operating outside of the US, email with your Stripe account ID to request access to stablecoin payments in more than 30 countries.
To start accepting stablecoin payments:
- Make sure you’ve set up your Stripe account .
- Go to your Payment methods settings in the Dashboard and request the Stablecoins and Crypto payment method. If you want to accept stablecoin or crypto payments only for machine payments , create a separate payment method configuration dedicated to machine payments.
- Stripe reviews your access request and contacts you for more details if necessary. The payment method appears as Pending while we review your request.
- After we approve your request, the Stablecoins and Crypto payment method becomes active in the Dashboard.
Payment lifecycle
In this guide, you build the server. Your server indicates that payment is required and returns the content after successful payment. You interact with Stripe and a facilitator to complete the payment.
Use a coding agent
You can build an API that uses x402 with a single prompt to your coding agent:
Command Line
You can also follow the step-by-step guide below.
Create your Coinbase Developer account
x402 mainnet payments settle through the Coinbase Developer Platform (CDP) facilitator. Sign up for a Coinbase Developer Platform account, then create API keys to authenticate your facilitator client.
For details, see the Coinbase Developer Platform guide on running on mainnet.
Create a Stripe deposit address
Before you configure your server, create a crypto deposit address. This is the on-chain address where Base payments are sent.
Command Line
Store the returned address as your the related setting environment variable.
You can create deposit addresses as often as you want, but we recommend that you keep these calls off your core request path.
Install dependencies
Install the required dependencies:
Command Line
npm install @x402/core @x402/evm @x402/hono @coinbase/x402 hono @hono/node-server stripe
Create your endpoint
Configure your server with x402 payment verification. Use the deposit address from the previous step as the static payTo recipient.
This example requires 0.01 USD, paid in the related setting, per request to /paid.
Node.js
Create a PaymentIntent
Because you created the deposit address ahead of time, incoming payments on Base are sent to that static address. After the x402 facilitator settles a payment, record the on-chain transaction as a PaymentIntent using transaction_verification mode.
API version
This feature requires the 2026-05-27.preview API version. Set the Stripe-Version header to 2026-05-27.preview when you initialize your Stripe client.
Node.js
import Stripe from "stripe";
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
apiVersion: "2026-05-27.preview",
});
// Record settled on-chain payments as Stripe PaymentIntents using transaction_verification mode.
resourceServer.onAfterSettle(async ({ result, requirements }) => {
const txHash = result.transaction;
if (!txHash || !result.success) return;
// requirements.amount is in atomic USDC units (6 decimals).
// $0.01 = 10000 atomic units. Convert to cents for Stripe.
const amountInCents = Math.round(Number(requirements.amount) / 10000);
if (amountInCents < 1) return;
const pi = await stripe.paymentIntents.create(
{
amount: amountInCents,
currency: "usd",
confirm: true,
payment_method_data: { type: "crypto" },
allowed_payment_method_types: ["crypto"],
payment_method_options: {
crypto: {
mode: "transaction_verification",
transaction_verification_options: {
network: "base",
transaction_hash: txHash,
},
},
},
},
{ idempotencyKey: txHash },
);
console.log(`Recorded PaymentIntent ${pi.id} for tx ${txHash}`);
});
Test your endpoint
Make a request to your server without an eligible client to confirm it returns a 402 status code. Use -iv to see the response headers.
Command Line
curl -iv http://localhost:4242/paid
The response includes a payment-required header with a base64-encoded payment requirements payload:
> GET /paid HTTP/1.1
< HTTP/1.1 402 Payment Required
< payment-required: eyJ4NDAyVmVyc2lvbiI6MiwiZXJyb3IiO...
Next, make a request with an eligible client. Because you created the deposit address in live mode, this request moves real funds. Use Stripe’s purl to test from the command line.
Command Line
purl http://localhost:4242/paid
After a successful payment, the server returns the content. In the Dashboard, go to Payments to see the transaction.
Token and network support
PaymentIntents with the crypto payment method in mode: transaction_verification support the related setting on the following networks:
| Network | Token | Token contract address |
|---|---|---|
| Tempo | the related setting | 0x20c000000000000000000000b9537d11c60e8b50 |
| Base | the related setting | 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 |
| Solana | the related setting | EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v |
