Send the payment-failed email from a Lovable app (TanStack Start, BuildBase sign-in)
Turn on the email BuildBase sends when a card fails, plus one prompt for a signed webhook route in a Lovable app for your own side effects.
Lovable can also connect to BuildBase itself while it builds: Use BuildBase in Lovable.
When a renewal fails, BuildBase emails the workspace owner from your sending domain. That needs no code, only two switches in the console. The prompt adds a webhook route for what you want to happen besides, such as flagging the workspace, verified with your webhook secret. This page assumes the app already signs people in with @buildbase/sdk, as the Lovable guide sets up. If it signs people in with something else, such as Supabase or Clerk, read keep your existing sign-in first.
Before you start
A sender connected (connect a sender) and the
Payment Failed notification event switched on
(notification events). For the route, an endpoint at
https://your-app.lovable.app/api/webhooks/buildbase under Settings >
Webhooks, with payment.failed ticked (add an
endpoint).
The prompt
The link opens a new Lovable project with the prompt filled in and not sent. For the app you already have, paste the prompt into that project's chat instead.
This app signs people in with BuildBase (@buildbase/sdk), set up as https://www.buildbase.app/guides/add-login-teams-and-paid-plans-to-a-lovable-app shows. If it does not, stop and tell me.
Read https://docs.buildbase.app/webhooks/overview.md first and do not invent event names.
Add src/routes/api/webhooks/buildbase.ts as a POST server route (createFileRoute with server.handlers). Verify it with parseWebhookEvent from @buildbase/sdk on the raw body from request.text(), the x-buildbase-signature and x-buildbase-timestamp headers and BUILDBASE_WEBHOOK_SECRET from Secrets; answer 401 when it returns null.
On payment.failed, flag the workspace in my database; do not send an email, BuildBase sends it. Answer 200 to every other event.Where the secrets go
The console shows the endpoint's signing secret once, when you create it. Add it under More > Settings > Secrets as BUILDBASE_WEBHOOK_SECRET, next to BUILDBASE_CLIENT_SECRET, and publish. Never put it in .env or give it a VITE_ prefix: Vite puts those values in the browser.
The Lovable trap
Lovable tends to write a createServerFn where a route belongs. A server function has no address BuildBase can post to, so every delivery fails. The console's delivery log shows each attempt: a 401 means the secret did not reach the route, and HTML or a 404 means there is no route.
If the route cannot read the secret at all, ask Lovable to read BUILDBASE_WEBHOOK_SECRET inside the handler, never at module scope, as the guide's env-binding fix says.
Full guides
- Add login, teams and paid plans to a Lovable app
- Failed payments: retries, grace days and the emails
- Add BuildBase to Lovable's instructions or skills