Building

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:

PhoneOutcomeEvent
+254700000001 Payment succeedspayment_intent.paid
+254700000002 User cancelspayment_intent.cancelled
+254700000003 Insufficient fundspayment_intent.failed
+254700000004 STK timeoutpayment_intent.expired
+254700000009 Under reviewpayment_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:

OutcomeEvent fired
successpayment_intent.paid
failedpayment_intent.failed
underpaidpayment_intent.underpaid
overpaidpayment_intent.overpaid
expiredpayment_intent.expired
cancelledpayment_intent.cancelled
reviewpayment_intent.requires_review

You 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 starts with fake, non-withdrawable seed balances that grow as test payments complete:

10,000USDT
10,000USDC
1BTC
10ETH
100SOL

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.

Sandbox first
Build and verify your whole integration in sandbox. The go-live checklist requires a completed sandbox payment and a received webhook before you can request live access. See Sandbox and go-live.