> ## Documentation Index
> Fetch the complete documentation index at: https://docs.payglue.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Paddle

> Connect Paddle as a payment provider in PayGlue.

Paddle is a merchant of record platform — it handles tax collection and compliance on your behalf. PayGlue connects Paddle to Ghost: when a customer completes a transaction or activates a subscription in Paddle, Ghost membership is granted automatically.

<Note>
  Paddle does not offer simple checkout links you can paste into a button. Checkout requires a small JavaScript snippet embedded in your Ghost site. [Step 5](#step-5-add-paddle-checkout-to-your-ghost-site) covers this.
</Note>

## Prerequisites

* A Paddle account at [paddle.com](https://www.paddle.com) with at least one product and price created
* A Ghost blog connected in PayGlue ([Connect Ghost](/ghost/connect))

***

## Step 1: Create an API key

In your Paddle dashboard, go to **Developer tools → Authentication**.

Click **Generate API key**, give it a name (e.g. `PayGlue`), and copy the key immediately — Paddle shows it only once.

> \[Screenshot — Paddle Developer tools → Authentication: Generate API key button and the resulting key field]

The key starts with `pdl_live_` for live mode or `pdl_sdbx_` for sandbox. PayGlue detects the mode automatically from this prefix — no separate setting needed.

***

## Step 2: Add a notification destination

Go to **Developer tools → Notifications** and click **+ New destination**.

> \[Screenshot — Paddle Developer tools → Notifications: empty state with "+ New destination" button]

Fill in the form:

* **Type:** URL

* **URL:** paste the webhook URL from your PayGlue Paddle connection page:

  ```
  https://api.payglue.io/webhooks/paddle?tenant=YOUR-SLUG
  ```

  Replace `YOUR-SLUG` with your PayGlue organization slug (visible in the dashboard URL or on the Paddle connection page).

* **Events:** select all six of the following:
  * `transaction.completed`
  * `subscription.activated`
  * `subscription.resumed`
  * `subscription.canceled`
  * `subscription.paused`
  * `subscription.past_due`

Click **Save destination**.

> \[Screenshot — Paddle: New destination form with URL filled in and the six events checked]

After saving, open the destination and copy the **secret key** (starts with `pdl_ntfset_`). You will need this in the next step.

> \[Screenshot — Paddle: Saved notification destination with the secret key field visible]

***

## Step 3: Enter credentials in PayGlue

In your PayGlue dashboard, go to **Providers** and click **Connect Paddle**.

Fill in the two fields:

* **API Key** — from Step 1
* **Webhook Secret** — the `pdl_ntfset_...` secret key from Step 2

> \[Screenshot — PayGlue dashboard: Paddle connection page with API Key and Webhook Secret fields]

Click **Save credentials**.

***

## Step 4: Run a health check

Click **Run health check** to confirm PayGlue can reach your Paddle account. A green "Connection established" banner means everything is working.

***

## Step 5: Add Paddle checkout to your Ghost site

Paddle does not generate standalone checkout URLs. Instead, checkout opens as an overlay on your page, triggered by a JavaScript call. You embed Paddle's script once in Ghost, then add a button wherever you want a buy button to appear.

### 5a: Find your client-side token and price ID

You need two values from Paddle before touching Ghost:

**Client-side token** — this is separate from the API key. In Paddle, go to **Developer tools → Authentication → Client-side tokens** and copy the token for your environment (starts with `live_` or `test_`).

> \[Screenshot — Paddle: Client-side tokens section with token value]

**Price ID** — in Paddle, go to **Catalog → Products**, open a product, and copy the ID of the price you want to sell. Price IDs start with `pri_`.

> \[Screenshot — Paddle: Product page showing price list with price IDs (pri\_...)]

### 5b: Add Paddle.js to Ghost via Code Injection

In Ghost Admin, go to **Settings → Code injection → Site header** and add the following. Replace `YOUR_CLIENT_TOKEN` with the client-side token from above:

```html theme={null}
<script src="https://cdn.paddle.com/paddle/v2/paddle.js"></script>
<script>
  Paddle.Initialize({ token: 'YOUR_CLIENT_TOKEN' });
</script>
```

> \[Screenshot — Ghost Admin: Settings → Code injection → Site header with the Paddle script pasted in]

Click **Save**.

<Warning>
  Use your **client-side token** here (starts with `live_` or `test_`), not your API key. The API key is secret and must never appear in your site's HTML.
</Warning>

### 5c: Add a buy button

Wherever you want a checkout button — in a Ghost page, post, or theme template — add a button that calls `Paddle.Checkout.open`. Replace `pri_xxxx` with your actual price ID:

```html theme={null}
<button onclick="Paddle.Checkout.open({ items: [{ priceId: 'pri_xxxx', quantity: 1 }] })">
  Buy now
</button>
```

In a Ghost post or page you can add this via the **HTML card** in the editor. In a theme file you can place it directly in the template.

> \[Screenshot — Ghost editor: HTML card with the Paddle checkout button code]

When a visitor clicks the button, a Paddle checkout overlay opens. After a successful payment, Paddle sends a webhook to PayGlue, which then grants the Ghost membership automatically.

***

## Step 6: Create a mapping

In your PayGlue dashboard, go to **Buy Button**, **Paywall**, or **Pricing Table** and select your Paddle product from the dropdown. Choose which Ghost newsletter to subscribe the buyer to and which welcome email to send, then save.

***

## Supported events

| Paddle event             | PayGlue action                             |
| ------------------------ | ------------------------------------------ |
| `transaction.completed`  | Grant Ghost membership (one-time purchase) |
| `subscription.activated` | Grant Ghost membership                     |
| `subscription.resumed`   | Restore Ghost membership                   |
| `subscription.canceled`  | Revoke Ghost membership                    |
| `subscription.paused`    | Revoke Ghost membership                    |
| `subscription.past_due`  | Revoke Ghost membership                    |

***

## Sandbox mode

Use a sandbox API key (`pdl_sdbx_...`) and a sandbox client-side token (`test_...`) during testing. PayGlue detects sandbox automatically — no extra setting in the dashboard. Make sure your Paddle notification destination in sandbox also points to the same webhook URL.

Remove test members from Ghost Admin before switching to live credentials.

***

## Troubleshooting

**Health check fails after saving credentials**

Confirm you entered the API key (not the client-side token) in the **API Key** field. The API key starts with `pdl_live_` or `pdl_sdbx_`; the client-side token starts with `live_` or `test_`.

**Checkout overlay does not open**

Check the browser console for errors. Common causes:

* `Paddle is not defined` — the Paddle.js script was not added to Code injection, or the page loaded before the script finished
* `Invalid token` — the client-side token is wrong or belongs to the wrong environment (sandbox vs. live)

**Webhook shows as Failed in Analytics**

Open the event and check the error. Common cause: the webhook secret in PayGlue does not match the secret key shown in the Paddle notification destination. They must be identical.

**Ghost member is not created after purchase**

Confirm there is an active mapping for the Paddle price in the Buy Button, Paywall, or Pricing Table editor. PayGlue receives the event but takes no action without a mapping.

***

## Webhook signature verification

Paddle's notification delivery does not currently attach a cryptographic signature to the requests it sends. PayGlue stores your Webhook Secret and will verify the `Paddle-Signature` header automatically if Paddle starts sending one — no action needed on your part. Until then, the per-tenant webhook URL itself acts as the shared secret between Paddle and PayGlue.
