Stripe Link
Accept one-click payments from shoppers who saved their details with Stripe Link.
Stripe Link is Stripe’s accelerated-checkout network. A shopper saves their payment details with Link once, and on any later Link-enabled checkout Stripe recognizes them and lets them pay in one click.
Link appears to a shopper in one of two ways:
- Express button — the shopper already has an authenticated Link session in their browser. A “Pay with Link” button renders alongside your Apple Pay and Google Pay buttons.
- Tile — the shopper is not recognized. Link is offered as a selectable payment method, and choosing it launches Stripe’s Link sign-in.
Both paths mount the same Link element and complete through the same onLinkResult callback — the tile is a different placement, not a different flow.
Prerequisites
Link is Stripe-only. It cannot be fulfilled by Airwallex, Authorize.net, or any other processor, and a saved Link payment method cannot be re-routed to another processor.
Enable Link on your Stripe processor before integrating:
- Go to Orchestration > Payment processors and open your Stripe processor.
- Under Accept digital wallet payments, turn on Stripe Link.
- Click Save Processor.
The toggle appears only on Stripe processors. Processor configuration is dashboard-only — it is not part of the public API. Unlike Apple Pay and Google Pay, Link does not require registering a custom domain. See Stripe for the full processor setup.
Add Stripe.js to your checkout page:
PaymentKit collects card details through VGS, not Stripe Elements. The Link element mounts into its own container beside your card form — the two coexist on the same page.
Setup
CDN
NPM/ES Modules
Initialize Link
Unlike Apple Pay and Google Pay — where you render a button that calls paymentKit.submit() — Link is the button. Stripe renders the express button and fires its own confirm event, so the integration is callback-driven.
Register your callbacks first, then call initStripeLink:
initStripeLink fetches the checkout’s Link configuration, sets up the Link element, and starts silent session detection. Mounting the visible button is a separate step — see Mount the express button. If Link is not available for the checkout — no Stripe processor, Link disabled, or Stripe.js missing — it stays quiet and no button renders.
The ordering above matters: onLinkReady and onLinkAuthChange both fire before the returned promise resolves, and neither emission is replayed for a callback registered later.
paymentKit.submit() does not work for Link. Calling it with paymentMethod: 'stripe_link' returns a directive error pointing you back to initStripeLink() and mountLinkButton().
Mount the express button
Mount the button into an empty container that Link owns — the SDK appends its own child node inside the selector you pass, and only removes that node again on re-mount. Never point it at your VGS card fields.
Call this only after initStripeLink has resolved. Before that the express element does not exist yet and the call fails with Express element not set up.
mountLinkButton reports failure through its return value rather than throwing, so check success. Mounting is idempotent — calling it again replaces the button rather than stacking a second one.
React to session state
Three callbacks cover the Link lifecycle — two drive what you render, one delivers the result. Register as many handlers per callback as you need; none are overwritten.
onLinkAuthChange reflects whether the shopper has an authenticated Link session. Whenever Link is advertised for the checkout, exactly one of the express button or the tile applies: the tile is the fallback when no session is recognized. If Link is not advertised at all, neither renders — showExpress is false and both containers should stay hidden.
Link uses its own isolated Stripe element, so it does not suppress your other express buttons. A recognized Link shopper on a wallet-capable device sees Link, Apple Pay, and Google Pay together.
Handle the result
onLinkResult receives either a data object or an errors object.
Result fields
data also carries errorCode, errorMessageForCustomer, and errorMessageForDebug. These are only populated on a failure, which arrives via result.errors — on a success result they are undefined.
Payer identity
Link returns the shopper’s identity when they confirm. The SDK captures it and sends it with the confirmation — you do not pass anything or call any extra method.
Captured values only fill fields that are blank. Anything you already supplied in customerInfo wins, so Link never overwrites merchant-supplied data. Because customerInfo.first_name and last_name are typed as required, pass empty strings when you want Link to supply the shopper’s name.
The Link element always asks for the billing address, even when you collect none. Stripe only surfaces the payer identity when it can fill both name and address, so declining the address would cost you the email too. Your field setting is honored on the server instead — the address is dropped at confirm time rather than never collected.
Phone is not requested. Any field Stripe cannot autofill from the shopper’s Link account is collected in the payment interface instead — an extra step at the highest-intent moment in the funnel.
Save Link for later
The Link payment method is always saved against the customer. What varies is whether it carries an off-session mandate — the thing that makes it chargeable later without the shopper present.
The SDK reads this from the checkout — there is no separate call.
Saved Link methods read back through the normal payment-method endpoints and, with the mandate, can be charged off-session for renewals and future invoices.
A saved Link method renders as a Link mark, not a card number. Link abstracts the underlying instrument, so brand and last four come back null by design — build your UI to omit them rather than to display a card.
Clean up
Tear down the Link element, its observers, and all registered callbacks when unmounting or navigating away. The call is idempotent.
In React, call this from your effect cleanup so re-mounts do not stack duplicate buttons. Teardown drops your callbacks too, so re-register them before calling initStripeLink again.
Options
initStripeLink options
Required here means required by the TypeScript type. The underlying API treats each customer_info field as individually optional, so a plain-JavaScript caller that omits a name gets a nameless customer rather than a validation error.
Error handling
Availability problems surface as a button that never appears, not as errors.
Treat onLinkReady as the availability signal: it fires true exactly once when Link is usable, and never fires at all when it is not — no Stripe processor, Link disabled, or Stripe.js missing. Render neither the express button nor the tile until onLinkReady fires.
Do not infer unavailability from onLinkAuthChange(false). It means “no authenticated Link session”, which is also the normal tile case, and on several initialization failure paths it never fires at all. Gating the tile on it alone renders a Link tile on checkouts where Link cannot be fulfilled.