PayKitv0.1 beta

Stripe

Configure Stripe for PayKit, set up webhooks, sync products, and use the customer portal.

Stripe is PayKit's primary payment provider. The @paykitjs/stripe adapter handles all Stripe API interactions, webhook processing, and product syncing.

Installation

pnpm add @paykitjs/stripe
bun add @paykitjs/stripe
npm install @paykitjs/stripe

Configuration

Pass the stripe() adapter to createPayKit with your secret key and webhook secret.

paykit.ts
import { stripe } from "@paykitjs/stripe";
import { createPayKit } from "paykitjs";

export const paykit = createPayKit({
  // ...
  provider: stripe({
    secretKey: process.env.STRIPE_SECRET_KEY!,
    webhookSecret: process.env.STRIPE_WEBHOOK_SECRET!,
  }),
});

Environment variables

Add these two variables to your .env file:

.env
STRIPE_SECRET_KEY=sk_live_...
STRIPE_WEBHOOK_SECRET=whsec_...
  • STRIPE_SECRET_KEY: find this in Stripe Dashboard under Developers > API keys.
  • STRIPE_WEBHOOK_SECRET: generated when you create a webhook endpoint. See the section below.

Webhook setup

In the Stripe Dashboard, go to Developers > Webhooks and create a new endpoint pointing to:

https://your-app.com/paykit/api/webhook/stripe

Select the following events when creating the endpoint:

  • checkout.session.completed
  • customer.subscription.created
  • customer.subscription.updated
  • customer.subscription.deleted
  • invoice.created
  • invoice.finalized
  • invoice.paid
  • invoice.payment_failed
  • invoice.updated
  • payment_method.detached

Stripe discourages selecting all events as it may cause performance issues. Only the events listed above are required by PayKit.

After saving, Stripe displays the signing secret. Copy it as your STRIPE_WEBHOOK_SECRET.

Local development

Use the Stripe CLI to forward webhook events to your local server:

stripe listen --forward-to localhost:3000/paykit/api/webhook/stripe

The CLI prints a webhook signing secret at startup. Use that as STRIPE_WEBHOOK_SECRET in your local .env.

Install the Stripe CLI from stripe.com/docs/stripe-cli. You'll need to run stripe login once to authenticate.

Product syncing

paykitjs push creates and updates Stripe products and prices to match your plan definitions. You don't need to touch the Stripe Dashboard for product management.

pnpm dlx paykitjs push
bunx paykitjs push
npx paykitjs push

Run this once on setup, and again every time you change your plans or pricing.

Customer portal

PayKit can open Stripe's built-in customer portal so users can manage payment methods, invoices, and subscriptions.

const { url } = await paykit.customerPortal({
  customerId: "user_123",
  returnUrl: "https://myapp.com/billing",
});

// redirect the user to `url`
const { url } = await paykitClient.customerPortal({
  returnUrl: window.location.href,
});

window.location.href = url;

The portal is hosted by Stripe, so no additional UI work is needed on your end.

Testing mode

Enable testing on your PayKit instance to use Stripe test clocks during development. This lets you simulate time-based billing events like renewals and trial expirations.

paykit.ts
export const paykit = createPayKit({
  // ...
  testing: {
    enabled: true,
  },
});

Use your Stripe test mode keys (sk_test_...) when testing. Test mode and live mode are completely isolated in Stripe.

API version

PayKit pins the Stripe SDK to a known-good API version so upstream changes don't silently break your integration. Override it with apiVersion if you need a newer version, for example to opt into a preview feature.

paykit.ts
export const paykit = createPayKit({
  // ...
  provider: stripe({
    secretKey: process.env.STRIPE_SECRET_KEY!,
    webhookSecret: process.env.STRIPE_WEBHOOK_SECRET!,
    apiVersion: "2026-03-04.preview",
  }),
});

The pinned default is exported as PAYKIT_STRIPE_API_VERSION if you want to reference it in code.

Managed Payments

Stripe Managed Payments is a preview feature where Stripe takes over tax calculation, payment method selection, and billing address collection on subscription checkout sessions. Enable it with managedPayments: true, and set apiVersion to the preview version that supports it.

paykit.ts
export const paykit = createPayKit({
  // ...
  provider: stripe({
    secretKey: process.env.STRIPE_SECRET_KEY!,
    webhookSecret: process.env.STRIPE_WEBHOOK_SECRET!,
    apiVersion: "2026-03-04.preview",
    managedPayments: true,
  }),
});

Managed Payments is a Stripe preview feature and the API version required may change. Review the Stripe Managed Payments docs before enabling in production. Note: digital products only, no shipping, and several Checkout parameters (automatic_tax, payment_method_types, Connect fields) are not supported in this mode.

On this page