Lovable and Stripe: Built-In Payments, Your Own Account, and the Webhook Behind Our Own Checkout
Lovable offers two ways to take money and its docs describe both precisely, including the one line most guides skip: on your own Stripe key the integration does not use webhooks by default. This page quotes both paths, reads Stripe's fees on the day of writing and prices one sale under each, quotes Stripe's own rule on why the success page is not proof of payment, and then shows the webhook and claim route that sell the bundle on this site, with the four defects that shipped with them and how each was fixed.
Updated

Which two paths does Lovable offer, and who qualifies for each?
Built-in payments and your own Stripe account. Both are in Lovable's docs, read on 26 September 2026, and they differ on plan, on who holds the keys, and on webhooks. The payments page says “built-in payments require a paid Lovable plan”, and offers Paddle and Stripe with “no API keys to handle”. The own-account page says the integration “does not require a paid Lovable plan”, and that “The form accepts restricted keys (rk_...) or secret keys (sk_...), test or live mode”.
| Built-in payments | Your own Stripe account | |
|---|---|---|
| Plan | Paid Lovable plan | Any plan, including Free |
| Provider | Paddle and Stripe | Stripe only |
| Keys | None to handle; Lovable provisions the account | A restricted or secret key pasted into the Connect Stripe form, stored as a backend secret |
| Test and live | Test mode in the preview, live after publishing; products sync on publish | Your test or live key; the full checkout runs from the preview in a new tab |
| Webhooks | Two endpoints per environment, registered by Lovable; do not edit them by hand | None by default; the app checks status directly with Stripe |
| Payments view | Products, prices, refunds managed in Lovable | Read-only; products, refunds and webhooks live in the Stripe dashboard |
| Cannot | Remix a project with payments; run two providers; sell physical goods by default | Combine with built-in payments in the same project |
The security line is the one to copy into your habits: “Never paste your Stripe key into chat messages.” The form is the only place for it, and “The key is stored as a backend secret, and Lovable does not read stored secret values back.” Lovable then “Lovable builds your payment flow with edge functions: small pieces of backend code that call Stripe using your stored key, so the key is never exposed in your app.”
What does a sale cost on each path?
Stripe's fees, from its US pricing page on 26 September 2026: “2.9% + 30¢ per successful transaction for domestic cards”, “+ 1.5% for international cards”, “+ 1% if currency conversion is required”. Checkout is “Included with Payments”; Billing is 0.7% of Billing volume (pay as you go); Tax Basic is 0.5% per transaction, where you're registered to collect taxes (no-code integration); a dispute is $15.00 for each dispute you receive. Paddle through Lovable's built-in path is “5.0% + 50¢ per transaction, no monthly fee”, with a “flat 10% under $10”. Lovable's own framing: “Using Stripe or Paddle through Lovable costs the same as setting up the provider directly.”
| Category | cents |
|---|---|
| Stripe, US card, $29 | 114 (2.9% + 30¢) |
| Stripe, international card, $29 | 158 (4.4% + 30¢) |
| Stripe, international + FX, $29 | 187 (5.4% + 30¢) |
| Paddle via Lovable, $29 | 195 (5.0% + 50¢) |
| Stripe, US card, $9 | 56 (2.9% + 30¢) |
| Paddle via Lovable, $9 | 90 (flat 10% under $10) |
Stripe rates from stripe.com/us/pricing and Paddle rates from docs.lovable.dev/features/payments, both read 26 September 2026. Rounded to the cent; Stripe Tax and Billing not included.
Paddle is a merchant of record, so its higher rate buys tax handling that Stripe sells separately; whether that is worth 2.1 points plus 20 cents on a $29 sale depends on where your buyers are. What the chart cannot show is the international share of your sales, which on this site is the majority, so the middle bars are our bars.
Why is the success page not proof of payment?
Because Stripe says so, in its "Fulfill orders" guide: “You can't rely on triggering fulfillment only from your checkout landing page, because it's not guaranteed customers visit that page. For example, a customer can pay successfully and then lose their internet connection before your landing page loads.” And: “Perform fulfillment only once per payment. Because of how this integration and the internet work, your fulfill_checkout function might be called multiple times, possibly concurrently, for the same Checkout Session.” The events to handle are checkout.session.completed and, for delayed payment methods, checkout.session.async_payment_succeeded. The detail that surprises people: “Checkout waits up to 10 seconds for your server to respond to the webhook event delivery before redirecting your customer.”
Put next to Lovable's line that on your own key “By default, the integration does not use webhooks: your app checks payment and subscription status directly with Stripe”, this is the decision the page exists for. A one-time purchase that grants access at the moment of return works until a buyer's connection drops between paying and returning. Subscriptions and delayed methods do not work that way at all. Ask Lovable for the webhook, verify its signature, and make it the only writer.
- Create session: server-side
- Stripe Checkout: hosted page
- Webhook: writes once
- Claim route: settles, sets cookie
- Member area: reads only
src/app/api/create-bundle-checkout, src/app/api/stripe/webhook and src/app/api/bundle/claim, read 26 September 2026.
| What it does | What it must not do | |
|---|---|---|
| Create session | Runs server-side; guests allowed; metadata marks the product; automatic tax on; success_url points at a Route Handler | Charge an account that already owns the bundle |
| Stripe Checkout | Hosted page; card never touches our server | Be trusted as proof of payment on return |
| Webhook | Verifies the signature, claims the event id, writes the purchase row once, sends the receipt only when this call inserted the row | Return 500 on a bad signature; grant anything from an unpaid session |
| Claim route | Retrieves the session, checks payment_status is paid, settles the same row idempotently, mints a 24-hour guest cookie, redirects | Swallow a Stripe error and show access anyway |
| Member area | Reads entitlement from Postgres by confirmed email or user id | Write any state |
The webhook and the claim route both call the same idempotent write, keyed on the Checkout Session id, because the browser redirect regularly arrives before the webhook and a buyer looking at a page that says they own nothing is worse than a duplicate no-op. The webhook adds a second layer on the Stripe event id so a retry cannot send a second receipt:
// Layer 1. Insert-and-check: if we did not insert, someone already handled this event.
const { data: claimed, error: claimError } = await supabase
.from("stripe_webhook_events")
.insert({ id: event.id, type: event.type })
.select("id")
.maybeSingle();
if (claimError?.code === "23505") {
return NextResponse.json({ received: true, duplicate: true });
}
try {
switch (event.type) {
case "checkout.session.completed":
case "checkout.session.async_payment_succeeded":
await handleCheckoutSession(event.data.object);
break;
case "charge.refunded":
await markPurchaseRefunded(charge.payment_intent);
break;
case "charge.dispute.created":
await markPurchaseDisputed(dispute.payment_intent);
break;
}
} catch (error) {
// 500 so Stripe retries. Release the claim first, or the retry short-circuits as a duplicate.
await supabase.from("stripe_webhook_events").delete().eq("id", event.id);
return NextResponse.json({ error: "Handler failed" }, { status: 500 });
}Two rules in there are cheap to state and expensive to skip. A bad signature returns 400, never 500, because a 500 makes Stripe retry a forgery. A handler failure releases the claim before returning 500, because otherwise the retry short-circuits as a duplicate and the purchase is lost.
What broke on our own checkout, and how was each fixed?
The path above is the fixed version. The git log of this repository, read 26 September 2026, shows how it got here.
| Date | What changed | |
|---|---|---|
| 297cbb7 | 25 Jul 2026 | Plan resolved from Stripe instead of an is_pro_user stub: a walk of up to 100 API calls per check. |
| 921358c | 25 Jul 2026 | Paywall made server-authoritative. |
| 7af859d | 11 Sep 2026 | Subscription and Builder Pack retired; one one-time product. |
| 30803ce | 12 Sep 2026 | Bundle purchasable; entitlement becomes one row in purchases, written by the webhook. |
| 371e8b7 | 12 Sep 2026 | Gated downloads and the member area. |
| 49e24a5 | 12 Sep 2026 | The defect that broke every guest purchase, fixed and gated. |
The last commit fixed four defects that had shipped that morning. The first one was the default path, not an edge case: checkout is guest-first by design, so every guest who paid hit it.
| Effect on a buyer | Fix | |
|---|---|---|
| The guest access cookie was written inside a server component render, which Next.js forbids; the throw was swallowed by a try/catch that had already set access to true. | A guest paid, saw "It is yours", and could not download anything. | A Route Handler at /api/bundle/claim settles the session and writes the cookie, then redirects to /thank-you, which only reads state. |
| The receipt's sender address was not verified with the email provider and the 403 was swallowed. | No receipt could send. | Verified sender, reply-to unchanged, List-Unsubscribe header. |
| The post-purchase sign-up button carried pre-purchase intent. | A buyer who created an account afterwards was sent back to the $199 page. | A separate purchase intent that returns to the member area. |
| A missing webhook secret was reported as a bad signature with a 400. | Stripe marked deliveries permanently failed and the log named the wrong cause. | A 503 before signature verification when the secret is absent. |
The common thread is the same as on the security page: a swallowed error looks like success. The fix that outlasts the others is that the member page now writes nothing and a gate script runs a guest purchase on every deploy. The vibe coding tips page carries the rest of that list.
Which prompts on this site encode these rules?
Four, across three categories. Subscription Checkout Flow and Payment History & Billing Pages sit in the SaaS prompts; Payment Provider Webhook Integration in the API prompts; Pricing Page with Tier Comparison in the landing page prompts. The lines they share, as they appear in the prompt bodies:
## Build Order
Server-side session creation first, then the webhook with signature verification, then the return pages, then the status UI. The webhook is the source of truth; build it before the celebration screen.
## Safe-Guard Instructions
- Verify webhook signatures; reject unsigned payloads
- Make webhook handlers idempotent: Stripe retries, and double-processing a payment event is a money-losing bug
- On Lovable, built-in payments (Paddle or Stripe) need a paid plan and run in test mode in the preview until the app is published; on the free plan connect your own Stripe account. Either way the webhook stays the source of truth
- Never grant entitlements from the success redirect alone; a user can bookmark that URL
- All Stripe calls server-side; the browser never sees the secret key
- Amounts and currency stored as provided, in minor units; no floating-point money anywhereEvery one of those lines is a defect we have either shipped or read about in the CVE record. The Pro variants add the distribution step each payment feature should carry, which is what the bundle sells at $199 USD, one time, through the exact checkout described above.
What do the top results for this term leave out?
- Lovable docs, Connect your own Stripe account. The primary source. Setup, how payments work, limitations, FAQ.
- No Code MBA, Lovable Stripe Tutorial 2026. About 2,100 words, updated 19 May 2026. No webhooks, no live-mode step, no fees, no restricted keys, no screenshots.
- RapidDev, Lovable Stripe Connect. About 4,500 words on Stripe Connect (marketplace payouts), not checkout. States the integration only works on a deployed URL; Lovable's FAQ says the full checkout runs from the preview.
What we did not publish
- A run of the Connect Stripe form on a Lovable test project. It would mean pasting a key from a live Stripe account into a throwaway project, and we decided the screenshot was not worth that.
- Our sales count. The webhook table and the purchases table were both read today; their sizes stay ours.
- A Paddle comparison from experience. We have only ever run Stripe.
Sources
All read on 26 September 2026. Quotes and rates in src/data/lovableStripe.ts.
Frequently asked
Does Lovable integrate with Stripe?↓
Do I need a paid Lovable plan to accept payments?↓
What does Stripe charge on a Lovable app?↓
Do payments work in the Lovable preview?↓
Does the own-account integration use webhooks?↓
What went wrong with your own Stripe checkout?↓
Related reading
- Lovable SaaS prompts
Subscription Checkout Flow and the billing pages prompt.
- add an API to a Lovable app
Payment Provider Webhook Integration lives here.
- landing page prompts by traffic source
The pricing page prompt with one source of truth for limits.
- Lovable security
The other place a swallowed error looked like success.
- Lovable and Supabase
Where the purchases row and its policies live.
- Lovable pricing
Which plan built-in payments need, priced today.
- how Lovable credits work
What a payments build costs in credits.
- vibe coding tips from our own mistakes
The guest-purchase defect among twelve.
- the SaaS starter kit
The schema a billing table attaches to.
- the Complete Lovable Bundle
Sold through the checkout on this page.
- SaaS ideas
Fifteen ideas with the billing model each one implies.
- build a SaaS
Billing as the last step of building a SaaS on Lovable.
Written by

Marco Kohns
Founder of ProtoBites - Venture Growth Studio
Growth PM at a Silicon Valley scale-up (a16z and General Catalyst backed), ex-Techstars where he consulted 13 early-stage startups, Reforge-trained. Every prompt on this site comes out of shipping ProtoBites' own portfolio products.