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

# Send Paddle Purchases to Qonversion

Every Paddle purchase must be linked to a Qonversion user so Qonversion can grant entitlements and attribute revenue. There are two ways to do it:

* **Automatic (recommended)** — tag the Paddle Checkout with the Qonversion user in `custom_data`. Qonversion reads it from the Paddle webhook and grants entitlements automatically, including for later renewals, refunds, and cancellations. No purchase-submission call is required.
* **Explicit** — submit the completed purchase yourself from your server (REST API) or the browser (Web SDK), passing the Qonversion user in the request.

## 1. Link the Qonversion user with `custom_data`

When you open the Paddle Checkout, set `custom_data.qonversion_client_uid` to the buyer's Qonversion User ID. Paddle stores it on the resulting transaction and includes it in every webhook it sends — that is how Qonversion maps the purchase (and all future events on the same subscription) to the user.

<CodeGroup>
  ```javascript Paddle.js overlay checkout theme={null}
  Paddle.Checkout.open({
    items: [{ priceId: 'pri_01hv4rrk', quantity: 1 }],
    customData: {
      qonversion_client_uid: '<QONVERSION_USER_ID>',
    },
  });
  ```
</CodeGroup>

<Info>
  The key must be exactly `qonversion_client_uid`. Its value is the Qonversion User ID — see [Getting the Qonversion User ID](#getting-the-qonversion-user-id).
</Info>

If you create transactions or subscriptions with the Paddle API instead of the overlay checkout, set the same `qonversion_client_uid` key on the request's `custom_data`.

### Customer-level fallback

If a webhook payload does not carry `custom_data.qonversion_client_uid`, Qonversion falls back to the Paddle **customer's** `custom_data`. You can set it when you create or update the customer:

<CodeGroup>
  ```bash cURL — Paddle API theme={null}
  curl --request PATCH \
    --url https://api.paddle.com/customers/{customer_id} \
    --header 'Authorization: Bearer {paddle_api_key}' \
    --header 'Content-Type: application/json' \
    --data-raw '{
      "custom_data": {
        "qonversion_client_uid": "<QONVERSION_USER_ID>"
      }
    }'
  ```
</CodeGroup>

<Warning>
  If neither the transaction nor the customer carries `qonversion_client_uid`, Qonversion acknowledges the Paddle webhook but cannot map the purchase to a user, so no entitlement is granted. Set it at checkout (or on the customer) before the first payment.
</Warning>

### Getting the Qonversion User ID

The Qonversion User ID is the value you place in `qonversion_client_uid` (and in the `{user_id}` of the REST call below). Obtain it in one of two ways:

* **From the SDK** — call the `userInfo()` method and use the `qonversionId` property from the result. See [User Identifiers](/docs/user-identifiers) for details.
* **Via API** — create a user by calling `POST /v3/users/{id}`. See the API reference for details.

## 2. Submit the purchase explicitly

If you prefer to push purchases yourself instead of relying on the automatic webhook mapping, send the completed purchase to Qonversion after a successful payment. Capture the Paddle identifiers from the completed transaction and call:

<Warning>
  The client-side `checkout.completed` event gives you the `transaction_id` (`txn_`) and `product_id` (`pro_`), but **not** the `subscription_id` — Paddle creates the subscription asynchronously a few seconds later. For a subscription purchase, read the `subscription_id` server-side from the `transaction.completed` / `subscription.created` webhook (or `GET /transactions/{id}`) before submitting. For subscriptions, prefer the automatic `custom_data` flow above, which has no such timing constraint.
</Warning>

```bash theme={null}
curl -X POST \
  https://api.qonversion.io/v3/users/{user_id}/purchases \
  -H "Authorization: Bearer {project_key}" \
  -H "Content-Type: application/json" \
  -d '{
    "currency": "USD",
    "price": "9.99",
    "paddle_store_data": {
      "type": "subscription",
      "transaction_id": "{paddle_transaction_id}",
      "subscription_id": "{paddle_subscription_id}",
      "product_id": "{paddle_product_id}"
    }
  }'
```

Replace `{paddle_transaction_id}` and `{paddle_subscription_id}` with the values from the completed Paddle transaction, and `{paddle_product_id}` with the Paddle product ID. The `{user_id}` is the Qonversion User ID (see [above](#getting-the-qonversion-user-id)).

| Field                               | Source                                                                                 |
| ----------------------------------- | -------------------------------------------------------------------------------------- |
| `currency`                          | transaction currency code                                                              |
| `price`                             | transaction total                                                                      |
| `paddle_store_data.type`            | `subscription` for recurring products, `non_recurring` for one-time purchases          |
| `paddle_store_data.transaction_id`  | Paddle transaction id (`txn_`)                                                         |
| `paddle_store_data.subscription_id` | Paddle subscription id (`sub_`). Required for `subscription`; omit for `non_recurring` |
| `paddle_store_data.product_id`      | Paddle product id (`pro_`)                                                             |

## Web SDK

If you are using Qonversion on the web, you can also use the [Qonversion Web SDK](/docs/web-sdk) to submit the purchase. After a successful Paddle payment, pass the purchase data to `sendPaddlePurchase`.

<Warning>
  The Web SDK object differs from the REST body above. Its fields are **camelCase** (`transactionId`, `productId`, `subscriptionId`), and the one-time `type` value is **`inapp`**, not `non_recurring` (the SDK maps it to `non_recurring` on the wire for you).
</Warning>

<CodeGroup>
  ```javascript theme={null}
  const purchase = await qonversionInstance.sendPaddlePurchase({
    price: '9.99',
    currency: 'USD',
    transactionId: 'txn_01hv4rrk',
    productId: 'pro_01hv4rrk',
    type: 'subscription',           // or 'inapp' for one-time purchases
    subscriptionId: 'sub_01hv4rrk', // required for 'subscription'; omit for 'inapp'
  });
  ```
</CodeGroup>

See the full [Paddle Integration guide](/docs/paddle-integration) for details.
