Creating Payment Methods
stripe402 clients do not need a Stripe account. The only thing a client needs is a credit card.
When a server responds with 402, it includes its own Stripe publishable key in the response. The client uses that key to tokenize their card into a PaymentMethod ID (pm_...) — the card details go directly to Stripe, never to the API server. The client then sends just the pm_... ID back to the server.
How It Works
1. Client hits paid endpoint
2. Server responds 402 with publishableKey: "pk_test_..."
3. Client uses that key to tokenize their card with Stripe → gets pm_...
4. Client retries the request with pm_...
5. Server charges the card and serves the resourceThe publishable key is available inside the onPaymentRequired callback as requirements.publishableKey.
Stripe Dashboard Requirement: Publishable Key Tokenization
Before clients can create PaymentMethods using raw card details (Methods 1, 3, and the create-pm script), the server operator must enable a Stripe dashboard setting:
Find "Publishable key card tokenization" (under "Advanced card tokenization controls" or similar)
Enable the toggle to allow creating PaymentMethods with a publishable key without Stripe's prebuilt UI elements
Save the setting
Without this, direct card tokenization via the API will fail with:
Why stripe402 requires this
Stripe disables this by default because most web apps should use Stripe Elements or Checkout for card collection, which provides PCI-compliant UI components. However, stripe402 is designed for programmatic, machine-to-machine payments — there is no browser UI for an AI agent or CLI tool to interact with.
Why this is safe
Card details go directly to Stripe's servers — the API server never sees raw card numbers. The publishable key creates a tokenized
pm_...reference, and only that token is sent to the API server.Publishable keys are designed to be public — they can only create tokens, not charge cards or read account data.
The setting only affects tokenization on the server operator's own Stripe account — each server operator controls their own toggle.
Browser clients using Stripe.js Elements are unaffected — this setting is only needed for headless/API-based tokenization (Method 2 below works without it).
Note for server operators: This setting applies to your Stripe account. You only need to enable it once, and it covers all stripe402 clients that use your publishable key for headless tokenization.
Method 1: Headless / Node.js Client (Card Details in Code)
For AI agents, server-to-server, or any headless client. Use the Stripe SDK with the publishable key from the 402 response and your card details:
Key points:
requirements.publishableKeycomes from the 402 response — the server provides itThe Stripe SDK sends card details directly to Stripe's servers, not to the API server
The client only sends the resulting
pm_...ID to the API serverNo Stripe account or secret key is needed on the client side
With Axios
Caching the PaymentMethod
You can create the PaymentMethod once and reuse the pm_... ID. Once cached, subsequent 402 responses skip the Stripe call:
Note: The cached pm_... ID is tied to the server's Stripe account (since it was created with the server's publishable key). If you're calling multiple stripe402 APIs on different Stripe accounts, each will produce a different pm_... ID.
PCI Compliance Note
Handling raw card numbers in code (even when sending them directly to Stripe) technically puts you in PCI SAQ-D scope. For automated systems and AI agents, this is often acceptable because:
Card details go directly to Stripe, never to the API server
The API server only sees the tokenized
pm_...IDThe agent's environment should be secured regardless
For user-facing applications, use Stripe.js in the browser instead (see below).
Method 2: Browser Client (Stripe.js)
For web applications where end users enter their own card details. This is the most secure approach — card data is handled entirely by Stripe's hosted iframe, never touching your code (SAQ-A compliance).
Setup
Or with npm:
Complete Browser Example
The key insight: requirements.publishableKey is the server's key, provided automatically in the 402 response. The client never needs their own Stripe account.
Method 3: Utility Script (for Testing)
The example app includes a script that creates a PaymentMethod from test card details. It uses the publishable key (not the secret key):
Output:
The script requires STRIPE_PUBLISHABLE_KEY in your .env file (the pk_test_... key, not the secret key).
Common Test Card Numbers
4242424242424242
Visa
Default test card
5555555555554444
Mastercard
378282246310005
Amex
6011111111111117
Discover
4000000000000002
Always declines
For testing error handling
Full list: Stripe Testing Documentation
Method 4: Stripe CLI (for Server Operators)
Server operators (who have Stripe accounts) can also create test PaymentMethods via the CLI:
This uses test tokens and requires a Stripe account login. This is for server-side testing only — clients never need the Stripe CLI.
Summary
Browser user
Credit card
Stripe.js Elements + publishable key from 402 response
AI agent / headless client
Credit card details
Stripe SDK + publishable key from 402 response
Server operator (testing)
Stripe account
CLI, SDK with secret key, or utility script
The critical design point: clients never need a Stripe account. The server's publishable key — provided in every 402 response — is all they need to tokenize a card.
PaymentMethod Lifecycle
Once created, a PaymentMethod ID (pm_...) is:
Reusable: The same ID can be sent on every request — the server only charges when the balance is insufficient
Persistent: Valid until the underlying card expires
Server-scoped: Tied to the server's Stripe account (the publishable key used to create it)
Not a card number: A tokenized reference — safe to store, transmit, and log
Safe to Reuse on Every Request
Clients can send the same paymentMethodId on every request without worrying about being charged multiple times. The server derives a clientId from the card's fingerprint and checks for existing credits before charging:
Credits sufficient: deducts from balance, no charge created
Credits insufficient: charges the card for a new top-up, then deducts
This means simple clients (like shell scripts using curl) can use the same payment header repeatedly. The card is only charged when the balance actually runs out. For optimal performance, clients should switch to sending just the clientId (from the payment-response header) after the first request, which avoids the Stripe API call to look up the card fingerprint on every request.
Last updated