← Back to Portal

💳 Payment Method Playground

Change the card on a subscription — the four endpoints from [PM 1]–[PM 3], end to end.

1
Configure
2
Pick a subscription
3
Cards on file
4
Add a card

1. Configure

The publishable key is fetched from GET /payments/config using your project key, so there is no second key to paste. Override it below only if your project has none stored.
Sent as Authorization: Bearer …. Use a test key.

2. Pick a subscription GET /subscriptions

This is the subscriptionId the service returns, not the Stripe sub_….

3. Cards on file GET /subscriptions/:id/payment-methods · POST /subscriptions/:id/payment-method · DELETE /subscriptions/:id/payment-methods/:pm

The default shown here is the effective one. A subscription's own default_payment_method overrides the customer's invoice_settings, so this is the card that will actually be charged at renewal — not merely the customer default.
No subscription selected yet.

4. Add a card POST /subscriptions/:id/setup-intent → confirmCardSetup → POST /payment-method

The card is collected by a SetupIntent with usage: 'off_session', so 3D Secure is cleared now rather than failing the next renewal with authentication_required. Use the 3DS card below to exercise that challenge — it is the one path no unit test can cover.

🧪 Test cards (click to copy)

  • ✓ 4242 4242 4242 4242 — succeeds, no authentication
  • ⚠️ 4000 0025 0000 3155 — requires 3DS on setup
  • ⚠️ 4000 0027 6000 3184 — requires 3DS on every charge
  • ✗ 4000 0000 0000 0002 — generic decline
  • ✗ 4000 0000 0000 9995 — insufficient funds
  • ⚠️ 4000 0000 0000 0341 — attaches fine, then fails to charge (use this to watch invoiceRetry decline)
  • Any future expiry, any 3-digit CVC. Test mode only — full list.

API call log

Every request this page makes, with the raw response. The masked card shape is deliberate: a full Stripe PaymentMethod never leaves the service.

Nothing yet.