Skip to main content

Documentation Index

Fetch the complete documentation index at: https://developers.kulmipay.com/llms.txt

Use this file to discover all available pages before exploring further.

M-Pesa STK Push (also called Lipa Na M-Pesa Express) lets you initiate a payment from your server. When you call the API, Safaricom sends a prompt to your customer’s phone asking them to enter their M-Pesa PIN. Once they confirm, the payment is processed and you receive a webhook notification. No redirect or hosted checkout page is required.

How it works

1

Send the STK push request

Call POST /api/v1/payment/mpesa-stk-push/ with the customer’s phone number and the amount to collect.
2

Customer receives a prompt

Safaricom sends a push notification to the customer’s phone with your business name and the payment amount.
3

Customer enters their PIN

The customer opens the prompt and enters their M-Pesa PIN to authorise the payment.
4

Webhook fires

Kulmi Pay sends a collection_event webhook to your configured endpoint with the invoice’s final state (COMPLETE or FAILED). You can also poll the payment status endpoint to check the result.

Send an STK push

curl -X POST https://app.kulmipay.com/api/v1/payment/mpesa-stk-push/ \
  -H "Authorization: Bearer ISSecretKey_test_xxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "phone_number": "254712345678",
    "amount": "1000.00",
    "api_ref": "ORDER-001",
    "mobile_tarrif": "BUSINESS-PAYS"
  }'

Request fields

FieldTypeRequiredDescription
phone_numberstringYesKenyan phone number in international format, e.g. 254712345678.
amountdecimal string or numberYesAmount in KES. The backend rounds decimal values up to the nearest whole shilling before sending the STK push.
api_refstringNoYour internal reference for this payment, e.g. an order ID. Defaults to MPesa Express when omitted and is returned in the webhook payload.
wallet_idstringNoThe ID of a specific KES wallet to receive funds. Defaults to your primary settlement wallet.
mobile_tarrifstringNoWho pays the transaction fee. BUSINESS-PAYS (default) or CUSTOMER-PAYS.

Success response

{
  "id": "a3f7c819-4e2b-4d1a-9c3f-2b8e1d7a6f05",
  "invoice": {
    "invoice_id": "INV-XXXXXXXX",
    "state": "PENDING",
    "provider": "M-PESA",
    "currency": "KES",
    "value": "1000.00",
    "api_ref": "ORDER-001",
    "account": "254712345678",
    "created_at": "2024-01-15T10:30:00Z"
  },
  "customer": {
    "phone_number": "254712345678",
    "provider": "M-PESA"
  },
  "payment_link": null,
  "customer_comment": null,
  "refundable": false,
  "created_at": "2024-01-15T10:30:00Z",
  "updated_at": "2024-01-15T10:30:00Z"
}
The invoice.invoice_id field is the value you use to check payment status. Save it with your order record.

Sandbox URL

Use the sandbox host with the same path while testing:
https://sandbox.kulmipay.com/api/v1/payment/mpesa-stk-push/
After sending the request, poll POST /api/v1/payment/status/ with the invoice.invoice_id from the response to check whether the customer completed the payment. Alternatively, configure a webhook to receive automatic notifications.