---
title: "Ask a payer to send you KES over M-PESA"
method: POST
path: "/v1/funding/mpesa-push"
tags: ["Partner API"]
---

# Ask a payer to send you KES over M-PESA

`POST /v1/funding/mpesa-push`

## Request

- Base URL: `https://sandbox.onlink.africa`
- URL: `https://sandbox.onlink.africa/v1/funding/mpesa-push`
- Auth: API key in header `X-OnLink-Key`

Sends an STK Push prompt to the number you name. The payer approves it on their own handset with their PIN — there is no OTP for you to handle and no way for you to complete it on their behalf. The deposit lands in your own KES account, which is resolved from your verified business and is not something you can specify. This returns as soon as the prompt is out, so treat the response as pending: the completion signal is the credit.received webhook, and a prompt the payer declines or ignores produces no event at all. There is no idempotency key. A repeated call is a second prompt, and if the payer approves both then both deposits land and each raises its own credit.received.

## Request body

- MpesaPushRequestDto
  - `phone` string, required: The payer mobile number to prompt, in any recognised Kenyan format — +254712345678, 254712345678, 0712345678 or 0112345678. Normalised server-side to the form the bank requires, so you can send the number as you hold it.
  - `amount` string, required: Amount in WHOLE KES, as a decimal string, at most 150,000 — the M-PESA per-transaction limit. M-PESA does not process decimals on an inbound customer-to-business push, so "100.50" is refused rather than rounded, and a leading zero is refused rather than normalised.

## Response `202`

The prompt was sent. Nothing has moved yet.

- MpesaPushResponseDto
  - `pushId` string, required: An opaque handle for this push. Quote it to support if a prompt never arrived or a deposit never landed. There is no route that reads it, and it is NOT the transactionId on the credit.received event — that id belongs to a record created later, when the money actually clears.
  - `status` 'pending', required: Always pending. The payer has been prompted on their handset and nothing has moved. The completion signal is the credit.received webhook; a prompt the payer declines or ignores produces no event at all.

## Other responses

- `400`: The phone is not a recognised Kenyan mobile number, or the amount is not a whole number of KES greater than zero.
- `401`: Signature missing or invalid
- `403`: Your credential was not granted funding:write.
- `404`: PARTNER_NOT_FOUND.
- `422`: MPESA_PUSH_REJECTED — the bank answered and refused this request, most often because the number is not M-PESA-registered. Do NOT retry: the same request cannot succeed. Fix the number, or ask the payer to check their line.
- `429`: Rate limited. This route allows 10 requests per minute per partner — lower than the rest of the API, because every request raises a real prompt on a real phone. Read the Retry-After-partner header.
- `503`: MPESA_PUSH_UNAVAILABLE — we did not get an answer from the bank, so the prompt MAY OR MAY NOT have reached the payer. There is no idempotency key on this route, so a retry can raise a second prompt: prefer waiting for credit.received, and retry only if no credit arrives. Or one of the account refusals: PARTNER_VA_NOT_ALLOCATED (you have no KES account yet), PARTNER_VA_ACTIVATING (it is being opened), PARTNER_VA_SUSPENDED (it is not currently usable — talk to us).

---

[API](https://skmtc.dev/onlink/apis/onlink-partner-api.md) - [All operations](https://skmtc.dev/onlink/apis/onlink-partner-api/llms.txt) - [OpenAPI document](https://skmtc.dev/onlink/apis/onlink-partner-api/revisions/1d1c6a3671f2?raw)
