React SDK
Build accessible buyer interfaces on top of your authenticated Cipay backend endpoint.
@cipay/client-sdk/react provides TanStack Query hooks and semantic, unstyled components. It calls your createCipayBuyerHandler endpoint; it never accepts a Cipay API key.
React SDK → /api/cipay on your server → Cipay
Add the provider
"use client";
import { CipayProvider } from "@cipay/client-sdk/react";
export function BuyerProvider({ userId, children }: {
userId?: string;
children: React.ReactNode;
}) {
return (
<CipayProvider endpoint="/api/cipay" sessionKey={userId}>
{children}
</CipayProvider>
);
}
Is sessionKey required?
No. Public product, quote, and checkout features work without it. Set it when a user signs in so subscription, order, and invoice queries can run and so cached account data is separated by application user.
| State | Value | Result |
|---|---|---|
| Signed out | Omit it or pass null |
Catalog and checkout work; account hooks stay idle. |
| Signed in | A stable non-secret user key | Account hooks run after the server verifies the session. |
| Logout or user switch | Change or clear it | The provider removes the previous account cache. |
sessionKey is not authentication. Your backend session remains authoritative.
See the components
These previews use the actual SDK components, including catalog images. The pricing example loads published products through ProductsList; its docs-only query client supplies deterministic preview data. The neutral black/white styles are examples that your application can replace.
Product card
import {
CipayProvider,
ProductCard,
useProduct,
} from "@cipay/client-sdk/react";
import { componentPreviewClient } from "../preview/component-data";
export function ProductCardExample() {
// Fetch the product created in Cipay instead of defining it in this component.
const product = useProduct("coffee");
if (product.isPending) return <p>Loading product…</p>;
if (product.isError) return <p role="alert">{product.error.message}</p>;
return (
<div data-preview="product-card">
<ProductCard
product={product.data}
priceLabel={<strong>Billing plan</strong>}
footer={<button>Continue to checkout</button>}
/>
</div>
);
}
export default function ProductCardPreview() {
return (
<CipayProvider endpoint="/api/cipay" queryClient={componentPreviewClient}>
<ProductCardExample />
</CipayProvider>
);
}
Pricing plans
import {
CipayProvider,
ProductCard,
ProductsList,
} from "@cipay/client-sdk/react";
import { componentPreviewClient } from "../preview/component-data";
export function PricingPlans() {
return (
<div data-preview="pricing-plans">
{/* Every card receives a product fetched from Cipay by ProductsList. */}
<ProductsList
input={{ pageSize: 3 }}
aria-label="Pricing plans"
renderProduct={(product) => (
<ProductCard
product={product}
priceLabel={<strong>Billing</strong>}
footer={<button>Choose {product.name}</button>}
/>
)}
/>
</div>
);
}
export default function PricingPlansPreview() {
return (
<CipayProvider
endpoint="/api/cipay"
queryClient={componentPreviewClient}
>
<PricingPlans />
</CipayProvider>
);
}