Become a Paddle partner
Join the Paddle partner program to read this content. You'll also get access to our partner API and agent tooling. Let us know a few details about your business to get started. Already a partner? Log in to view this page.
After you've created a seller's product catalog, you're ready to build a pricing page and checkout.
You can use Paddle.js to integrate into a seller's frontend. It handles rendering localized prices on a pricing page and securely taking payment using Paddle Checkout.
Overview
Integrate checkout and pricing page in three steps:
- Create a client-side token
Authenticate Paddle in the frontend. - Return localized prices for a pricing page
Render localized prices on a pricing page. - Open a checkout
Open a checkout in the seller's frontend.
Create a client-side token
- Layer
- Your agent
- Authentication
- Seller API key
- Environment
- Sandbox, Live
Client-side tokens authenticate Paddle in the frontend. They're safe to publish.
To create a client-side token, send a POST request to the /client-tokens endpoint.
If successful, Paddle returns a 201 with the created client-side token entity. Extract the token for both sandbox and live, then store against the user record in your database.
{ "name": "App integration", "description": "Used to build a pricing page and checkout."}{ "data": { "id": "ctkn_01ghbkd0frb9k95cnhwd1bxpvk", "seller_id": "sel_01jqx8k5z9r2m4n6p8s0t2v4w6", "token": "live_7d279f61a3499fed520f7cd8c08", "name": "App integration", "description": "Used to build a pricing page and checkout.", "status": "active", "created_at": "2026-06-26T14:36:14.695Z", "updated_at": "2026-06-26T14:36:14.695Z", "revoked_at": null }, "meta": { "request_id": "1681f87f-9c36-4557-a1da-bbb622afa0cc" }}Install and initialize Paddle.js
- Layer
- Your agent
- Authentication
- Client-side token
- Environment
- Sandbox, Live
Install @paddle/paddle-js using your package manager:
pnpm add @paddle/paddle-jsyarn add @paddle/paddle-jsnpm install @paddle/paddle-jsThen import it where you'll initialize Paddle.js with the client-side token. For sandbox, also set the environment to sandbox.
Call initializePaddle() with the seller's client-side token and keep the returned paddle instance. You'll use this to render prices and open checkouts. Pass an eventCallback to receive checkout events as the buyer moves through:
import { initializePaddle, type Paddle } from "@paddle/paddle-js";
let paddle: Paddle | undefined;
initializePaddle({ environment: "sandbox", // omit if live token: "test_9f8e7d6c5b4a3f2e1d0c9b8a7", eventCallback: (event) => { // Update the seller's UI as checkout progresses. Provisioning is handled // server-side by webhooks, not here. if (event.name === "checkout.completed") { // Show a confirmation in the seller's app. } },}).then((p) => { paddle = p;});Return localized prices for a pricing page
- Layer
- Your agent
- Authentication
- Client-side token
- Environment
- Sandbox, Live
A pricing page shows the seller's plans with prices localized in the right currency, formatted for their locale, with estimated tax.
You can use Paddle.PricePreview() to take your price IDs and return display-ready amounts.
Resolve the seller's stored external_ids to the current environment's price IDs, then call PricePreview() on the paddle instance:
const preview = await paddle?.PricePreview({ items: [ { priceId: "pri_starter_monthly", quantity: 1 }, { priceId: "pri_pro_monthly", quantity: 1 }, ], // Omit `address` to let Paddle localize from the buyer's IP address, // or pass a country to preview a specific market. // address: { countryCode: "US" },});
for (const item of preview?.data.details.lineItems ?? []) { // `formattedTotals` is display-ready — currency, locale, and tax included. renderPlan(item.price.name, item.formattedTotals.total);}Re-run PricePreview() whenever the buyer switches plan or billing cycle.
Open a checkout
- Layer
- Your agent
- Authentication
- Client-side token
- Environment
- Sandbox, Live
When a buyer chooses a plan, open Paddle Checkout with Paddle.Checkout.open(). Pass the same price ID that you used in the pricing page, plus anything you'll need to reconcile later as customData:
function openCheckout(priceId: string) { paddle?.Checkout.open({ items: [{ priceId, quantity: 1 }], customData: { // Echoed back on transaction and subscription webhooks, so you can tie // the purchase to your own records without storing PII in Paddle. app_user_id: "user_42891", }, settings: { // Where the buyer lands after paying. Falls back to the seller's // default payment link if omitted. successUrl: "https://aeroedit.com/welcome", }, });}As Paddle is the merchant of record, Paddle Checkout collects payment and handles tax, fraud, and compliance for the seller.
To redirect when a checkout is completed, pass a successUrl to the settings object or use an event callback for the checkout.completed event.
React to checkout events
The eventCallback you set when initializing Paddle.js fires across the checkout lifecycle, including checkout.completed, checkout.closed, checkout.payment_failed, and others.
These are most useful when working with inline checkouts, where the payment form is embedded in the seller's app but the seller has to build the UI to display pricing and order details.
Handle provisioning server-side
A customer can close the checkout tab before the callback fires or experience connection issues, so use webhooks to grant access reliably.