# Connecting Paddle

Attribute sales from your Paddle checkout: the API key, the notification destination, the field that carries the click id, and what to check when a sale doesn't appear.

If Paddle bills your customers, connect it here. Your sales, renewals and refunds flow into
AffiliateRail exactly as a Stripe merchant's do. Click, sale, commission and payout all run on the
same ledger, the same commission rules and the same payouts.

You need two things from Paddle:

- An **API key**, which lets us read your Paddle account.
- An address in Paddle that sends us a message every time a sale happens. Paddle calls it a
  **notification destination**. It comes with a password-like code that proves each message came
  from Paddle, called its **signing secret**.

Paddle has no one-click sign-in like Stripe's, so you fill in a short form instead.

## Before you start

Decide whether you're connecting **sandbox** (Paddle's test environment) or **live**. Paddle keeps
them completely separate, on different sign-in pages and different API hosts, and a key from one
never works against the other.

Rehearse in sandbox first. You can put a full transaction through with a test card and watch the
commission appear before any real money is involved.

Sandbox sales are test sales. The sale and its commission show up with a **Test** chip, so you can
see the setup worked. They're never paid:

- Nothing goes into the partner's balance.
- No payout picks them up.
- Your revenue and owed totals leave them out.

Switch the connection to live and real sales pay as normal. Test rows stay.

Once Paddle is selected, **Getting started** follows this path. It shows **Finish verifying
Paddle** until the saved connection is verified, then **Paddle verified**. Its test-sale step links
back here and asks for a Paddle sandbox checkout, and it doesn't ask you to connect Stripe as well.

## Get your webhook URL

Open **Settings**, **Connections** in AffiliateRail. The Paddle card shows a URL ending in your
program id. Copy it exactly.

That URL is unique to your program. It has to be, because a Paddle notification carries no field
naming the seller who sent it. The URL is the only thing that says a sale is yours.

The URL is safe to share, because your program id is already in your tracking script. The
signature keeps the connection safe. Every notification is signed, and we check the signature
against your own secret before we act on anything.

## Create the API key

In Paddle, go to **Developer tools**, then **Authentication**, and create a key.

It needs read access to notification settings, transactions, subscriptions, customers and
adjustments. If Paddle offers a read-only preset, that's the right one. We never write to your
Paddle account, the same way we never write to your Stripe.

Paddle shows the key once. Paste it straight into the Paddle card, and don't keep a copy in a note.

<Callout type="info">
The key itself says which environment it belongs to. A live key starts `pdl_live_apikey_` and a
sandbox key starts `pdl_sdbx_apikey_`. If you pick the wrong environment on the card, we refuse the
key and tell you which one it is. That way it can't fail later, at your first sale.
</Callout>

## Create the notification destination

Still under **Developer tools**, go to **Notifications** and create a destination. Choose the
webhook type, and paste the URL you copied above.

Subscribe it to these events:

| Event | Why we need it |
| --- | --- |
| `transaction.completed` | The sale. Both the first purchase and every renewal |
| `subscription.created` | Binds a customer to a partner even if the transaction is delayed |
| `subscription.updated`, `.activated`, `.past_due`, `.paused`, `.resumed`, `.canceled` | Keeps the customer's status honest in your reports |
| `adjustment.created`, `adjustment.updated` | Refunds and chargebacks, so a commission is voided when money goes back |

Save it, then copy the destination's **signing secret**. It starts `pdl_ntfset_`. If Paddle only
shows it once, copy it now.

If you lose it, delete the destination and make a new one. Then paste the new secret over the old
one here. Nothing else breaks.

## Connect

Back on the Paddle card, choose the environment, paste the API key and the signing secret, and save.

We call Paddle with the key straight away, before we mark anything as connected. Three things can
come back:

- **Connected, with a destination pointing here.** Everything is in place.
- **Connected, with no destination pointing here.** Your key works and your webhook doesn't. Go
  back and check the URL character for character. Nothing will reach us until it matches.
- **Refused, with a reason.** Either Paddle rejected the key, or the key belongs to the other
  environment. Paste the right key, or switch the environment on the card.

## The field that carries the click id

Attribution rides on one field: **`custom_data.rail_referral`** on the transaction.

A click id is the code our script gives each partner click. Our tracking script fills the field
for you when your checkout opens through Paddle.js, the same way it stamps a Stripe checkout.

If you create transactions on your server instead, set the same key yourself. Do it when you create
the transaction, using the click id our script left in the visitor's `rail` cookie.

Paddle then does something Stripe can't. It copies `custom_data` onto the subscription it creates,
and back onto every transaction that subscription creates. So the click id rides every renewal on
its own. A partner keeps earning on a customer for as long as your commission rule says. Nothing on
your side has to remember anything.

## When a sale doesn't appear

Work down this list. It's ordered by how often each one is the answer.

1. **Look at the Paddle card.** It shows the last event we received and when. If that's blank or
   days old, the problem is between Paddle and us, and your ledger is fine.
2. **Check the delivery in Paddle**, under Notifications. Paddle shows what it sent and what we
   answered.
   - A **400** means the signature didn't verify. Almost always, the signing secret here isn't the
     one on that destination. Paste it again.
   - A **200** saying this program has no live Paddle connection means the URL is pointing at a
     program whose connection was disconnected.
   - A **200** with anything else means we received it and made a decision, so carry on down.
3. **Check the customer exists** under Customers. If they're there with no partner against them,
   the sale arrived with no click id, so the checkout wasn't stamped. The
   [attribution guide](/guides/attribution) covers the fix. The attribution report lists every sale
   in that state so you can match it to a partner by hand.
4. **Check your commission rules.** A customer against the right partner with no commission means
   the sale landed and no rule matched it. [Commission rules](/guides/rules) covers why that
   happens.

## Disconnecting

Disconnect on the same card. We stop reading new sales straight away. **Every commission already
earned stays exactly as it is**, along with the sales, the payouts and the balances.

You can also delete the destination in Paddle, which has the same effect from the other end.

## What we hold, and what we can't do

We hold your API key and your signing secret, encrypted, and nothing else of yours.

- The key is read-only, because that's all we ask for.
- We never write to your Paddle account.
- Payouts to your partners run from your own PayPal, Wise or Payoneer account, never through us.

[Payouts](/guides/payouts) explains that side.
