Integration guide

Recovering failed Paddle payments

Paddle acts as merchant of record, so the charge, tax handling and invoicing stay with Paddle. What Paddle does not decide is which failure deserves an immediate nudge versus a delayed retry, or which channel that nudge should use. RRLabs reads Paddle's notifications and orchestrates the outreach; the money never moves through RRLabs.

Quick answer

Paddle recovery listens to transaction.payment_failed and subscription.past_due notifications, then follows up with the customer while Paddle, as merchant of record, keeps handling the charge, tax and invoice.

Events that matter

transaction.payment_failed
A Paddle transaction was declined.
subscription.past_due
The subscription entered the dunning window.
transaction.completed
Payment went through — close the recovery loop.
subscription.canceled
Stop all outreach for this customer.

Setting it up

  1. 1

    Create the notification destination

    In Paddle Billing, add a notification destination pointing at your RRLabs webhook URL and subscribe to the transaction and subscription events above.

  2. 2

    Verify the signature

    Each payload carries a Paddle-Signature header; RRLabs rejects anything that does not verify against the notification secret.

  3. 3

    Respect merchant-of-record rules

    Paddle owns the invoice and the tax treatment. Outreach links customers back to Paddle's hosted update page rather than a custom card form.

  4. 4

    Close on completion

    transaction.completed or a renewed subscription marks the attempt resolved.

Consume Paddle Billing notifications

// Paddle Billing → Notifications → destination URL
// Verify the Paddle-Signature header against your notification secret first.
const event = JSON.parse(rawBody);

if (event.event_type === "transaction.payment_failed") {
  const tx = event.data;
  await rrlabs.enqueueRecovery({
    provider: "paddle",
    externalId: tx.id,
    customerEmail: tx.customer?.email,
    amountCents: Number(tx.details?.totals?.total ?? 0),
    currency: tx.currency_code,
  });
}

if (event.event_type === "transaction.completed") {
  await rrlabs.closeRecovery({ provider: "paddle", externalId: event.data.id });
}

Manual recovery vs. automated recovery

CapabilityPaddle aloneWith RRLabs
Retry logicPaddle's standard dunning windowOutreach timed per failure reason inside that window
ChannelsPaddle emailsEmail, WhatsApp and SMS where consented
Message contentPaddle-branded templatesYour brand voice, reason-specific copy
AttributionRecovered totals onlyRecovered transactions linked to the message that preceded them
Source of truthPaddlePaddle — it remains merchant of record

Frequently asked questions

Can RRLabs retry the charge itself on Paddle?

No. As merchant of record Paddle owns the retry. RRLabs orchestrates the customer-facing side and points people at Paddle's own update page.

Will this conflict with Paddle's dunning emails?

It can. Most teams reduce Paddle's email cadence and let RRLabs handle the sequence, or keep RRLabs on channels Paddle does not use.

Which Paddle version is supported?

Paddle Billing notifications. Paddle Classic webhooks use different event names and need a custom mapping.

Other platforms

Estimate your recoverable revenue

Calculate now