Limits and input formats
Validate amounts, phone numbers, and request limits before submission.
Amounts and fees
Send JSON integers in KES cents, without quotes or a decimal point. 10000 means KES 100.00. Payment amounts must be between 100 and 25000000 cents, inclusive, and divisible by 100. The merchant's approved per-payment maximum may be lower.
The daily limit applies to payout admission and includes the amount, service fee, and provider fee. It uses the East Africa Time calendar day, UTC+03:00. Accepted payouts consume the daily allowance; failure releases reserved funds but does not restore the admission counter. Collection requests are subject to the per-payment maximum and STK request limits, rather than this payout daily allowance.
A configured recipient allowlist applies to payouts. A recipient outside it returns 400 MERCHANT_INVALID_REQUEST. Ask your administrator to review policy changes; keys cannot override the merchant's limits or recipient restrictions.
Phone numbers
Both collections and payouts require Kenyan mobile numbers beginning with 7 or 1 after the country code. These examples normalize to 254712345678:
254712345678+2547123456780712345678712345678
Spaces are accepted. Hyphens, parentheses, extensions, letters, and non-Kenyan numbers are rejected. A valid number format does not prove the number is registered with M-Pesa or eligible to receive a prompt or payout.
JSON and text fields
Payment request bodies have a 64 KiB limit. Send one JSON object with Content-Type: application/json. Unknown properties, duplicate property names, and trailing JSON values are rejected. Send documented lowercase field names.
Currency is trimmed and uppercased; use KES. Methods are trimmed but case-sensitive: stk for collections and b2c for payouts. Payouts default to b2c if omitted.
References are optional and trimmed. They may contain up to 80 UTF-8 bytes, which can be fewer than 80 characters for non-ASCII text. References need not be unique and are not provider receipts or idempotency keys.
Collections optionally accept quoted_fee_minor and validate it against the 10% deposit fee. For payouts, see fee validation.
Request rate
| Limit | Current value | Shared scope |
|---|---|---|
| Merchant requests | 120 per minute | Merchant API keys and portal requests using the merchant limiter |
| New STK requests | 3 per minute | Normalized payer phone across all merchants |
An idempotent replay still consumes merchant request-rate capacity, but an existing request found before STK admission does not create another prompt. Concurrent requests can still encounter rate limits; use backoff.
HTTP 429 uses MERCHANT_LIMIT_EXCEEDED for both rate and business limits. The response includes Retry-After: 60. A lower amount, the next EAT calendar day, or an approved policy change may be needed for a business limit. Do not rotate keys or idempotency keys to bypass a limit.