Recover failed Lemon Squeezy payments
Lemon Squeezy acts as merchant of record, so tax and card handling stay with them. Recovery is where an orchestration layer helps: their failure webhooks tell you exactly which subscription lapsed, and RRLabs turns that into scheduled, multi-channel outreach.
The Lemon Squeezy events recovery depends on
- subscription_payment_failed
- A renewal charge failed — open a recovery case.
- subscription_payment_success
- The renewal was collected. Close the case.
- subscription_expired
- The subscription lapsed after retries. Case lost.
Verifying Lemon Squeezy webhooks
- Scheme
- HMAC-SHA256 over the raw request body
- Signature location
- X-Signature
The digest is hex-encoded. Verify against your signing secret with a timing-safe comparison before parsing the body.
import { createHmac, timingSafeEqual } from "crypto";
const digest = createHmac("sha256", process.env.LEMONSQUEEZY_WEBHOOK_SECRET!)
.update(rawBody)
.digest("hex");
const signature = req.headers["x-signature"] as string;
if (!timingSafeEqual(Buffer.from(digest), Buffer.from(signature))) {
return new Response("Invalid signature", { status: 401 });
}
const { meta, data } = JSON.parse(rawBody);
if (meta.event_name === "subscription_payment_failed") {
await rrlabs.enqueueRecovery({ provider: "lemonsqueezy", externalId: data.id });
}Decline playbook for Lemon Squeezy
| Failure signal | Recovery action |
|---|---|
| Renewal failure, card still valid | Retry through Lemon Squeezy's own schedule and send a reminder — no customer action needed yet. |
| Card expired or removed | Send the Lemon Squeezy customer portal link so the buyer can update their method. |
| Repeated failure before expiry | Escalate the channel: email first, then WhatsApp or SMS before the subscription expires. |
What happens after a payment fails
T+0s
Payment failed
Provider webhook received and verified
T+2s
AI analysis
Decline reason classified, amount at risk scored
T+5s
Dynamic email
Copy generated for that decline code and customer
Day 2
Smart retry
Retry scheduled only when the decline code is retryable
Day 2
WhatsApp push
Second channel used when the email went unanswered
On success
Recovered
Counted only when the provider confirms the charge
Timings describe the configured workflow, not a guaranteed outcome. Every step is skipped when the decline reason makes it counter-productive.
Frequently asked questions
- Does RRLabs charge Lemon Squeezy customers directly?
- No. Lemon Squeezy remains merchant of record and performs every charge. RRLabs only reads webhooks and sends recovery messages.
- Where do customers update their card?
- In the Lemon Squeezy customer portal. RRLabs links to it rather than collecting card details.
Connect Lemon Squeezy with read-only credentials
RRLabs reads failure events and orchestrates recovery. It never holds card data and never becomes the merchant of record.
Get early access