Paddle

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#

  1. Create an API key

    In Paddle open Developer tools, Authentication, New API key with two permissions:

    PermissionWhy
    transaction.readImport completed transactions.
    notification_setting.writeLet Pulse register its own notification destination.
  2. 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)”.

  3. Optional: paste a notification secret

    Only needed when Pulse cannot register the destination itself (non-https local 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 eventWhat Pulse does
transaction.completedStores the transaction with its custom data.
adjustment.created, adjustment.updatedMarks 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:

js
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.read and notification_setting.write.
Sales have no source
customData.pulse_vid was 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).