/api/v1/payment/stk/push
Send an M-Pesa STK push
Sends a "Lipa na M-Pesa" prompt to the customer's phone. account may be a debit note number, a policy number, a risk note number or a premium-finance loan ref (IPF-…). A policy resolves to its oldest unpaid debit note. If the policy has a signed premium-finance loan waiting for its deposit, the prompt is for the deposit (purpose ipf_deposit) and paying it hands the loan to Flexysure Finance. An active (or in-arrears) loan ref is an instalment repayment to Flexysure Finance (purpose ipf_repayment): when the customer pays, the money is booked in Flexysure Finance's books against the loan (fees, then interest, then principal of the oldest unpaid instalment), never as a brokerage receipt, and the loan's repaid and arrears update. To clear a loan early, use POST /ipf/loans/{uuid}/early-settlement (purpose ipf_settlement). The amount may not exceed what is outstanding on that account. Daraja takes whole shillings, so cents are rounded up.
- Scope
pay- Authentication
- Bearer token
- Rate limit
- 60 requests per minute per token (per-client override)
- Idempotency
-
Required: send an
Idempotency-Key; a retry with the same key replays the first response.
Headers
| Header | Meaning |
|---|---|
| Authorization | Bearer <access_token> (scope pay) |
| Idempotency-Key | Required. A unique value (a UUID) per write. Replays within 24 hours return the stored response with Idempotent-Replayed: true; the same key with a different body is rejected (idempotency_key_reused). |
Body fields
| Field | Type | Required | Description |
|---|---|---|---|
| account | string | Yes |
Debit note number, policy number, risk note number or IPF loan ref.
Example: DN-000123 |
| amount | number | Yes |
Amount in shillings, at least 1 and at most the outstanding balance.
Example: 30175 |
| phone | string | Yes |
Safaricom number: 07XXXXXXXX or 2547XXXXXXXX (01… and 2541… also accepted).
Example: 0712345678 |
Example
curl -X POST 'https://flexysure.intrepidprojects.co.ke/api/v1/payment/stk/push' \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H 'Accept: application/json' \
-H 'Idempotency-Key: 3917f09c-c992-4f40-a44f-0fe777689102' \
-H 'Content-Type: application/json' \
-d '{
"account": "DN-000123",
"amount": 30175,
"phone": "0712345678"
}'
Request body (JSON)
{
"account": "DN-000123",
"amount": 30175,
"phone": "0712345678"
}
{
"merchant_request_id": "29115-34620561-1",
"checkout_request_id": "ws_CO_14102026101500123",
"stk_request_uuid": "9b2f0f5e-6d0b-4c1e-9d55-2b8f3c1a7e10",
"status": "pending",
"status_label": "Waiting for customer",
"purpose": "premium",
"account": "DN-000123",
"phone": "0712 345 678",
"amount": 30175,
"amount_minor": 3017500,
"result_code": null,
"result_desc": null,
"mpesa_receipt": null,
"receipt_number": null,
"debit_note": "DN-000123",
"ipf_loan_ref": null,
"created_at": "2026-10-14T10:15:00+03:00",
"updated_at": "2026-10-14T10:15:00+03:00",
"customer_message": "We sent an M-Pesa prompt to 0712 345 678. The customer enters their PIN to pay."
}
Responses
| Status | Meaning |
|---|---|
| 200 | Prompt sent: Insurance Cloud fields plus stk_request_uuid to poll |
| 404 | account_not_found: no debit note, policy, risk note or loan with that reference in your organisation |
| 422 | amount_exceeds_balance (with outstanding), nothing_outstanding, financed_by_lender, loan_not_payable (loan not running: pending, closed or cancelled), payment_refused or validation_failed. No money moved. |
Errors are problem documents; the common codes (401, 403 insufficient_scope, 422, 429) apply to every endpoint.