Paddle
Connect Paddle Billing with an API key. Pulse imports completed transactions and refunds. Paddle checkouts open in an overlay rather than a link, so you pass the visitor id yourself in one line.
Connect Paddle#
- Create an API key
In Paddle open Developer tools, Authentication, New API key with two permissions:
Permission Why transaction.readImport completed transactions. notification_setting.writeLet Pulse register its own notification destination. - Paste it into Pulse
Settings, Revenue, Connect, Paddle. Keys that contain
_sdbx_(sandbox) talk to Paddle's sandbox API and the connection is labelled “Paddle (sandbox)”. - Optional: paste a notification secret
Only needed when Pulse cannot register the destination itself (non-
httpslocal setups). Create it in Paddle and paste its secret key (pdl_ntfset_…).
What is synced#
- Transactions with status completed, including their address and customer.
- Amount is the transaction total minus tax, in its currency.
- Product is the first line item, country comes from the address, and the email is stored only as a keyed one-way hash.
- Kind: recurring charges are renewals, other subscription transactions are subscription sales, the rest are one-time.
| Webhook event | What Pulse does |
|---|---|
transaction.completed | Stores the transaction with its custom data. |
adjustment.created, adjustment.updated | Marks a transaction refunded when a full refund or chargeback is approved. |
Attribution#
Paddle.js opens its checkout from your code, and Paddle checkouts have no address the script can recognise, so it cannot tag them. Pass the visitor id as custom data when you open it:
Paddle.Checkout.open({
items: [{ priceId: 'pri_123', quantity: 1 }],
customData: { pulse_vid: window.pulse?.visitorId() },
});pulse.visitorId() returns the id the server gave this tab (an empty string until the first pageview has been answered, which takes moments). Pulse reads pulse_vid from the transaction's custom data, and an optional source key as a fallback source name. If you create transactions on your server, send the id along and set the same custom data there.
Refunds and currencies#
A full refund or an approved chargeback removes a sale. A partial refund reduces it to what is left; the webhook reports full refunds at once, partial ones arrive with the next deep sync (within 6 hours). Amounts in other currencies are converted to US dollars at the payment day's rate (see currencies).
Common issues#
- “Paddle rejected this API key”
- Create a new key in Developer tools, Authentication.
- “This Paddle key lacks a permission”
- Edit the key and enable
transaction.readandnotification_setting.write. - Sales have no source
customData.pulse_vidwas missing or empty when the checkout opened. Open it from a click handler after the page has loaded, so the visitor id exists.- Classic Paddle
- Pulse supports Paddle Billing only (
api.paddle.com).