@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 requiresAuthorization: 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).
PaginatedResponse<Sku>: { data, total, page, limit, totalPages }.
Buy a SKU
The SDK’spurchaseSku 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:
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.
/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 thex-api-key header carries a DEV key (pk_dev_...), the entire purchase flow 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.
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/billsto discover what’s available. - Configure your per-transaction markup at
/configure/skus. - Set up a webhook at
/configure/notificationsso you don’t have to poll. - See the React guide and the Python guide for idiomatic versions of the same REST + JWT pattern.
