Skip to main content
This page shows the full purchase flow — browse catalog → debit credits → poll for settlement — using the public REST API and @chipi-stack/backend for the read-only calls. The purchase itself is a plain HTTP POST because the SDK’s purchaseSku is wired to an internal wallet-pays-on-chain path that doesn’t apply to API-key integrations.

Install

You only need the SDK for the read calls (getSkuList, getSku, getSkuPurchase). The purchase POST is plain fetch, so you can skip the SDK entirely if you want zero dependencies.

Initialise the SDK

Resolve a customer JWT

Every bill purchase requires Authorization: Bearer <JWT> in addition to the x-api-key header. The JWT is issued by your auth provider — Chipi validates it against the JWKS rule you configured for this API key (typically https://clerk.yourdomain.com/.well-known/jwks.json). In a server-side flow, you’d typically receive the JWT from your authenticated session for the user making the purchase:

Browse the catalog

getSkuList returns a paginated response. GetSkuListQuery supports four filters today (all typed in @chipi-stack/types@14.4.0): provider ("TET" | "CHIPI"), category (SkuCategory enum — the upstream classification), chipiCategory (the admin-curated taxonomy code, e.g. "RECARGAS", "GIFT_CARDS", "GENERAL", "TELEFONIA"), and carrierName (case-insensitive substring match against the carrier).
The response is a PaginatedResponse<Sku>: { data, total, page, limit, totalPages }.

Buy a SKU

The SDK’s purchaseSku requires an on-chain wallet path that’s reserved for Chipi’s internal PWA. For API-key integrations, call the REST endpoint directly. Same auth headers as the read calls, body matches the CreateSkuPurchaseInput DTO:
The response is the freshly-created Transaction row. status is PENDING initially. The ledgerEntryId field references the debit Chipi just took against your credits balance.

Poll for settlement

getSkuPurchase is a read; the SDK works fine here.
Most transactions settle in under 5 seconds. Gift cards with pin-code delivery can take longer. For production traffic, prefer a webhook over polling — configure one at /configure/notifications in the dashboard. Chipi delivers sku-purchase.completed, sku-purchase.failed, and sku-purchase.refunded events with HMAC-signed bodies.

DEV sandbox

When the x-api-key header carries a DEV key (pk_dev_...), the entire purchase flow is sandboxed:
  • No real credits debited. Your OrgBalance.availableUsd is never touched.
  • No carrier call. TET is never invoked.
  • Deterministic SUCCESS. Every purchase succeeds within milliseconds.
Sandbox responses are tagged so your integration code can distinguish them:
You can integrate freely against pk_dev_... without worrying about credits or accidentally recharging a real phone. Swap the API key to pk_prod_... (and point the SKU lookup at the production catalog) and the same code path runs against the real carrier with no other changes.

Putting it together

✅ Verified against the live API on 2026-05-19 — exact pattern used in the production smoke purchase for sku-VIR020 (Virgin $20 MXN). 201 + PENDING from the POST, SUCCESS within 5 seconds on the first poll, real TET file number returned, recharge landed on a live phone.

What’s next

  • Browse the catalog visually in the dashboard at /admin/bills to discover what’s available.
  • Configure your per-transaction markup at /configure/skus.
  • Set up a webhook at /configure/notifications so you don’t have to poll.
  • See the React guide and the Python guide for idiomatic versions of the same REST + JWT pattern.