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.
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 optionalIdempotency-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 headerIdempotency-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