Guides
Test in sandbox
Build the whole flow against Safaricom's sandbox with test credentials — including the failure paths — before a shilling moves.
Get sandbox credentials
Create an app on the Safaricom Daraja portal and open its Sandbox credentials. You want four values:
| Field | Sandbox value |
|---|---|
| Consumer key | From the Daraja portal |
| Consumer secret | From the Daraja portal |
| Shortcode | 174379 (Safaricom's shared test paybill) |
| Passkey | From "Lipa na M-Pesa Online" in the portal |
Paste them into your application's Sandbox environment in paylod, then mint an mp_test_… key.
What sandbox actually does
Sandbox is Safaricom's own environment, not a paylod mock. The STK Push is real: it goes to Daraja, Daraja answers, and the callback comes back to paylod's hosted receiver exactly as it would in production. What is not real is the money — nothing settles.
That means the shape of everything you build — the 202, the paymentId, the webhook envelope, the signature, the result codes — is identical in production. There is no second integration to write.
Send a test payment
Set PAYLOD_API_KEY to the mp_test_… key. Nothing else changes.
import { Paylod } from "@paylod/node";
const paylod = new Paylod(process.env.PAYLOD_API_KEY!); // mp_test_… key
const outcome = await paylod.collectAndWait({
amount: 10,
phone: "254708374149", // Safaricom's published test MSISDN
accountReference: "TEST-1",
});
console.log(outcome.paid ? outcome.receipt : outcome.message);Use a real number you control and you will get a real prompt, with no real money attached.
Exercise the failure paths
Most production incidents are failure paths nobody tried. Before you go live, make sure your code does something sensible for each of these:
| Result code | How to trigger it in sandbox | What your code should do |
|---|---|---|
1032 | Press Cancel on the prompt | Show a friendly retry, do not fulfil |
1037 | Ignore the prompt until it expires | Retry, or fall back to polling |
2001 | Enter the wrong M-Pesa PIN | Ask them to try again |
1 | Push an amount above the test balance | Tell the customer the balance is low |
Every code, with its cause and fix, is in the error reference.
Test your webhook locally
No tunnel needed. The CLI streams your live webhook events to localhost with the signature intact:
npx @paylod/cli listen --forward http://localhost:3000/webhookYour handler verifies a real signature against a real payload, on your laptop. See Handle the result.
Next
Go live — swap the credentials, swap the key, keep the code.