Skip to content
Create account or Sign in
The Stripe Docs logo
/
Ask AI
Create accountSign in
Get started
Payments
Revenue
Platforms and marketplaces
Money management
Developer resources
APIs & SDKsHelp
OverviewAccept a paymentUpgrade your integration
Online payments
OverviewFind your use case
Use Payment Links
Use a prebuilt checkout page
Build a custom integration with Elements
Build an in-app integration
Use Managed Payments
Recurring payments
In-person payments
Terminal
Payment methods
Add payment methods
Manage payment methods
Faster checkout with Link
Payment operations
Analytics
Balances and settlement time
Compliance and security
Currencies
Declines
Disputes
Radar fraud protection
Payouts
ReceiptsRefunds and cancellations
Advanced integrations
Custom payment flows
Flexible acquiring
Off-Session Payments
Multiprocessor orchestration
Beyond payments
Incorporate your company
Crypto
Agentic commerce
Machine payments
    Overview
    Quickstart
    x402
Financial Connections
Climate
Verify identities
United States
English (United States)
  1. Home/
  2. Payments/
  3. Machine payments

x402 paymentsPrivate preview

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. The client pays, then retries the request with an authorization. Stripe handles deposit addresses and automatically captures the PaymentIntent when funds settle on-chain.

GitHub

You can find the app’s complete source code on GitHub.

Before you begin

  • A Stripe account.
  • Crypto payins enabled for your account.
  • Machine payments enabled for your account. Contact machine-payments@stripe.com.

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.

Create your endpoint

Add payment middleware to your endpoint to require payment.

This example requires 0.01 USD, paid in USDC, per request to /paid.

Node.js
Python
No results
import { paymentMiddleware } from "@x402/hono"; import { x402ResourceServer, HTTPFacilitatorClient } from "@x402/core/server"; import { ExactEvmScheme } from "@x402/evm/exact/server"; app.use( paymentMiddleware( { "GET /paid": { accepts: [ { scheme: "exact", price: "$0.01", network: "eip155:84532", payTo: createPayToAddress, } ], description: "Data retrieval endpoint", mimeType: "application/json", } }, new x402ResourceServer(facilitatorClient).register( "eip155:84532", new ExactEvmScheme() ) ) )

Create a PaymentIntent

To process payments, create a PaymentIntent that accepts the crypto payment method. Use the payTo method from earlier.

API version

This feature requires the 2026-03-04.preview API version. Set the Stripe-Version header to 2026-03-04.preview when initializing your Stripe client.

Node.js
Python
No results
import Stripe from "stripe"; const stripe = new Stripe(process.env.STRIPE_SECRET_KEY, { apiVersion: "2026-03-04.preview", }); const validPayToAddresses = new Set<string>(); async function createPayToAddress(context) { // If a payment header exists, extract the destination address from it if (context.paymentHeader) { const decoded = JSON.parse( Buffer.from(context.paymentHeader, "base64").toString() ); const toAddress = decoded.payload?.authorization?.to; if (toAddress && typeof toAddress === "string") { if (!validPayToAddresses.has(toAddress)) { throw new Error("Invalid payTo address: not found in server cache"); } return toAddress; } throw new Error( "PaymentIntent did not return expected crypto deposit details" ); } // Create a new PaymentIntent to get a fresh crypto deposit address const decimals = 6; // USDC has 6 decimals const amountInCents = Number(10000) / Math.pow(10, decimals - 2); const paymentIntent = await stripe.paymentIntents.create({ amount: amountInCents, currency: "usd", payment_method_types: ["crypto"], payment_method_data: { type: "crypto", }, payment_method_options: { crypto: { // @ts-ignore - Stripe crypto payments beta feature mode: "deposit", deposit_options: { networks: ["base"], }, }, }, confirm: true, }); if ( !paymentIntent.next_action || !("crypto_display_details" in paymentIntent.next_action) ) { throw new Error( "PaymentIntent did not return expected crypto deposit details" ); } // Extract the Base network deposit address from the PaymentIntent const depositDetails = paymentIntent.next_action .crypto_display_details; const payToAddress = depositDetails.deposit_addresses["base"].address; console.log( `Created PaymentIntent ${paymentIntent.id} for $${( amountInCents / 100 ).toFixed(2)} -> ${payToAddress}` ); validPayToAddresses.add(payToAddress); return payToAddress; }

This function returns a crypto deposit address that the client receives and uses for payment.

The PaymentIntent response includes deposit addresses with supported_tokens, which lists the accepted tokens and their contract addresses for each network:

{ "id": "pi_123", "amount": 5000, "currency": "usd", "status": "requires_action", "next_action": { "type": "crypto_display_details", "crypto_display_details": { "deposit_addresses": { "base": { "address": "0xbase_address", "supported_tokens": [ { "token_currency": "usdc", "token_contract_address": "0x…" } ] } } } } }

For more details on how crypto PaymentIntents work, including deposit addresses, payment lifecycle, and supported networks, see the deposit mode integration guide.

Test your endpoint

Make a request to your server without an eligible client to confirm it returns a 402 status code.

Command Line
curl http://localhost:3000/paid

You see a 402 status code.

Next, make a request with an eligible client. Use Stripe’s purl to test in the command line.

Command Line
purl http://localhost:3000/paid

Sandboxes and testnet

PaymentIntents that you create in a sandbox don’t monitor crypto testnets, so we can’t automatically detect testnet transactions that you send. To test sandbox PaymentIntents, use the test helper endpoint to simulate crypto deposits. Learn more about testing your integration.

If you connected a wallet, the server returns the content and you can confirm payment. Visit the Stripe Dashboard Payments page to see the transaction.

Alternatively, you can use curl to fetch the latest payments from the Stripe API:

Command Line
curl https://api.stripe.com/v1/payment_intents?limit=10 \ -u
sk_test_BQokikJOvBiI2HlWgH4olfQ2
:

Run mainnet transactions

To run mainnet transactions, integrate with an x402 facilitator that supports mainnet.

See the Coinbase Developer Platform guide to use the CDP Facilitator.

Token and network support

PaymentIntents with the crypto payment method in mode: deposit support USDC on the following networks:

NetworkTokenToken contract address
TempoUSDC0x20c000000000000000000000b9537d11c60e8b50
BaseUSDC0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913
SolanaUSDCEPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
Was this page helpful?
YesNo
  • Need help? Contact Support.
  • Chat with Stripe developers on Discord.
  • Check out our changelog.
  • Questions? Contact Sales.
  • LLM? Read llms.txt.
  • Powered by Markdoc
On this page
Related Guides
Deposit-mode crypto PaymentIntents