# x402 payments Use x402 for machine-to-machine payments. Find the app’s [complete source code](https://github.com/stripe-samples/machine-payments) on GitHub. [x402](https://x402.org) 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 Authorisation. After the facilitator settles the Payment on-chain, Stripe records it as a [PaymentIntent](https://docs.stripe.com/api/payment_intents.md). This feature is available to businesses with physical locations in all US states except New York, and in [more than 30 countries](https://docs.stripe.com/payments/machine.md). ## Before you begin > Stablecoin payments are available to businesses in all US states, except New York. For businesses operating outside of the US, email [machine-payments@stripe.com](mailto:machine-payments@stripe.com) with your Stripe account ID to request access to stablecoin payments in 30+ countries. To start accepting stablecoin payments: 1. Make sure you’ve [set up your Stripe account](https://dashboard.stripe.com/register). 2. Go to your [Payment methods](https://dashboard.stripe.com/settings/payment_methods) settings in the Dashboard and request the **Stablecoins and Crypto** payment method. If you only want to accept stablecoin or crypto payments for [machine payments](https://docs.stripe.com/payments/machine.md), we recommend creating a separate [payment method configuration](https://docs.stripe.com/payments/payment-method-configurations.md) dedicated to machine payments. 3. Stripe reviews your access request and contacts you for more details if necessary. The payment method appears as **Pending** while we review your request. 4. After we approve your request, the **Stablecoins and Cryptocurrency** 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. A diagram showing the x402 payment flow between client, server, Stripe, and facilitator (See full diagram at https://docs.stripe.com/payments/machine/x402) ## Use a coding agent You can build an API that uses x402 with a single prompt to your coding agent: ```bash Read https://docs.stripe.com/payments/machine/x402.md?lang=node, and create an API that uses x402 to charge for access using the Base network for crypto. ``` 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](https://portal.cdp.coinbase.com/), then create API keys to Authenticate your facilitator Client. For details, see the Coinbase Developer Platform guide on [running on mainnet](https://docs.cdp.coinbase.com/x402/quickstart-for-sellers#running-on-mainnet). ## Create a Stripe Deposit address Before you configure your Server, create a Cryptocurrency Deposit address. This is the on-chain address where Base payments are sent. ```bash stripe post /v1/crypto/deposit_addresses --live --stripe-version 2026-05-27.preview -d network=base ``` Store the returned address as your `DEPOSIT_ADDRESS` 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. ## Create your endpoint Add Payment middleware to your Endpoint to require Payment. Use the Deposit address from the previous step as the static `payTo` recipient. This example requires 0.01 USD, paid in USDC, per request to `/paid`. #### Node.js ```node import { x402ResourceServer, x402HTTPResourceServer, HTTPFacilitatorClient, } from "@x402/core/server"; import { ExactEvmScheme } from "@x402/evm/exact/server"; import { facilitator } from "@coinbase/x402"; const facilitatorClient = new HTTPFacilitatorClient(facilitator); const resourceServer = new x402ResourceServer(facilitatorClient).register( "eip155:8453", new ExactEvmScheme(), ); const httpServer = new x402HTTPResourceServer(resourceServer, { "GET /paid": { accepts: [ { scheme: "exact", price: "$0.01", network: "eip155:8453", payTo: process.env.DEPOSIT_ADDRESS, }, ], description: "Data retrieval endpoint", mimeType: "application/json", }, }); // Register the payment middleware so it intercepts requests to your endpoint. app.use(httpServer.middleware()); ``` ## 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](https://docs.stripe.com/api/payment_intents.md) 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 ```node import Stripe from "stripe"; const stripe = new Stripe(process.env.STRIPE_SECRET_KEY, { apiVersion: "2026-05-27.preview", }); // Call this after the x402 middleware settles a payment. The settlement // result includes the on-chain transaction hash and network. async function recordPayment(settlement) { const txHash = settlement.transaction; if (!txHash) return; const pi = await stripe.paymentIntents.create( { // Use the amount the client actually paid, in the smallest currency unit. amount: settlement.amount, currency: "usd", confirm: true, payment_method_data: { type: "crypto" }, 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. ```bash curl -iv http://localhost:3000/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](https://github.com/stripe/purl) to test from the command line. ```bash purl http://localhost:3000/paid ``` After a successful Payment, the Server returns the content. In the [Dashboard](https://dashboard.stripe.com), go to **Payments** to see the Transaction. ## Token and network support `PaymentIntents` with the `crypto` payment method in `mode: transaction_verification` support USDC on the following networks: | Network | Token | Token contract address | | --- | --- | --- | | Tempo | USDC | `0x20c000000000000000000000b9537d11c60e8b50` | | Base | USDC | `0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913` | | Solana | USDC | `EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v` |