Checkout

Create checkout sessions programmatically to collect payments from your customers

If you want to integrate the checkout process directly into your application, you can use our API to create sessions programmatically. This gives you full control over when and how your customers are prompted to pay.

Checkout isn’t just for one-time payments - when a customer completes checkout, Paid creates an order (subscription) that tracks their plan, billing cycle, and usage over time.

You’ll need a Product ID to get started. You can find it in the Products section of your dashboard, or create one via the API.

Make sure you’ve connected Stripe before creating checkouts. Stripe is required to process payments.

Creating a session

To create a checkout session, call the API with the products you want the customer to purchase and a URL to redirect them to after payment.

The API returns an object containing all the information about the session, including a url where you should redirect your customer so they can complete their order.

1import { PaidClient } from "@paid-ai/paid-node";
2
3const client = new PaidClient({ token: "YOUR_PAID_API_KEY" });
4
5const checkout = await client.checkouts.createCheckout({
6 products: [{ id: "prod_abc123" }],
7 customerId: "cus_xyz789",
8 successUrl: "https://example.com/success?checkout={CHECKOUT_ID}",
9});
10
11// Redirect your customer to this URL
12console.log(checkout.body.url);

The {CHECKOUT_ID} placeholder in successUrl is automatically replaced with the checkout’s display ID (e.g. chk_abc123), so you can look up the result when the customer lands back on your site.

Multiple products

You can pass several products in a single session. If a product has plan tiers, the customer picks one during checkout. If it doesn’t, it’s shown directly with its base pricing.

1const checkout = await client.checkouts.createCheckout({
2 products: [
3 { id: "prod_platform" },
4 { id: "prod_addon_storage" },
5 ],
6 successUrl: "https://example.com/success",
7});

Automatic upgrades

If you pass a customerId and that customer already has an active order for the product, Paid automatically handles the upgrade with proration. No need for separate upgrade logic — the same API call works for both new purchases and plan changes.

1// Works for both new customers and upgrades
2const checkout = await client.checkouts.createCheckout({
3 products: [{ id: "prod_abc123" }],
4 customerId: "cus_xyz789",
5 successUrl: "https://example.com/success",
6});

Anonymous checkout

If you don’t have a customer yet — for example, on a public pricing page — you can omit customerId entirely. The checkout page will collect the customer’s name and email, and Paid creates the customer record and order on completion.

1const checkout = await client.checkouts.createCheckout({
2 products: [{ id: "prod_abc123" }],
3 successUrl: "https://example.com/welcome",
4});

Expiration

By default, checkout sessions expire after 24 hours. You can override this by setting expiresAt to an ISO 8601 timestamp.

1const checkout = await client.checkouts.createCheckout({
2 products: [{ id: "prod_abc123" }],
3 successUrl: "https://example.com/welcome",
4 expiresAt: "2026-04-01T00:00:00.000Z",
5});

Metadata

You can attach arbitrary key-value metadata to a checkout session for your own tracking. This data is returned on the checkout object but is never shown to the customer.

1const checkout = await client.checkouts.createCheckout({
2 products: [{ id: "prod_abc123" }],
3 successUrl: "https://example.com/welcome",
4 metadata: { campaign: "spring_launch", referrer: "pricing_page" },
5});