19 Compare

Stripe Checkout vs Payment Links

Both take money. One takes an afternoon of integration and one takes four minutes, and the four-minute option is right more often than developers like to admit.

A Payment Link is a URL you create once and share, with no code. Checkout is a session your application creates, so the price, customer and metadata can depend on application state. Start with links — if you are validating whether anyone will pay, a URL you can send today beats an integration you ship next week.

The upgrade trigger

Move from links to Checkout when the purchase depends on something only your application knows.

A fixed-price product, a deposit, a one-off service: a link is sufficient and always will be. A price that varies by quantity, a plan chosen in your interface, a purchase that must be tied to a specific account record: that is a session, because a static URL cannot carry per-transaction context.

Until that is true, the integration is work with no return.

Side by side

Payment LinksCheckout
Time to first paymentMinutesAn afternoon
Code requiredNoneServer-side session creation
Dynamic pricingNoYes
Per-customer metadataLimitedReliable
Ties payment to a recordAwkwardDesigned for it
SubscriptionsSupportedSupported, more control
Best forValidating demand, fixed pricesA product with accounts

The webhook rule

The most important thing on this page, and it applies to both options.

Do not fulfil on the redirect. Fulfil on the webhook.

The success URL a customer lands on after paying is not a reliable signal that payment completed. Customers close the tab, networks drop, phones lock, and browsers do whatever they like. If your fulfilment logic lives on that page, some paying customers get nothing and you will not know until they email you.

The webhook is the authoritative event. Everything that grants access, sends a receipt, provisions an account, or notifies you should hang off it. The redirect page exists to say thank you and nothing more.

Two things that follow:

  • Webhook handlers must be idempotent. Events can arrive more than once, and provisioning twice is a support ticket at best and a duplicate charge at worst.
  • Verify the signature. An unauthenticated webhook endpoint that grants access is an endpoint that grants access to anyone who finds it.

Where the webhook belongs

Next to your database, not in your frontend deployment.

A webhook is an unauthenticated request from a third party that needs privileged write access. There is no user session; the payload is all you have. Putting that handler where the privileged credential already lives, rather than shipping that credential into your web application’s environment, is the safer arrangement. The general version of this argument is here.

Practical notes

  • Test with a real card in live mode once. Test mode does not exercise every path, and the first real payment is a bad time to discover that.
  • Handle the failure states. Card declined, authentication required, subscription payment failed later. The last one is the most commonly skipped and the most costly, because it is silent churn.
  • Put the customer identifier in metadata from the very first transaction, even on a link where it is awkward. Reconciling payments to accounts retroactively is miserable.
  • One account, and know where the keys live. If several products share an account, be deliberate about which environment holds the live key.
  • Do not build a billing portal. The hosted one handles cancellation, card updates and invoices, and none of that is where your differentiation lies.

The order I would do it in

  1. Payment Link. Get a real payment from a real person. This answers the only question that matters early.
  2. Add the webhook as soon as anything needs to happen after payment.
  3. Move to Checkout when price or product depends on application state.
  4. Add the hosted billing portal rather than building account management.
  5. Handle failed renewals before you need to, because you will need to.

FAQ

What is the difference?

A link is a static URL needing no code. Checkout is a session your app creates, so price, customer and metadata can vary per transaction.

Which should I start with?

Links. Validating that someone will pay beats shipping an integration first.

When do you upgrade?

When the purchase depends on something only your application knows, or you need reliable metadata tying it to a record.

Do I still need webhooks?

Yes. The redirect is not a reliable signal. Fulfil on the webhook, make it idempotent, verify the signature.

Related: Shopify vs custom ecommerce and how I build web apps.