Client

Call PayKit from the browser with a typed HTTP client.

The PayKit client SDK lets you call billing operations from the browser. It's fully type-safe, and methods and their inputs are inferred from your server instance.

Setup

Install the client and create an instance typed to your server paykit export. It uses import type to carry server types into the browser without bundling any server code.

src/lib/paykit-client.ts
import { createPayKitClient } from "paykitjs/client";
import type { paykit } from "@/server/paykit";

export const paykitClient = createPayKitClient<typeof paykit>();

The client resolves the current customer automatically on each request. You need identify configured on your server instance for this to work. See customer identification for details.

Available methods

The client exposes subscribe and customerPortal. Neither requires a customerId since it's resolved from the incoming request via identify.

subscribe

Works the same as the server-side subscribe, but without customerId. Returns { paymentUrl }.

// Subscribe from a React component
<Button
  onClick={async () => {
    const { paymentUrl } = await paykitClient.subscribe({
      planId: "pro", // type-safe, only valid plan IDs accepted
      successUrl: "/billing/success",
      cancelUrl: "/billing",
    });
    if (paymentUrl) {
      window.location.href = paymentUrl;
    }
  }}
>
  Upgrade to Pro
</Button>

customerPortal

Opens Stripe's customer portal. Returns { url }.

// Open customer billing portal
const { url } = await paykitClient.customerPortal({
  returnUrl: window.location.href,
});
window.location.href = url;

Custom base URL

If you changed basePath on your server instance, pass the PayKit root URL to the client.

export const paykitClient = createPayKitClient<typeof paykit>({
  baseURL: "/custom",
});

The client derives its API URL automatically, so baseURL: "/custom" maps to /custom/api under the hood.

You can also pass an absolute URL like https://example.com/custom.

Separate frontend and API origins

When the browser application and PayKit API use different origins, add the browser origin to the server's trustedOrigins. This protects cookie-authenticated billing mutations and lets PayKit resolve relative provider return URLs against the browser application.

paykit.ts
export const paykit = createPayKit({
  // ...
  trustedOrigins: ["https://app.example.com"],
});
paykit-client.ts
export const paykitClient = createPayKitClient<typeof paykit>({
  baseURL: "https://api.example.com/paykit",
});

No trustedOrigins configuration is needed when the frontend and PayKit handler share an origin. If a cross-origin request is rejected, PayKit logs the rejected origin and the configuration needed to trust it.

Type safety

The client infers available plan IDs directly from your server instance type. If you pass an invalid planId, TypeScript catches it at compile time. See TypeScript for more on how type inference works across the stack.

On this page