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.
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 the provider'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 baseURL to match.
export const paykitClient = createPayKitClient<typeof paykit>({
baseURL: "/custom/api",
});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.