trakily.

Paddle

Connect Paddle Billing with an API key and attribute transactions and subscriptions.

Connecting Paddle imports your payments, refunds and subscriptions into Trakily and keeps them in sync. Trakily only reads data; it never creates charges or changes anything in your Paddle account apart from registering one webhook, if you allow it. Read Revenue attribution first if you haven't.

1. Create a api key

  1. 1

    Paddle → Developer tools → Authentication → New API key

  2. 2

    Read access: Transactions, Subscriptions, Customers, Adjustments

  3. 3

    Optional: Notification settings write, so we can register the webhook

Direct link: vendors.paddle.com/authentication-v2

This is for Paddle Billing. Live keys (pdl_live_…) and sandbox keys (pdl_sdbx_…) are detected automatically; older keys without a prefix are tried against both.

2. Connect it in Trakily

  1. 1

    Open your site's Settings → Revenue (owners only) and click Connect next to Paddle.

  2. 2

    Paste the api key, then click Connect Paddle. Trakily checks the key.

  3. 3

    The first sync imports your full history in the background. After that, Trakily pulls changes every 15 minutes, and webhooks deliver new payments within seconds.

Keys are encrypted at rest and only used to read payments. Test-mode and live keys both work; a test key only sees test data.

3. Webhook for real-time updates

Trakily registers the webhook in your Paddle account for you when you connect, as long as the key allows it. The webhook card in Settings then says Registered automatically. It stays in your Paddle account; delete it there if you disconnect.

Prefer to add it yourself? Tick I'll register the webhook myself when connecting, then create an endpoint in Paddle with the URL shown in Settings and these events, and paste its signing secret into the webhook card:

Endpoint URL (your site's id is filled in on the Settings page)
https://trakily.com/api/webhooks/paddle/pls_…
transaction.completedadjustment.createdadjustment.updatedsubscription.createdsubscription.updatedsubscription.canceled

4. Pass the visitor id at checkout

Pass the visitor id as customData when you open Paddle.js checkout. Trakily reads custom_data.trakily_visitor_id (and trakily_session_id, if you add it) from transactions.

Paddle.js checkout
// Pass ids as custom data when opening checkout (client side)
const vid = decodeURIComponent(document.cookie.match(/_trakily_vid=([^;]+)/)?.[1] ?? "").split("|")[0];
Paddle.Checkout.open({
  items: [{ priceId: "<price id>", quantity: 1 }],
  customData: { trakily_visitor_id: vid },
});

The keys are always trakily_visitor_id and trakily_session_id. The visitor id is the first part of the _trakily_vid cookie (before the first |); the session id is the _trakily_sid cookie. If the session id is missing, Trakily uses the visitor's latest session before the payment.

Success page detection

Paddle checkouts don't return a checkout id to your page that the script can read, so for Paddle use customData (above) or email matching with identify. Trakily looks up each transaction's customer email for email matching.

Troubleshooting

  • “This Paddle key can't read transactions.” Give the key read access to Transactions, Subscriptions, Customers and Adjustments.
  • Webhook not registered automatically. The key doesn't have write access to notification settings. Add it and reconnect, or add the notification destination by hand.
  • Payments arrive but show as unattributed. Pass the visitor id at checkout (step 4). Payments that can't be matched yet are retried every hour for 90 days, so a later identify call can still link them.
  • Nothing new since connecting. Click Sync now on the provider card. If the card says Needs attention, the error message tells you what the provider returned (for example a revoked key).