Initiates an M-Pesa STK Push: the customer’s phone shows a payment prompt, and once they act on it the transaction settles into a terminal state. Send an Idempotency-Key header so retries can never double-prompt (see Idempotency).

Request parameters

integer
required
Amount to collect, in whole KES (integer shillings). 150 = KES 150. Must be ≥ 1 — M-Pesa moves whole shillings only, so no decimals.
string
required
Customer’s Kenyan mobile number. Accepted formats: 0712345678, 0112345678, 254712345678, +254712345678 (and the 01/2541 equivalents).
string
required
Your reference for this payment, max 12 characters. Shown to you on the transaction — use your invoice or order number.
integer
required
Which of your approved payment channels to collect on — required on every request, so multi-channel merchants name the destination explicitly instead of relying on a default. Find your channel IDs on the Channels page (the Channel ID column). A channel that does not exist or is not approved for you fails with 503 CHANNEL_NOT_APPROVED.

Response

201 Created
string
Unique ID of this transaction — use it to retrieve status.
string
Always pending at creation. Follows the lifecycle.
integer
Platform fee for this transaction in whole KES, quoted and reserved from your prepaid wallet at initiation.
string
The payment provider’s transaction reference.
After 201, the transaction is processed in the background: the customer acts on the phone prompt, we confirm the result with the provider, and the status moves to a terminal state (usually within two minutes). Subscribe to webhooks or poll GET /transactions/.

Idempotency

STK initiation is not safe to retry blindly — a retry after a dropped connection can send a second payment prompt to your customer. To make retries safe, send an optional Idempotency-Key header:
  • 8–128 characters, from A–Z a–z 0-9 . _ : - (e.g. order-2041-attempt-1).
  • Scoped to your account — the same key on another merchant’s key is a different request.
  • The first request with a key creates the payment. Any later request with the same key returns that same transaction (HTTP 201, response header Idempotency-Replayed: true) instead of a new one — no second STK prompt, no second fee hold.
  • Keys are stored for the life of the transaction and never expire; use a new key whenever you deliberately want a fresh payment.
  • Omitting the header keeps the old behavior: every request starts a new payment.
cURL

Errors

Do not blindly retry a timed-out STK request. If the connection drops after we accepted it, a retry would create a second payment prompt. Always send an Idempotency-Key header so a retry returns the original transaction instead of starting a new one. Without a header, first list your recent transactions for the same account_reference and only re-send if none exists.