2026-11-18
Recovering Abandoned Crypto Checkouts by Email

A card checkout gets abandoned when someone changes their mind. A crypto checkout gets abandoned for that reason too, and for a few more. The customer has USDC but no ETH for gas. They have it on the wrong network. They went to withdraw from an exchange, and by the time it arrived, the charge had expired.
Card stores have sent "you left something in your cart" emails for years. Klap Link now does the same for crypto checkouts, with one difference: the payment page shows the payer a checkbox for it, and nothing is sent if they untick it.
How it works on Klap Link
The merchant turns on Checkout recovery in the Link settings. It's off until you do.
Once it's on, the payment page shows a checkbox under the email field: "Email me a link to finish if I don't complete this payment." The payer can untick it. Without an email address, or with the box unticked, nothing is ever sent.
Every checkout on a Klap Link payment page is a charge, and that charge expires after 15 minutes. About an hour after an unpaid checkout expires, the payer gets one email:
Finish your payment to Acme Studio
You started a payment to Acme Studio for Logo design package and didn't finish it.
Total: $450.00
[Finish payment]
If you don't want to, ignore this email; we won't remind you about this payment again.
The button goes back to the same payment page, where a new checkout starts.
The hour of waiting leaves time for someone halfway through an exchange withdrawal to come back on their own. The job checks every 15 minutes and only picks up checkouts that expired between one and 24 hours ago, so an old abandoned checkout never gets a surprise email days later.
What it won't send
A reminder is skipped when:
- a newer checkout from the same payer replaced this one
- they already paid, or have another checkout open right now
- it's for a link that was archived or a product that sold out
- some money already arrived, so the charge ended
partially_paidorunderpaidinstead of plain expired - recovery was turned off in the meantime
Partial payments matter more than they look. An underpaid charge isn't an abandoned one. The customer tried to pay and something went wrong, and "finish your payment" would be the wrong message. Those go to the underpayment flow instead.
There are also hard caps, so a busy store can't turn this into a mailing list. Each payer gets at most one reminder per link every 30 days and three per day across all links. Each merchant can send at most 100 a day. A payer who abandons the same link five times in a week hears from you once.
Buyer details on abandoned checkouts are cleared after 30 days, whether or not a reminder went out.
Testing it
In test mode the email goes to the merchant account owner, not the payer, with [Test] in the subject and a note that it was a test. Create a test checkout on your own link, leave it, and the reminder lands in your inbox an hour or so after it expires. That's the easiest way to see exactly what your customers will get.
Building the same thing on the API
If you use the Klap API directly instead of Link, you have everything you need already. Every charge fires charge.expired when it times out unpaid, and externalRef tells you which order it was:
if (event.event === 'charge.expired') {const order = await db.orders.findUnique({ where: { id: event.data.externalRef } })if (order && order.status === 'pending' && order.recoveryConsent) {await recoveryQueue.add({ orderId: order.id },{ delay: 60 * 60 * 1000, jobId: `recovery_${order.id}` },)}}
When the job runs, check the order again before sending. The customer may have paid in another tab or another checkout during that hour. Then send a link to a page that creates a fresh charge for the same order. Don't resend the old charge's address, since it's expired.
If you build your own, copy the checkbox: put it on the checkout, where the customer can see it, and don't treat an email typed for a receipt as permission to market to them. Its caps are too. Keep the count per person in the database, not in the job's memory, so a restart or a second worker can't send the same reminder twice. Idempotent payment webhook handlers covers that pattern for webhooks, and it works the same way here.
Before Black Friday
If you sell through Klap Link and expect more traffic over the holiday weekend, turning recovery on now gives you a week to watch a few reminders go out before it gets busy. The setting is under the organization settings in Klap Link, and only an owner can change it.
And if your abandoned checkouts are mostly "insufficient funds for gas", a reminder helps less than telling people up front. Does USDC have gas fees? has the one line worth adding to your payment page.