How to Send a Stripe Card Update Link (Three Ways, and Which to Use)
When a subscriber's card fails, the fix is usually one thing: get them to a page where they can enter a working card. Stripe gives you three ways to do that without card details ever touching your servers. They behave differently in ways that matter.
Disclosure: we run Renewvane, a failed payment recovery service on Stripe. Stripe details were checked against Stripe's documentation on October 15, 2026.
Option 1: Let Stripe's own email carry the link (no code)
In your Dashboard's email settings, Stripe can send failed payment, expiring card and similar emails that "include a link to a page where the customer can update their payment method". You can point that link at a Stripe hosted Customer Portal or at your own subscription management page (Stripe docs: customer emails).
On the Stripe hosted page, the customer "can update their payment method for the relevant subscription and pay any outstanding invoices if applicable."
Watch out for: the link stops working in some cases, including when the subscription status changes to cancelled, incomplete_expired or unpaid, or when "The subscription's current renewal period expired" (same page).
Best for: teams that want something working today with no code.
Option 2: The hosted invoice page (pay now)
Every invoice has a hosted page. Its URL is on the invoice as hosted_invoice_url. On it, the customer can "Pay the invoice using any of the enabled payment methods" (Stripe docs: hosted invoice page).
Two details make this page especially useful for failed payments:
- It handles bank confirmation. If the payment needs 3D Secure, "the hosted invoice page displays the payment confirmation modal to your customer" (same page).
- It collects the money immediately, rather than waiting for the next retry.
Watch out for:
- Expiry. "Invoice URLs expire 30 days after the due date", and "the expiration window is never longer than 120 days." After that, Stripe sends the visitor to a page saying the link expired (same page). For a sequence that runs about ten days this is rarely a problem, but do not reuse old links.
- Saving the new card. For an invoice attached to a subscription, Stripe saves the payment method "only if the customer doesn't have a default invoice payment method" (same page). So paying this invoice may not fix next month's charge if an old default card is still on file. Pair it with Option 3 when the card itself is dead.
Best for: "authentication required" failures and temporary declines where you want the money now.
Option 3: A customer portal deep link straight to "update payment method"
The customer portal can open directly on a single task. The payment_method_update flow lets "your customer add a new payment method", and "The payment method is set as the customer.invoice_settings.default_payment_method" (Stripe docs: portal deep links).
Creating one looks like this (from Stripe's docs):
curl https://api.stripe.com/v1/billing_portal/sessions \
-u "<<YOUR_SECRET_KEY>>:" \
-d "customer={{CUSTOMER_ID}}" \
--data-urlencode "return_url=https://example.com/account/overview" \
-d "flow_data[type]=payment_method_update"
You can also set flow_data[after_completion] to send the customer back to your own page when they finish.
Watch out for:
- Session URLs are short lived. Stripe describes the
urlas the short lived URL of the session (Stripe API: portal session object). Do not paste a session URL into an email. Put your own link in the email, and when it is clicked, create a fresh session and redirect. - Configure the portal first. The portal is configured in the Dashboard, separately for live mode and each sandbox (Stripe docs: integrate the customer portal).
- The retry trap. Stripe retries using the subscription's own default payment method before the customer's default. Stripe's own warning: "if a subscription has a
default_payment_method, but you only updatecustomer.invoice_settings.default_payment_method, Stripe continues to retry on the subscription'sdefault_payment_method" (Stripe docs: Smart Retries). The portal flow updates the customer default. If your subscriptions set their own default payment method, also update the subscription when you seecustomer.updated, or pay the open invoice through Option 2.
Best for: expired, lost or replaced cards, where the customer needs a new card on file for the future.
Which one should you use?
| Situation | Our pick | Why |
|---|---|---|
| Expired or replaced card | Portal deep link, then retry or pay the open invoice | Fixes future charges, not just this one |
| Insufficient funds or temporary decline | Hosted invoice page | Takes payment now, when the customer is ready |
Bank wants a confirmation (authentication_required) |
Hosted invoice page | Shows the 3D Secure confirmation |
| No developer time | Stripe's own emails and hosted page | Works today with no code |
That table is our opinion. Test it on your own customers.
What access a third party needs
If a tool sends these links for you, it should not need your full secret key. Stripe's restricted keys start with rk_live_ or rk_test_, and "a RAK can do only what you give it permission to do". Stripe's comparison puts it plainly for third parties: a secret key is "Dangerous: gives full control to the third party", while a restricted key is "Safer: you hand out only the access the third party needs" (Stripe docs: restricted API keys).
For card update links, that usually means read access to invoices and customers, plus write access only for creating portal sessions. Our own service also asks for read access to events, payment intents, charges and payment methods, so it can notice failures and check how each invoice was paid. Permission names in the Dashboard change from time to time, so check them when you create the key.
How to tell if your links are doing anything
Clicks are not proof. Email security scanners click links, and Stripe's retries keep recovering some invoices on their own. Two checks give a clearer answer:
- Did the customer actually act through the link? For example, a new payment method added right after the click, or a bank confirmation completed on the page you sent them to.
- Did your emailed group recover more than a random holdout group that got no emails?
We use both checks in our own monthly proof report: it credits us with the smaller of two amounts, the measured lift after a safety margin for chance, and the payments where the subscriber clicked our link and then, within 7 days, paid through the page we opened with a new card or a bank confirmation. Our price is a flat $49 a month and does not depend on it; the report is there so you can see whether it is worth it. See how attribution works.
Sources
- Stripe docs, Automate customer emails: https://docs.stripe.com/billing/revenue-recovery/customer-emails
- Stripe docs, Hosted invoice page: https://docs.stripe.com/invoicing/hosted-invoice-page
- Stripe docs, Deep links in the customer portal: https://docs.stripe.com/customer-management/portal-deep-links
- Stripe API, Customer Portal Session object: https://docs.stripe.com/api/customer_portal/sessions/object
- Stripe docs, Integrate the customer portal with the API: https://docs.stripe.com/customer-management/integrate-customer-portal
- Stripe docs, Automate payment retries: https://docs.stripe.com/billing/revenue-recovery/smart-retries
- Stripe docs, Restricted API keys: https://docs.stripe.com/keys/restricted-api-keys
See your own number first. The free Leak Check takes a few totals from your own Stripe Dashboard and shows what is still lost after Stripe's retries. It runs in your browser with no Stripe access, and your numbers are never sent to us. If it is enough for our $49 a month plan to likely pay for itself (about $2,500 a month of failed payments across 20 or more failed payments), the plan will start with a 30 day free trial once it opens. The paid service is not open yet.