Skip to content
Cipay
Esc
navigateopen⌘Jpreview
On this page

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>
  );
}

Choose how much UI to use