Test data
Everything below works only in sandbox (a cwk_test_… key). No real money moves, but webhooks, signatures, and request logs behave exactly like production.
M-Pesa test numbers
Set one of these as the customer phone on a test payment and the sandbox tester drives that outcome automatically:
| Phone | Outcome | Event |
|---|---|---|
+254700000001 | Payment succeeds | payment_intent.paid |
+254700000002 | User cancels | payment_intent.cancelled |
+254700000003 | Insufficient funds | payment_intent.failed |
+254700000004 | STK timeout | payment_intent.expired |
+254700000009 | Under review | payment_intent.requires_review |
Triggerable outcomes
From the console's Sandbox tester you can create a test payment and drive it to any outcome regardless of the method, which moves the intent and fires the matching webhook:
success -> payment_intent.paid
failed -> payment_intent.failed
underpaid -> payment_intent.underpaid
overpaid -> payment_intent.overpaid
expired -> payment_intent.expired
cancelled -> payment_intent.cancelled
review -> payment_intent.requires_reviewYou can also send a standalone test webhook of any type, and refund a sandbox payment to fire payment_intent.refunded.
Sandbox balances
Each sandbox merchant has fake, non-withdrawable balances that grow as test payments complete: USDT 10000, USDC 10000, BTC 1, ETH 10, SOL 100. Use Reset sandbox data to clear all test payments, refunds, webhook deliveries, and logs and return to the seed balances. Live data is never touched.