Sandbox setup
Create a Daraja app, find the test credentials, smoke test each API, and prepare to go live.
The sandbox is Safaricom's test environment. Requests behave like the real thing, but no money moves. Set it up once and every tutorial and example on this site works against it.
1. Create the app
- Sign in at developer.safaricom.co.ke.
- Open My Apps → Create new app and select every product you need: M-Pesa Express, C2B, B2C, B2B, Transaction Status, Account Balance, Reversal, Dynamic QR, M-Pesa Ratiba, Bill Manager, Tax Remittance and so on.
- Copy the Consumer Key and Consumer Secret.
Calling an API whose product is not selected on the app fails, even with a valid token.
2. Find the test credentials
These live on the portal's Test Credentials and simulator pages. Read them from the portal each time: they change now and then.
| Item | Where, or typical value |
|---|---|
| M-Pesa Express shortcode | 174379 |
| M-Pesa Express passkey | Simulator page (a public test passkey) |
| C2B, B2C and B2B shortcodes | Test Credentials page (600xxx) |
| Test phone number | 254708374149, or your own Safaricom line to receive a real STK prompt |
| Initiator name and password | Test Credentials page |
| SecurityCredential | Generated from the initiator password and the sandbox certificate |
3. Save them
The easiest path is the wizard, which checks the keys live and stores them privately:
uvx mpesa-daraja-mcp initIf you are writing your own integration, put the same values in a .env file:
DARAJA_ENV=sandbox
DARAJA_CONSUMER_KEY=
DARAJA_CONSUMER_SECRET=
DARAJA_SHORTCODE=174379
DARAJA_PASSKEY=
DARAJA_INITIATOR_NAME=
DARAJA_SECURITY_CREDENTIAL=
DARAJA_CALLBACK_BASE_URL=https://<tunnel-host>Add .env to .gitignore, and commit a .env.example with no values.
4. Smoke test each API, in order
- [ ] Token: credentials check returns OK
- [ ] Tunnel: ngrok http 5000; curl -X POST https://<tunnel>/health → 200 from outside
- [ ] STK: push KES 1 to your phone; approve; callback ResultCode 0
- [ ] STK failures: cancel (1032), ignore (1037), wrong PIN (2001) → all recorded as FAILED
- [ ] C2B: register URLs → simulate → confirmation received
- [ ] B2C/B2B: payout with sandbox initiator → Result on ResultURL
- [ ] Status/Balance: results arrive and parseIf a step fails, fix it and rerun the same step before moving on. With the MCP server, mpesa_check_credentials followed by mpesa_stk_push is an end-to-end sandbox test without writing any code.
5. Go-live checklist
- [ ] Business has a real Paybill/Till, KYC complete, and an M-Pesa org-portal admin
- [ ] Production API operator (initiator) created with the roles each API needs
- [ ] Daraja portal → Go Live: verify shortcode by OTP, choose products, accept terms
- [ ] Production Consumer Key/Secret + production passkey (emailed for M-Pesa Express)
- [ ] SecurityCredential regenerated with the PRODUCTION certificate
- [ ] Separate secrets per environment, in a secret manager
- [ ] Callback URLs on your own domain with valid TLS (no tunnels); C2B URLs registered once on the prod shortcode
- [ ] Products needing extra approval requested by email (e.g. C2B external validation, Ratiba, Bill Manager, Pull)
- [ ] Live test with small amounts; reconcile against the org-portal statement
- [ ] Monitoring: PENDING age, ResultCode distribution, utility balance alerts