Mintcash
Guides

Update a card on a subscription

How to hand a customer a page where they put a new card on their subscription.

Cards get lost, reissued, and expire mid-subscription. POST /subscriptions/{id}/card-update returns a URL where the customer enters a new one — and once they pay with it, that card becomes the one every future renewal bills.

Choosing a mode

mode decides which surface the returned url opens. It defaults to embedded.

 hostedembedded (default)
What you getA complete page, branded with your theme and logoThe bare card form
What you seeAmount owed, billing period, plan, the card that failedYou can completely customize the page
Where it goesEmail, SMS or as part of your website, sent it to the customer as-isAn iframe in your own account or billing page

Pick hosted when the link travels to the customer on its own and has to stand up without context. Pick embedded when the customer is already signed in to your product — on an account or billing screen — and you are supplying the context yourself.

hosted

A complete, self-contained page carrying everything the customer needs to act on: who is asking, what is owed, what they are agreeing to from here, the card that is being replaced, and the form. It follows your checkout theme, so it arrives in your branding, not MintCash's.

mode: hosted — secure.mintcash.me/r/<token>
AAcme Payments Ltd

Update your card on your Acme Payments Ltd subscription

Your subscription
Renews$4.99 every 30 days1 of 3 intro payments left
Then$9.99 every 30 daysfrom 21 Nov 2026
Next renewal22 Oct 2026
Card on fileMastercard •••• 0000
Member since22 Sep 2026
Pay with a new card
Card details0000 0000 0000 0000
Expiry dateMM / YY
Security codeCVC
Pay $4.99 and update my card

By paying you authorise Acme Payments Ltd to charge this card $4.99 now, then $4.99 every 30 days for 1 more payment, then $9.99 every 30 days until you cancel. This card replaces the Mastercard •••• 0000 for all future payments.

Secured by MintCashQuestions? ops@acme-payments.example

The mandate line under the button spells out the whole commitment — the amount now, the remaining intro payments, the recurring price it steps up to, and the card being replaced — so the customer is agreeing to the full schedule rather than just today's charge.

embedded

The same card fields with nothing around them, sized to drop into an iframe on a page of your own. No merchant header, no subscription summary, no mandate copy: that context is yours to supply, and you should — the customer is authorising future renewals either way.

mode: embedded — secure.mintcash.me/c/<session>
Card details0000 0000 0000 0000
Expiry dateMM / YY
Security codeCVC
Save this card for future paymentsPay $4.99
const res = await fetch(
  `https://sandbox.mintcash.me/subscriptions/${subscriptionId}/card-update`,
  {
    method: "POST",
    headers: { Authorization: ..., "Content-Type": "application/json" },
    body: JSON.stringify({
      mode: "hosted",
      returnUrl: "https://example.com/account/billing",
    }),
  },
);

const { url, mode } = await res.json();
// url  → https://secure.mintcash.me/r/GzB1k...  (send this to the customer)
// mode → "hosted"

When you can call it

Active subscriptions can't change card yet

This endpoint only opens up once a renewal has already failed and the subscription has moved to past_due. Changing the card on a healthy active subscription is on the roadmap but is not available today — the call is rejected with 400.

Three conditions, all checked before a link is minted:

ConditionWhy
Subscription is past_dueA renewal must have failed first; a cancelled subscription is terminal.
It has an unsettled invoiceThere must be a failed renewal for the new card to pay. A settled invoice has nothing owing.
No scheduled retry is mid-chargeMintCash refuses to race its own retry on the old card rather than risk a double charge.

Anything else comes back as 400, except a spent attempt cap, which is 429. The API reference lists every status this endpoint returns.

If a customer wants to move to a different card while their subscription is still healthy, the only route today is to cancel it and create a new one with the new card token, which resets the billing period. Otherwise the next failed renewal opens this flow — and MintCash emails them a card-update link at that point anyway.

The flow

Rendering diagram…

The new card has to actually pay before it replaces the old one. On a successful charge, in one transaction:

  1. The failed invoice is settled and the subscription returns to active.
  2. The subscription's payment method is swapped to the new card, so every future renewal bills it.
  3. The link is consumed, therefore it cannot be used again.

You receive subscription.succeeded, and alongside it subscription.payment_method_updated carrying the new card and the previousToken it replaced, so you can update your own stored copy. The event fires on every swap; the token fields are only filled in when the customer consented to saving the card. See Event types.

The two are not strictly paired: if a scheduled retry settled the invoice first, that charge is flagged for refund and its subscription.succeeded is suppressed, but the card change still applies and subscription.payment_method_updated fires on its own.

The old card is not deleted

Payment methods are shared across a customer's other subscriptions and saved-card charges, so the card that was failing stays on file. Only this subscription moves to the new one.

A decline is not the end of the link: the customer can try another card until the invoice's attempt cap is spent.

Wait for the webhook

A 200 from this endpoint means a link was minted, not that anything was paid and not that the card changed. Treat subscription.succeeded as the signal to restore access, exactly as you would for any other subscription charge.

Notes

  • embedded URLs are short-lived. hosted hands back the recovery link itself, so it survives 7 days in an inbox. embedded hands back a checkout session, which expires after 15 minutes. Mint it when the customer is actually looking at the page, not ahead of time. Calling again after it lapses returns a fresh session on the same link, and costs nothing against the attempt cap.
  • Opening a link is free. Only a submitted card counts against the cap, so a customer who opens the page and leaves — or a mail scanner that prefetches the link — costs nothing.
  • The cap is per invoice, not per link. Minting a new link does not buy more attempts. Once the five are spent, every link on that invoice stops working: this endpoint returns 429, and any link already in the customer's hands opens on a dead-end page instead of a card form.
  • Wallets are hidden. Apple Pay and Google Pay are not offered on either surface: a wallet sale leaves no token that renewals could bill.
  • hosted never asks whether to save the card. Handing it over for future renewals is the whole point of that page, so there is no opt-in checkbox. embedded is the standard checkout form, so your account's save-cards setting decides whether the checkbox appears there. Either way the card becomes the subscription's payment method — the checkbox only governs whether the reusable token is returned to you on the webhook.

It does not pause dunning

Handing out a card-update link does not suspend the retry schedule:

  • Scheduled retries keep running against the old card while the link is live.
  • A failed attempt on the link does not advance the ladder, and does not bring the cancellation date closer.
  • Whichever charge settles the invoice first wins. If a scheduled retry succeeds while the customer is paying, the customer's charge is flagged for refund rather than kept.
  • If every scheduled retry is exhausted, the subscription is cancelled and the link dies with it — even if it still has days of TTL left.

See also