Guides
Go live
Move from sandbox to production: production Daraja credentials, the callback URL you paste into the Daraja portal, and the go-live checklist.
What changes
Almost nothing. Your code is the same; three things move.
- Your application's Production environment gets your production Daraja credentials and your real shortcode.
- You paste the production callback URL into the Daraja portal.
- Your backend swaps
mp_test_…formp_live_….
The endpoints, the request bodies, the webhook envelope and the result codes are identical. That is the whole point of building against sandbox first.
1. Get production Daraja credentials
Production credentials are issued by Safaricom against your real till or paybill, on the Daraja portal under "Go Live". You will need:
- Your consumer key and secret for the production app.
- Your shortcode — the till or paybill number customers already pay.
- Your Lipa na M-Pesa Online passkey.
- For payouts, reversals, and the admin queries: an Initiator Name and Initiator Password (a.k.a. the security credential), issued separately.
Paste them into the application's Production environment. They are encrypted at rest and never read back.
2. Set the callback URL in the Daraja portal
paylod hosts the callback receiver, so what you paste into Daraja is the URL paylod shows you on the application's Endpoints & Webhooks tab.
This is the one step nobody can do for you — Safaricom has no API for registering a callback URL. Everything else in a paylod integration is automatable.
Treat the callback URL as a secret. It carries a per-application token.
3. Swap the key
Mint an mp_live_… key on the API Keys tab and put it in your server's secret store. Your code does not change at all:
PAYLOD_API_KEY=mp_live_YOUR_API_KEYThe key alone decides that this is production. There is no environment flag to forget.
Go-live checklist
- The API key lives on your server, never in a browser or mobile app.
- The
amountcomes from your own order record, never from the client. - Your webhook handler verifies the HMAC signature before parsing the body.
paylod.webhookHandler()does this for you. - You compare
data.amountagainst the order total before fulfilling. - One
Idempotency-Keyper logical order; retries reuse it. 429is handled with a backoff, not a crash.- Your failure paths (
1032,1037,2001) have been exercised at least once. - If you use payouts or admin queries, the Initiator Name and Password are set on the Production environment.
The reasoning behind each of these is in Secure integration.
Then watch it
Payments, webhook deliveries and their retries are all visible in the dashboard. If a delivery is failing, you will see the attempts and the response your endpoint returned.