Skip to content

M-Pesa STK Push Builder

Working Daraja code for Lipa na M-Pesa Online (STK push) in four languages, plus a Password generator and decoder for the most common Daraja error. Everything runs in your browser; your keys never leave this page.

Request

Step

Code

    Expected response
    Save for later
    Your .env file

    PHP output reads config('services.mpesa.consumer_key'), consumer_secret, shortcode, passkey and access_token. Map them in config/services.php.

    Daraja Password generator & decoder

    Getting 500.001.1001 or "Invalid initiator information"? Decode the Password you sent to see which part is wrong.

    Generate

    Password

    Decode

      How STK push works

      1. Get a token. GET /oauth/v1/generate?grant_type=client_credentials with HTTP Basic auth (Consumer Key and Secret). Tokens last about an hour; cache them.
      2. Send the STK push. POST /mpesa/stkpush/v1/processrequest. The customer sees an M-Pesa PIN prompt. A response with ResponseCode "0" only means the prompt was sent.
      3. Receive the callback. Safaricom posts Body.stkCallback to your CallBackURL. ResultCode 0 means paid, and only then does it include CallbackMetadata with the receipt number.
      4. Query when unsure. If no callback arrives in about 90 seconds, or you get 1037, POST /mpesa/stkpushquery/v1/query with the CheckoutRequestID.

      Sandbox: https://sandbox.safaricom.co.ke. Production: https://api.safaricom.co.ke.

      The Password, step by step

      1. Take the current time in Kenya and format it as YYYYMMDDHHmmss, e.g. 20261028074100.
      2. Join, with nothing in between: BusinessShortCode + Passkey + Timestamp.
      3. Base64-encode the result. That's the Password.
      4. Send the same Timestamp in the request body. Generating the time twice, once for the Password and once for the field, is a classic bug.

      Request fields

      FieldValue
      BusinessShortCodeYour PayBill, or for Buy Goods your store (head office) number.
      TransactionTypeCustomerPayBillOnline or CustomerBuyGoodsOnline.
      AmountWhole shillings. Decimals are rejected.
      PartyA, PhoneNumberThe customer's number as 2547XXXXXXXX or 2541XXXXXXXX.
      PartyBThe PayBill number, or the till number for Buy Goods.
      CallBackURLPublic HTTPS URL. Avoid "mpesa" or "safaricom" in it, which developers report gets callbacks dropped.
      AccountReferenceUp to 12 characters, shown on the customer's prompt.
      TransactionDescUp to 13 characters.

      Handling the callback

      • Reply with {"ResultCode": 0, "ResultDesc": "Accepted"} quickly, and do slow work afterwards.
      • CallbackMetadata is only present on success. Code that reads it unconditionally crashes on every failed payment.
      • Treat 1037 as "not known yet", not "failed": query before letting the customer pay again.
      • Callbacks can arrive twice. Update the order idempotently on CheckoutRequestID.

      Every ResultCode and Daraja error is explained in the M-Pesa error code reference.

      Frequently asked questions

      How is the M-Pesa Daraja STK push Password generated?

      Password is base64(BusinessShortCode + Passkey + Timestamp), with the three values joined with no separators. Timestamp is the current time in YYYYMMDDHHmmss format, and you must send exactly the same Timestamp in the request body. Generate a fresh one for every request.

      Why do I get 500.001.1001 on STK push?

      Most often the Password doesn't match: the Timestamp in the Password differs from the Timestamp field, the passkey has a stray space or belongs to another shortcode, or BusinessShortCode is wrong. Paste your Password into the decoder on this page to see exactly which part is off. On the STK query endpoint, 500.001.1001 can also mean the payment is still being processed.

      What is the difference between PayBill and Till (Buy Goods) STK push?

      PayBill uses TransactionType CustomerPayBillOnline, with PartyB set to the PayBill number. Till uses CustomerBuyGoodsOnline: BusinessShortCode is your store (head office) number and PartyB is the till number. Use the passkey Safaricom issued for the BusinessShortCode you send.

      What timezone should the Daraja Timestamp use?

      Use Kenyan time (Africa/Nairobi, UTC+3). Servers in other timezones are a common source of confusing failures. The generated code always formats the time in Africa/Nairobi.

      Where do I find the sandbox shortcode and passkey?

      In the Daraja portal, open your sandbox app's test credentials (simulator) page. The sandbox PayBill is normally 174379, with a matching test passkey shown there. Production passkeys are sent by Safaricom when your shortcode goes live.

      Related

      Checked October 2026 against published Daraja integration guides. Safaricom's own documentation is on the Daraja portal at developer.safaricom.co.ke.

      Need this built for you?

      I integrate MTN MoMo, M-Pesa and Airtel Money into Laravel / PHP, Python / Django, Node.js / Next.js apps: payments, callbacks, payouts and go-live, with tests.