Create STK Push Requests
Use the STK Push endpoint to create a pending local transaction.
Flow
This is the local Daraja Local version of the real STK Push workflow:
1. Your app -> Daraja Local
POST /mpesa/stkpush/v1/processrequest
Sends phone number, amount, account reference, and callback URL.
2. Daraja Local -> Your app
Immediately returns MerchantRequestID and CheckoutRequestID.
Your app should save CheckoutRequestID as a pending payment.
3. Daraja Local
Creates an in-memory PENDING transaction.
No real Safaricom API is called and no phone prompt is sent.
4. Developer or test -> Daraja Local
Manually approves, fails, or times out the transaction using the simulator.
5. Daraja Local -> Your callback URL
POSTs the final result to the original CallBackURL.
Your app should update its payment record from this callback.
The important integration rule is: treat the immediate STK Push response as an acknowledgement, not final payment confirmation.
Endpoint
POST /mpesa/stkpush/v1/processrequest
Example Request
Send a POST request to the /mpesa/stkpush/v1/processrequest endpoint.
Replace <ACCESS_TOKEN> with the token generated from the OAuth endpoint.
Replace <CALLBACK_URL_ENDPOINT> with your server callback url in development. The sandbox will call this url to simulate a call from Daraja servers.
Replace <GENERATED_BASE64_PASSWORD> with your generated Base64 encoded string Format: base64.encode(Shortcode+Passkey+Timestamp).
curl -X POST http://127.0.0.1:8080/mpesa/stkpush/v1/processrequest \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <ACCESS_TOKEN>" \
-d '{
"BusinessShortCode": 174379,
"Password": "<GENERATED_BASE64_PASSWORD>",
"Timestamp": "20260705120000",
"TransactionType": "CustomerPayBillOnline",
"Amount": 100,
"PartyA": 254712345678,
"PartyB": 174379,
"PhoneNumber": 254712345678,
"CallBackURL": "http://127.0.0.1:3000/mpesa/callback",
"AccountReference": "INV-001",
"TransactionDesc": "Test payment"
}'
Important to note
- How to generate the missing values:
- Timestamp: Use the current date/time (e.g., if now is July 5, 2026, 12:30:00, then 20260705123000).
- Password: Base64 encode the string: 174379 + YOUR_PASSKEY + 20260705123000. Example
Buffer.from("174379" + "your_passkey" + "20260705123000").toString("base64")
Safaricom validates the password construction. Daraja Local validates only that the field is present because it does not hold a production passkey.
Example Response
{
"MerchantRequestID": "1760000000000-abcd1234",
"CheckoutRequestID": "ws_CO_1760000000000_abcd1234ef56",
"ResponseCode": "0",
"ResponseDescription": "Success. Request accepted for processing",
"CustomerMessage": "Success. Request accepted for processing"
}
Save the CheckoutRequestID. You will use it to query, approve, fail, or timeout the transaction.
What Your App Should Do
After receiving the response:
1. Save CheckoutRequestID.
2. Mark the payment as PENDING.
3. Wait for the callback before marking the payment SUCCESS, FAILED, or TIMEOUT.
Do not mark the payment successful from the STK Push acknowledgement alone.
Validation
Daraja Local rejects:
- missing required fields
- invalid callback URLs
- non-positive amounts
- fractional amounts and non-numeric JSON values
- string values for shortcode, party, and phone-number fields
- malformed JSON
