- You charged the user off-platform (credits flow)
- You collected an on-chain USDC payment
Most integrators pre-fund Chipi credits and charge their own users by card,
transfer, or in-app balance — that side is yours. When a purchase fails:
- Chipi restores your credits automatically and sends
sku-purchase.refunded(so your ledger reconciles off one signal). - You refund the user in your own payment system (reverse the card charge, credit their in-app balance, etc.) — Chipi never touched the user’s money, so only you can return it.
sku-purchase.failed / sku-purchase.refunded and trigger your
own refund. No on-chain work is involved.Returning the user’s money is always the integrator’s responsibility — you
collected it, so you control where it sits. Chipi restores your credits and
gives you the signal + data to make the user whole.
Webhook events
Configure a webhook at/configure/notifications in the dashboard. Every body is
HMAC-signed (see Verifying the signature).
Verifying the signature
Each delivery includes achipi-signature header: HMAC-SHA256(rawBody, signingKey)
as hex. Verify it against the raw request body before trusting the event.
Executing an on-chain refund
Only relevant if you collected an on-chain USDC payment. Onsku-purchase.refund-due
the payload carries everything you need:
1
Verify settlement by the Transfer event — never the tx status
A Starknet tx can report
execution_status = SUCCEEDED while the inner
transfer no-op’d (a “phantom success”). Read the receipt and confirm a USDC
Transfer event into your wallet actually fired. No event → no money
arrived → do not refund. This doubles as the ownership gate: only refund
payments that settled into your wallet.2
Be idempotent on the payment hash
Reserve
refund-<paymentTransactionHash> before sending; if it already
exists, skip. Webhooks can deliver more than once — refund exactly once.3
Cap the amount
refund.amount is advisory; verify the actual settled Transfer amount and
never exceed it, bounded by a sane maximum. Above the cap, escalate to manual
review instead of auto-paying.4
Refund USDC from your wallet
Send USDC from your collection wallet back to
refund.recipient and record the
refund tx hash so it’s auditable.Avoid charging twice in the first place
Refunds are the safety net — the better fix is not double-charging:- Reuse the idempotency key on retry.
transactionHashonPOST /v1/sku-purchasesis the idempotency key. Persist it per(skuId, reference, amount)and reuse it when the user taps “try again” — a repeated key returns the existing purchase instead of creating a second charge. - Lock the buy action while a purchase is in flight to prevent a double-submit.
- Chipi also rejects an exact
(skuId, reference, amount)repeat within the carrier’s dedup window before any new debit, as a server-side backstop.
