Stripe's Billing Portal Can Now Deep-Link to 'Update Your Details.' Most Dunning Emails Only Link to 'Update Your Card.'
Stripe quietly shipped a customer_update portal deep link on Aug 26 — for a decline category dunning flows built for card failures still miss.
On August 26, 2026, Stripe added a new value to the billing portal's flow_data.type parameter: customer_update. It's a small, easy-to-miss line in a changelog dominated that same day by a much louder release — the Billing.FeedbackOption API we covered in our look at Stripe's custom cancellation reasons. But this one touches a different part of the churn stack entirely, and it's worth pulling apart on its own, because it exposes a gap most dunning setups have been quietly living with for years: they only know how to send a customer to fix their card.
What actually shipped on August 26
Stripe's own changelog entry is direct about it: setting flow_data.type to customer_update "creates a deep link that navigates your customer directly to the billing information page in the customer portal, where they can update their details." That's it — no new object, no new webhook events, just a new destination you can point a portal session at. It's additive: Stripe is explicit that "no changes are required for existing integrations," so nothing breaks if you never touch it.
What makes it worth a second look is what "billing information" actually means here, because it's a different page from the one most SaaS dunning flows already link to. The portal's customer_update flow lets a customer edit their name, email, billing address, and tax ID. It does not touch their card. For that, the portal has had a separate flow for years: payment_method_update. Stripe now has five distinct portal deep links, and each one exists because it maps to a genuinely different action a customer needs to take.
| Flow type | What it lets the customer do | When your dunning logic should route here |
|---|---|---|
payment_method_update | Add or replace a card, set as default payment method | Card-level failures — expired_card, insufficient_funds, invalid_number |
customer_update | Edit billing address, tax ID, name, email | Address- or tax-ID-level failures — incorrect_address, incorrect_zip, rejected invoices |
subscription_update | Upgrade, downgrade, or change plan quantity | Feature-ceiling or price-fit cancellation reasons |
subscription_update_confirm | Confirm a specific plan change you’ve already priced out | When you own the pricing UI and just need Stripe to handle proration and 3DS |
subscription_cancel | Cancel a specific subscription | The cancellation flow itself, not recovery |
Why "update your card" was never the whole fix
Our own guide to Stripe dunning makes the case that every recovery email should link straight to the customer portal rather than making someone hunt for a settings page — friction in the update flow is a silent recovery killer. That advice still holds. What it assumed, reasonably at the time, is that the update a failing customer needs is almost always a card update. For a meaningful slice of failures, it isn't.
Stripe's own decline-code taxonomy separates these cleanly, and we went deep on how that taxonomy now travels consistently across payment methods in our piece on Stripe's unified decline vocabulary. Two codes in particular describe a completely different failure mode than a bad card: incorrect_address, where "the address entered by the customer is incorrect," and incorrect_zip, where "the postal code is incorrect." Neither of those is fixed by adding a new card. They're fixed by editing the billing address already on file — which, until August 26, had no dedicated deep link at all. A dunning email that only offered payment_method_update was, for this category of failure, sending the customer to fix the one thing that wasn't actually broken.
The scale of that mismatch is bigger than most teams assume, because AVS-driven declines get mentally filed under "card problem" by default. AVS checks the billing address a customer supplies against what their card issuer has on file, and issuers vary widely in how strictly they enforce a match — a customer who moved eight months ago and never updated a SaaS subscription's billing address is a completely ordinary, completely non-fraudulent way to trip this check.
Source: Riskified, "Reducing Credit Card Declines from AVS Mismatch"
Riskified's own numbers put this starkly: even orders with zero address match at all were, seven times out of ten, real purchases from real customers — not fraud, just outdated or mistyped billing data. Most merchants don't run Riskified-grade override logic on top of a raw AVS check, which means the default behavior on a mismatch is often a flat decline, full stop. That decline lands on your invoice as incorrect_address or incorrect_zip, gets treated by your dunning stack as a generic failed payment, and gets the same "update your card" email as an expired Visa — which does nothing, because the card was never the problem.
The B2B version of the same gap: tax ID, not address
For subscription businesses selling to companies rather than individuals, the equivalent failure rarely shows up as a card decline at all — it shows up as an invoice that never gets paid because it never gets approved. A tax ID that's expired, was entered with a typo, or belongs to a subsidiary that's since been restructured is a routine reason an accounts payable team kicks an invoice back before anyone even reaches a payment step. That failure mode sits closer to what we've written about in net terms and invoice-based B2B billing: the payment itself was never attempted, so none of your card-decline dunning logic ever fires, and the account just quietly stalls in accounts payable until someone notices the renewal never landed.
customer_update is the same fix for both failure modes, because both are billing-information problems rather than payment-method problems. A dunning or renewal-reminder workflow that can tell the difference between "your card needs updating" and "your billing details need updating" can now send the right link for each, instead of relying on the customer to somehow find the correct page inside a portal home screen they were never deep-linked into.
Wiring it into an actual dunning flow
The integration is a few lines, not a rebuild. On your invoice.payment_failed webhook, read the charge's decline_code before you generate the portal link for your recovery email:
- Card-level codes —
expired_card,insufficient_funds,incorrect_cvc,invalid_number— create a portal session withflow_data[type]=payment_method_update. - Billing-detail codes —
incorrect_address,incorrect_zip— create a portal session withflow_data[type]=customer_updateinstead. - No charge attempt at all (a stalled B2B invoice) — send
customer_updateproactively as part of your renewal-reminder sequence, before the invoice due date, rather than waiting for a decline that will never come.
Every dunning email you send already carries the decline reason in the webhook payload that triggered it. The only change is a branch in that logic instead of a single hardcoded flow type — the kind of fix that takes an afternoon, not a sprint.
None of this replaces the harder problem of a subscriber who's decided, for real product or price reasons, that they're done. That's the moment CancelFlow is built for, and it's a different conversation than a stale ZIP code. But involuntary churn from a wrong billing address or an expired tax ID is pure waste — a customer who never intended to leave, lost to a form field nobody prompted them to fix. Run your current dunning recovery rate through our churn calculator before and after you split this logic out, and the gap between "fixed a card" and "fixed a billing address" is usually the fastest, cheapest win left in an involuntary-churn stack that's already been through a few rounds of optimization.
Frequently asked questions
What is Stripe's new customer_update billing portal flow?+
It's a flow_data.type value Stripe added to the Billing Portal Sessions API on August 26, 2026 (API version 2026-08-26.dahlia). Setting flow_data[type] to customer_update creates a deep link that sends a customer straight to the billing information page in the hosted portal — where they can edit their billing address and tax ID — with the rest of the portal's navigation hidden. It sits alongside four existing flow types: payment_method_update, subscription_cancel, subscription_update, and subscription_update_confirm.
What's the difference between customer_update and payment_method_update?+
payment_method_update sends a customer to add or replace a card — it only touches customer.invoice_settings.default_payment_method. customer_update sends them to edit billing information: name, email, billing address, and tax ID. A card can be perfectly valid and unexpired while the billing address on file is stale, and that mismatch is what triggers Stripe's incorrect_address and incorrect_zip decline codes — a different failure than expired_card or insufficient_funds, and one payment_method_update alone doesn't fix.
Can a wrong billing address or tax ID actually cause a subscription payment to fail?+
Yes. Address Verification Service (AVS) checks the billing address a customer has on file against what their card issuer has on record, and a mismatch can trigger a decline independent of whether the card itself is valid — Stripe surfaces this as the incorrect_address or incorrect_zip decline code. On the invoicing side, an outdated or incorrect tax ID is a separate, common reason a B2B invoice gets kicked back by a customer's accounts payable system before it's ever paid, regardless of whether the underlying charge succeeded.
Do I need to rebuild my dunning emails to use this?+
No rebuild — it's an additive API parameter, and Stripe notes no changes are required for existing integrations. The work is in your dunning logic, not your portal setup: when you generate the billing portal link for a failed-payment email, branch on the invoice's decline_code. Route expired_card, insufficient_funds, and similar card-level failures to payment_method_update. Route incorrect_address, incorrect_zip, and tax-ID-driven invoice rejections to customer_update instead of sending everyone to the same generic card-update link.
Stop losing subscribers today
One script tag. One function call. A live cancellation flow in under 10 minutes.
Start free trial →