Skip to main content
The useCustomer hook fetches customer profile data and feature access in one request. If the customer does not exist yet, PriceOS will create it automatically.
Setup first: see the React integration guide.
const result = useCustomer<MyFeatures>(options?)

Parameters

options.enabled
boolean
Enable or disable fetching. Defaults to true.
options.errorOnNotFound
boolean
When true, a 404 is surfaced as an error instead of returning null. Defaults to false.
options.swr
SWRConfiguration<PriceOSCustomer<MyFeatures> | null, Error>
Optional SWR config for caching/revalidation behavior.

Returns

customer
PriceOSCustomer<MyFeatures> | null
Customer data including profile fields and featureAccess.
isLoading
boolean
Whether data is currently loading.
error
Error | null
Error from the latest request.
refetch
() => Promise<void>
Manually revalidate customer data.
trackUsage
(body) => Promise<TrackUsageResponse>
Tracks usage and revalidates customer and feature-access caches.
checkout
(body) => Promise<CreateCheckoutResponse>
Creates a checkout session and redirects to Stripe Checkout.
openCustomerPortal
(body?) => Promise<CreateCustomerPortalResponse>
Creates a customer portal session and redirects to Stripe Customer Portal.

trackUsage body

featureKey
string
required
Feature key to track usage for (typed to your tracked limit feature keys when using generated types).
amount
number
Usage amount to record. Defaults to 1.
eventKey
string
Stable event key for retries and deduplication.
occurredAt
number
Unix timestamp in milliseconds for when the event happened.
metadata
Record<string, string>
Optional string key/value metadata attached to the usage event.
When using built-in Next.js handlers (priceos/next), client hook calls must use a positive amount. For negative adjustments, track usage on your backend with the Node.js SDK or REST API.

Examples

import { useCustomer } from "priceos/react";
import type { MyFeatures } from "./priceos.types";

export function CustomerCard() {
  const { customer, isLoading, error, refetch, trackUsage, checkout, openCustomerPortal } = useCustomer<MyFeatures>();

  const customerName = customer?.name ?? "Unknown";
  const hasBlogAccess = customer?.featureAccess?.blogs?.hasAccess;

  async function onAddSeat() {
    await trackUsage({
      featureKey: "team_seats",
      amount: 1,
      eventKey: `add_team_seat_${Date.now()}`,
    });
  }

  async function onUpgrade() {
    await checkout({
      productKey: "starter_monthly",
      successUrl: "https://app.acme.com/settings/billing?checkout=success",
      cancelUrl: "https://app.acme.com/settings/billing?checkout=canceled",
    });
  }

  async function onManageBilling() {
    await openCustomerPortal();
  }

  if (isLoading) return <div>Loading...</div>;
  if (error) return <button onClick={refetch}>Retry</button>;

  return (
    <div>
      <h3>{customerName}</h3>
      <p>Blog access: {hasBlogAccess ? "Yes" : "No"}</p>
      <button onClick={onAddSeat}>Add teammate</button>
      <button onClick={onUpgrade}>Upgrade</button>
      <button onClick={onManageBilling}>Manage billing</button>
    </div>
  );
}