Provider guide

Paddle webhooks, kept properly.

Paddle is a merchant of record, so its webhooks are not just notifications: they are how you learn that money moved, that a subscription changed state, that tax was handled. Losing one is a billing bug rather than a logging gap.

Field notes

How Paddle behaves, and where it bites

A timestamped signature, a five minute tolerance, and two generations of the product that do not share a scheme.

How Paddle sends

Paddle Billing POSTs JSON with the event in event_type (subscription.updated, transaction.completed) and signs it with Paddle-Signature, a semicolon-separated ts=…;h1=… pair.

Where it bites

  • Classic and Billing are different products. They sign differently and name events differently. A guide, or a preset, for one is wrong for the other.
  • The signature is timestamped. There is a tolerance, so a badly skewed clock on either end turns valid deliveries into failures.
  • Billing state is a sequence, not a snapshot. Reconstructing why a subscription is in its current state needs the events in order, which means having kept them.

The vault under it

Point a WebhookVault endpoint at Paddle and every delivery is stored in full: headers verbatim, bodies byte-for-byte, labelled with its event type and searchable. Forward it onward to your own handler if you want the relay pattern, replay any delivery once the bug is fixed, and let a Watchdog notice the day it stops arriving.

01

Create an endpoint

Name it paddle-billing. Turn on forwarding to your own handler if you want the vault in front of it rather than beside it.

02

Register the capture URL

Paddle → Developer tools → Notifications → New destination. Paste the capture URL and pick the events you want.

03

Keep everything

Every delivery from here on is on the shelf: searchable, replayable, and watched for the day it goes quiet.

Verify from the record, not just at the door

Paddle Billing signs ts:body with your notification secret and sends both halves in one header. The vault parses the pair, enforces the tolerance, and rules on every capture.

The vault stores the signature headers verbatim with every request, so a delivery from last month can still be checked today. Verdicts are part of Solo and up. How verification works →

captured · transaction.completed✓ verified
# headers, stored verbatim
"Paddle-Signature": "ts=1757030400;h1=8f3a2c41…"

{
  "event_id": "evt_01j9x2m4k…",
  "event_type": "transaction.completed",
  "occurred_at": "2026-09-11T06:14:22.19Z",
  "data": {
    "id": "txn_01j9x2m4k…",
    "status": "completed",
    "currency_code": "USD"
  }
}

Event catalogue

Paddle webhook events you'll see

A few of the events Paddle sends, not the full list: Paddle's own documentation has every one. Each arrives in the vault labelled with its event type.

EventWhat it tells you
transaction.completedA transaction was paid and fully processed.
transaction.payment_failedA payment attempt on a transaction failed.
subscription.createdA new subscription started.
subscription.updatedA subscription changed: items, billing date, status or a scheduled change.
subscription.past_dueA renewal payment failed and the subscription is past due.
subscription.canceledA subscription was cancelled. The event name uses the American spelling.

Questions

Paddle webhook questions, answered

The three that come up most when Paddle is wired to a new endpoint.

Does Paddle retry failed webhooks?

Yes. Paddle Billing retries a delivery that does not get a 2xx, with growing gaps, over a period of days in live and far more briefly in sandbox, and a notification can be replayed afterwards. Every retry carries the same event_id, so deduplicate on it. A WebhookVault capture URL stores the delivery the first time it arrives.

How do I verify Paddle-Signature?

Split the header into ts and h1. Compute HMAC-SHA256 over ts, a colon and the raw body, keyed with the notification destination's secret key, hex-encode it and compare it with h1 in constant time; refuse a ts that is too old. On Solo and up the vault does this at capture, with a five minute tolerance, and puts the verdict on every row.

Does this guide cover Paddle Classic?

No. Paddle Classic sends form-encoded alerts signed with a public key in p_signature, a different scheme from Billing's Paddle-Signature. This guide and the vault's Paddle preset are for Paddle Billing. Classic alerts are still captured and stored in full, but the Paddle preset cannot verify their signature.

Keep the events your revenue depends on.

Free tier keeps 3 days while you evaluate; Solo keeps a month from $5.