Revenue attribution
Paddle
Connect Paddle Billing with a read-only API key and a notification destination so ProductLense records transactions and adjustments net of Paddle's cut.
ProductLense reads your Paddle Billing customers, subscriptions, completed transactions and adjustments. Paddle is a merchant of record, so ProductLense records what the customer paid and treats everything Paddle keeps (its fee and the tax it remits) as the fee. ProductLense only reads: it never writes to your Paddle account, never refunds, cancels or changes anything.
What you need
| Field | Secret | Where to find it |
|---|---|---|
| API key | Yes | Paddle → Developer tools → Authentication. |
| Webhook secret key | Yes | The pdl_ntfset_... secret shown when you create the notification destination pointing at ProductLense. |
Every plan includes one billing connection per site, Free too; Growth and Scale allow any number. See plans and limits.
Permissions
The API key needs read access to customers, subscriptions, transactions and adjustments. ProductLense calls GET /customers, /subscriptions, /transactions and /adjustments and nothing else.
Set up
- In Paddle, open Developer tools → Authentication and create an API key with read access to the four resources above.
- In ProductLense, open your site's Settings → Billing connections → Paddle, paste the key and click Connect and import history.
- Copy the webhook URL from the connection card.
- In Paddle, open Developer tools → Notifications → New destination, paste the URL and subscribe to the events below.
- Copy the destination's secret key into the Paddle connection in ProductLense.
Webhook
URL: https://api.productlense.app/api/webhooks/paddle/<connection-id> (ProductLense shows the exact URL after you save).
Events ProductLense uses:
transaction.completed,transaction.updatedadjustment.created,adjustment.updatedsubscription.created,subscription.updated,subscription.canceled,subscription.activated,subscription.paused,subscription.resumed,subscription.past_duecustomer.created,customer.updated
Verification: the Paddle-Signature header (timestamp plus h1 HMAC-SHA256 with your secret key). Deliveries older than 5 minutes are rejected.
What ProductLense reads
- Customers: email, name and custom data.
- Subscriptions: status, billing interval and amount.
- Payments: completed transactions.
- Refunds and chargebacks: refund and chargeback adjustments.
- History: the last 12 months on first connect, then a nightly reconcile at 03:00 UTC from the last sync minus 48 hours.
How fees are derived
fee = grand_total − earningsThat is Paddle's fee plus the tax it collects and remits, so net revenue equals what Paddle pays out to you. When a transaction has no earnings figure, ProductLense uses Paddle's fee plus tax. Refund and chargeback adjustments are netted at your earnings share, and a chargeback adds its chargeback fee, so a full refund cancels the original charge exactly. Fees are reported by Paddle, not estimated.
Match payments to visitors
ProductLense reads the user id from the customer's custom_data: pl_user_id, user_id, userId or uid. Use the same id you pass to identify. A ProductLense visitor id in pl_visitor_id or visitor_id is also accepted. Without either, ProductLense falls back to the customer email, matched to the email trait sent with identify, or to a user id that is that email.
await fetch('https://api.paddle.com/customers', {
method: 'POST',
headers: { Authorization: `Bearer ${process.env.PADDLE_API_KEY}`, 'Content-Type': 'application/json' },
body: JSON.stringify({
email: user.email,
custom_data: { pl_user_id: user.id },
}),
});