Skip to main content

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.

The chipi-stack Python package exposes the bills flow with the same shape as the Node SDK — same CreateSkuPurchaseParams, same Transaction response, same polling pattern.
Requires chipi-stack >= 2.1.0 — earlier versions had a create_sku_transaction method that posted to a non-existent endpoint. The current purchase_sku (sync) and apurchase_sku (async) methods documented here go to the real POST /sku-purchases and match the Node SDK contract.

Install

pip install "chipi-stack>=2.1.0"

Initialise the SDK

import os
from chipi_sdk import ChipiSDK, ChipiSDKConfig

sdk = ChipiSDK(
    config=ChipiSDKConfig(
        api_public_key=os.environ["CHIPI_PUBLIC_KEY"],
        api_secret_key=os.environ["CHIPI_SECRET_KEY"],
        # alpha_url is only needed for staging
        alpha_url=os.environ.get("CHIPI_BASE_URL"),
    )
)

Browse the catalog — get_sku_list

get_sku_list accepts the same filters as the Node SDK: category (legacy SkuCategory), chipi_category (curated taxonomy: "RECARGAS", "GIFT_CARDS", "GENERAL", "GAMING", "TELEFONIA"), carrier_name (case-insensitive substring), provider, plus pagination and locale.
from chipi_sdk import GetSkuListQuery

result = sdk.get_sku_list(
    params=GetSkuListQuery(
        chipi_category="RECARGAS",
        carrier_name="Telcel",
        limit=20,
    ),
    bearer_token=os.environ["CHIPI_SECRET_KEY"],
)

print(f"{result.total} matching SKUs")
print(result.data[0].name, result.data[0].fixed_amount, result.data[0].currency)
The async variant is aget_sku_list. Same applies to all paired methods on this page.

Charge the user’s wallet — purchase_sku

from chipi_sdk import (
    Chain,
    ChainToken,
    Currency,
    CreateSkuPurchaseParams,
    WalletData,
)

result = sdk.purchase_sku(
    params=CreateSkuPurchaseParams(
        sku_id=chosen_sku.id,
        sku_reference=user_phone,                 # e.g. "5512345678"
        currency_amount=chosen_sku.fixed_amount,  # 200 for $200 MXN
        currency=Currency.MXN,
        chain=Chain.STARKNET,
        token=ChainToken.USDC,
        encrypt_key=user_pin,
        wallet=WalletData(
            public_key=user_wallet.public_key,
            encrypted_private_key=user_wallet.encrypted_private_key,
        ),
    ),
    bearer_token=os.environ["CHIPI_SECRET_KEY"],
)

purchase_id = result.id
print(f"Purchase created: {purchase_id}")

Poll for settlement — get_sku_purchase

import time

def wait_for_settlement(sdk, purchase_id: str):
    for _ in range(6):
        purchase = sdk.get_sku_purchase(
            purchase_id,
            bearer_token=os.environ["CHIPI_SECRET_KEY"],
        )
        if purchase.status in ("SUCCESS", "FAILED"):
            return purchase
        time.sleep(2.5)
    raise TimeoutError("Settlement timeout — keep polling or use a webhook")

final = wait_for_settlement(sdk, purchase_id)
print(final.status)  # "SUCCESS" | "FAILED"
For production, prefer a webhook over polling — configure one at /configure/notifications in the dashboard.

Putting it together

import os, time
from chipi_sdk import (
    ChipiSDK,
    ChipiSDKConfig,
    Chain,
    ChainToken,
    Currency,
    CreateSkuPurchaseParams,
    GetSkuListQuery,
    WalletData,
)


def pay_telcel_recharge(sdk, user_phone, user_pin, user_wallet):
    bearer = os.environ["CHIPI_SECRET_KEY"]

    # 1. Find the right SKU (Telcel $200)
    listing = sdk.get_sku_list(
        params=GetSkuListQuery(
            chipi_category="RECARGAS", carrier_name="Telcel", limit=50
        ),
        bearer_token=bearer,
    )
    sku = next((s for s in listing.data if s.fixed_amount == 200), None)
    if sku is None:
        raise ValueError("SKU not found")

    # 2. Charge the wallet
    result = sdk.purchase_sku(
        params=CreateSkuPurchaseParams(
            sku_id=sku.id,
            sku_reference=user_phone,
            currency_amount=200,
            currency=Currency.MXN,
            chain=Chain.STARKNET,
            token=ChainToken.USDC,
            encrypt_key=user_pin,
            wallet=user_wallet,
        ),
        bearer_token=bearer,
    )

    # 3. Wait for settlement
    for _ in range(6):
        p = sdk.get_sku_purchase(result.id, bearer_token=bearer)
        if p.status == "SUCCESS":
            return p
        if p.status == "FAILED":
            raise RuntimeError("Purchase failed")
        time.sleep(2.5)

    raise TimeoutError("Settlement timeout — set up a webhook for production")
✅ Verified on 2026-05-10 by python/tests/test_staging_smoke_purchases.py at commit 3068c85 — runs in CI with a real TEST_SKU_ID against live staging when credentials + TEST_WALLET_* secrets are set. Mirrors the Node staging-purchases.test.ts so the contracts stay aligned across SDKs.

What’s next

  • Browse the catalog visually in the dashboard at /admin/bills.
  • Configure your per-transaction markup at /configure/skus.
  • Set up a webhook at /configure/notifications so you don’t have to poll.
  • Need server-side billing in TypeScript? See the Node guide. React? See the React guide.