Documentation Index
Fetch the complete documentation index at: https://docs.chipipay.com/llms.txt
Use this file to discover all available pages before exploring further.
This page shows the full purchase flow — browse catalog → charge wallet → poll for settlement — with code lifted from staging-integration/staging-purchases.test.ts.
Install
npm install @chipi-stack/backend
Initialise the SDK
import { ChipiServerSDK } from "@chipi-stack/backend";
const sdk = new ChipiServerSDK({
apiPublicKey: process.env.CHIPI_PUBLIC_KEY!,
apiSecretKey: process.env.CHIPI_SECRET_KEY!,
baseUrl: process.env.CHIPI_BASE_URL, // omit for production
});
Browse the catalog
Find the SKU your user wants to pay. Filter by category (RECARGAS, GIFT_CARDS, GENERAL, TELEFONIA) and optionally by carrierName.
// Example: list Telcel phone-recharge options
const skus = await sdk.getSkuList({
category: "RECARGAS",
carrierName: "Telcel",
limit: 20,
});
console.log(skus.length, "SKUs found");
console.log(skus[0]); // { id, chipiName, fixedAmount, currency, carrierName, ... }
Charge the user’s wallet
purchaseSku debits the user’s gasless wallet for the SKU price (in USDC) plus your configured markup, then settles with the provider in MXN. Chipi’s paymaster covers gas.
import { Currency } from "@chipi-stack/backend"; // re-exported from @chipi-stack/types
const result = await sdk.purchaseSku({
params: {
skuId: chosenSku.id, // from getSkuList above
skuReference: userPhoneNumber, // user-facing reference (e.g. phone number)
currencyAmount: chosenSku.fixedAmount, // amount in the SKU's local currency (MXN)
currency: Currency.MXN,
chain: "STARKNET",
token: "USDC",
encryptKey: userPin,
wallet: {
publicKey: userWallet.publicKey,
encryptedPrivateKey: userWallet.encryptedPrivateKey,
},
},
});
const purchaseId = result.id;
console.log("Purchase created:", purchaseId);
Poll for settlement
The purchase progresses through PENDING → PROCESSING → SUCCESS (or FAILED). Most transactions settle within seconds, but pin-codes for gift cards can take longer.
async function waitForSettlement(purchaseId: string) {
for (let i = 0; i < 6; i++) {
const purchase = await sdk.getSkuPurchase(purchaseId);
if (purchase.status === "SUCCESS" || purchase.status === "FAILED") {
return purchase;
}
await new Promise((r) => setTimeout(r, 2_500));
}
throw new Error("Settlement timeout — keep polling or use a webhook");
}
const final = await waitForSettlement(purchaseId);
console.log(final.status); // "SUCCESS" | "FAILED"
For production, prefer a webhook over polling — configure one at /configure/notifications in the dashboard.
Putting it together
import { ChipiServerSDK, Currency } from "@chipi-stack/backend";
async function payTelcelRecharge(
sdk: ChipiServerSDK,
userPhone: string,
userPin: string,
userWallet: { publicKey: string; encryptedPrivateKey: string },
) {
// 1. Find the right SKU — say, Telcel $200 prepaid
const skus = await sdk.getSkuList({ category: "RECARGAS", carrierName: "Telcel" });
const sku = skus.find((s) => s.fixedAmount === 200);
if (!sku) throw new Error("SKU not found");
// 2. Charge the user's wallet
const { id: purchaseId } = await sdk.purchaseSku({
params: {
skuId: sku.id,
skuReference: userPhone,
currencyAmount: 200,
currency: Currency.MXN,
chain: "STARKNET",
token: "USDC",
encryptKey: userPin,
wallet: userWallet,
},
});
// 3. Wait for settlement
for (let i = 0; i < 6; i++) {
const p = await sdk.getSkuPurchase(purchaseId);
if (p.status === "SUCCESS") return p;
if (p.status === "FAILED") throw new Error("Purchase failed");
await new Promise((r) => setTimeout(r, 2_500));
}
throw new Error("Settlement timeout — set up a webhook for production");
}
✅ Verified by staging-integration/staging-purchases.test.ts at commit 90c7020 (2026-03-13). Runs in CI on every PR from staging → main with a real TEST_SKU_ID against live staging — costs ~0.001USDC+0.01-0.05 STRK gas per execution.
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.
- Python and React guides land in follow-up PRs.