@chipi-stack/chipi-react exposes the read side of the Bills flow as React Query hooks (useGetSkuList, useGetSku, useGetSkuPurchase). The purchase itself is a plain useMutation calling POST /v1/sku-purchases — the SDK’s usePurchaseSku hook wraps an on-chain wallet path that’s reserved for Chipi’s internal PWA, not what you want here.
Every endpoint on this page is guarded by Chipi’s
BearerTokenGuard and requires both an x-api-key header and a customer JWT in the Authorization: Bearer header. The JWT is issued by your auth provider (Clerk, Auth0, BetterAuth, your own); Chipi validates it against the JWKS URL you register for this API key.Install
Wrap your app in ChipiProvider
ChipiProvider accepts your ChipiSDKConfig. It mounts a built-in QueryClient, so you don’t need to provide one separately for Chipi hooks.
Resolve a customer JWT
Every hook + the purchase mutation need a customer JWT. Wrap your auth-provider’s session-token getter in agetBearerToken function. With Clerk:
getAccessTokenSilently), BetterAuth (session.token), or any provider that exposes a signed session token. The token is sent verbatim in the Authorization: Bearer header and validated against your registered JWKS URL.
Browse the catalog — useGetSkuList
Filters are typed in @chipi-stack/types@14.4.0: provider ("TET" | "CHIPI"), category (SkuCategory enum), chipiCategory (curated taxonomy code), carrierName (case-insensitive substring).
getBearerToken returns a non-null token, so it’s safe to render before sign-in.
data shape: PaginatedResponse<Sku> — { data: Sku[], total, page, limit, totalPages }.
Look up a single SKU — useGetSku
Submit a purchase — custom useMutation against /v1/sku-purchases
Use React Query’s useMutation to wrap a plain fetch. The request body matches the CreateSkuPurchaseInput DTO on chipi-back. transactionHash is purely an idempotency key — any unique string is fine; re-sending the same value within the day returns the existing Transaction row instead of double-charging.
Transaction. id is what you pass to useGetSkuPurchase to poll for settlement.
Poll for settlement — useGetSkuPurchase
/configure/notifications in the dashboard.
DEV sandbox
WhenNEXT_PUBLIC_CHIPI_PUBLIC_KEY is a DEV key (pk_dev_...), every purchase is sandboxed:
- No real credits debited. Your
OrgBalance.availableUsdis never touched. - No carrier call. TET is never invoked.
- Deterministic SUCCESS. Every purchase succeeds within milliseconds.
ledgerEntryId starts with le-dev- and skuFileNumber starts with dev-sandbox-. Swap to pk_prod_... (and point the catalog reads at the production data) and the same code path runs against the real carrier.
Putting it together
What’s next
- Need server-side billing instead? See the Node guide — same REST pattern with
fetch+ customer JWT. - Need to filter by carrier? Use
carrierName— case-insensitive substring match. - Need credits to actually charge for purchases? See Billing & Credits.
✅ Verified against the live API on 2026-05-19 — same REST contract used in the production smoke purchase against Legaria (transaction tx-75456794-f4b8-4835-8282-0f89f1964eda, sku-VIR020 Virgin $20 MXN, settled SUCCESS in < 5s).
