# Paddle

> Connect Paddle Billing so completed transactions, refund adjustments and cancellations reach your revenue reports.

Section: Revenue attribution  
Canonical page: https://statsy.co/docs/revenue/paddle  
Last updated: 2026-09-15

Statsy works with Paddle Billing. It is another merchant of record, so Paddle takes the payment and reports the outcome to Statsy.

## Connect Paddle

1. Copy the webhook URLIn Statsy, open **Site settings › Integrations** and press **Connect** on the Paddle tile. The dialog shows the URL for your site, ending in `/api/hooks/paddle/` and your `ws_` site key, with a copy button.
2. Add it as a webhook in PaddlePaste the URL into a new webhook endpoint in Paddle and subscribe it to the events listed below.
3. Paste the signing secret backPaddle shows a secret key for each notification destination you create. Paste it into the second field in the dialog and press **Save and connect**. It is stored encrypted and never shown again, so keep your own copy.

## Which events to subscribe to

| Event | What Statsy does with it |
| --- | --- |
| `transaction.completed` | Records the payment. It is stored as a renewal when the transaction's origin is `subscription_recurring`, and as a one-time payment otherwise. |
| `adjustment.created` | Records a refund — but only adjustments whose action is `refund`. Credits and chargebacks are ignored. |
| `subscription.canceled` | Marks the customer as churned. Note the American spelling, with one *l*. |

## Passing the visitor through

Paddle's `custom_data` travels from checkout to webhook. The script adds `custom_data[statsy_vid]` to Paddle checkout links when a visitor clicks one.

If you open Paddle's overlay checkout with Paddle.js, pass it yourself:

```js
const vid = statsy.visitorId();

Paddle.Checkout.open({
  items: [{ priceId: 'pri_123', quantity: 1 }],
  customData: vid ? { statsy_vid: vid } : undefined,
});
```

Set the same custom data on the subscription if you want renewals credited to the original source as well as the first transaction.

## How the webhook is verified

Paddle sends a `Paddle-Signature` header containing a timestamp and a signature over the body. Statsy checks both, and rejects requests whose timestamp is more than five minutes away from its own clock.

> **Note.** Paddle sandbox notifications are not treated differently from live ones. Point the sandbox at a test site in Statsy if you do not want sandbox money in your real numbers.

## Amounts

Paddle reports the grand total of a transaction, in the smallest unit of the transaction currency. Statsy stores the original currency alongside a converted USD figure, so a mixed-currency Paddle catalogue totals correctly.

Previous: [Lemon Squeezy](https://statsy.co/docs/revenue/lemon-squeezy)  
Next: [Polar](https://statsy.co/docs/revenue/polar)