Saving payment methods
A saved payment method lives on a customer and can be charged again without re-entering card or bank details. There are two ways one gets created — during a checkout (the component/hosted page saves the method the payer just used) and directly via the platform API (server-to-server). Both produce the same saved method: it shows up in the customer’s wallet and is charged the same way.
This guide covers the checkout path and how it connects to the wallet. For the pure server-to-server flow (create customer → save method → charge), see Customers & wallets.
1. Make the session save-capable
Section titled “1. Make the session save-capable”Saving is opt-in per session. Pass a customer_id (so there’s a wallet to save into) and
setup_future_usage when you create the session:
{ "amount": 14227, "currency": "USD", "customer_id": "cus_88420", "setup_future_usage": "on_session"}setup_future_usage | Effect |
|---|---|
off (or omitted) | Never offer to save. No save UI is shown. |
on_session | Offer to save for future customer-present payments (wallet). |
off_session | Offer to save for merchant-initiated payments (autopay). |
customer_id is your own identifier for the payer (the same one Customers & wallets
uses as reference_id). Without it there’s nowhere to save the method.
2. The payer opts in at checkout
Section titled “2. The payer opts in at checkout”When the session is save-capable and the payer enters a new card or bank account, the
component/hosted page shows a “Save this payment method to my wallet” checkbox (default checked).
The method is saved only if it’s checked — see the
setup-future-usage attribute. The checkbox is hidden for Apple Pay and
when an already-saved method is selected.
Admin/agent “capture a new method” flows can set
new-method-onlyto hide the saved-method selector while still saving the new method to the customer’s wallet.
3. Read the result
Section titled “3. Read the result”On success the confirm result (and the payment.success event) carries saved_method_id when a
method was saved:
payment.addEventListener('payment.success', (e) => { const { paymentUid, savedMethodId } = e.detail; if (savedMethodId) { // The payer saved this method. It's now in their wallet — nothing else to do here; // the canonical record arrives on the checkout_session.completed webhook. }});The webhook (checkout_session.completed) is the source of truth for both the payment and the
saved method — fulfill and reconcile from it, not the browser event. See Webhooks.
4. Offer the saved method next time
Section titled “4. Offer the saved method next time”Create the next session with the same customer_id and the checkout automatically surfaces that
customer’s saved cards and bank accounts (sanitized — brand/bank + last4 only). The payer picks one
instead of re-entering details; no setup_future_usage is needed just to use an existing method.
To manage methods directly (list, set default, delete) or to charge one server-to-server with
wallet_credit / wallet_ach, use the platform wallet API — the
saved_method_id from checkout is the same saved_payment_method_uid those endpoints operate on.
How the two paths relate
Section titled “How the two paths relate”| Saved during checkout | Saved via the API | |
|---|---|---|
| Who saves it | The payer, by checking the box | Your server, after tokenizing |
| Trigger | setup_future_usage + customer_id on the session | POST /api/customers/{uid}/payment-methods |
| You get back | saved_method_id (result + webhook) | saved_payment_method_uid |
| Result | Identical — one saved method on the customer’s wallet, reusable either way |
ACH note
Section titled “ACH note”For bank-account (ACH) saves, the same NACHA authorization applies as for the charge — the component
shows the SEC-code-appropriate authorization affirmation (see
ach-sec-code) before the debit, and the accepted mandate is recorded with
the payment.