Skip to content

Take a payment by mobile money push

POST
/transactions/stk
curl --request POST \
--url https://cybqa.pesapal.com/pesapalv3/api/transactions/stk \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{ "id": "example", "currency": "KES", "amount": 1, "description": "example", "callback_url": "example", "cancellation_url": "example", "notification_id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0", "billing_address": { "email_address": "example", "phone_number": "example", "first_name": "example", "middle_name": "example", "last_name": "example", "country_code": "example", "line_1": "example", "line_2": "example", "city": "example", "state": "example", "postal_code": "example", "zip_code": "example" }, "branch": "example", "redirect_mode": "TOP_WINDOW", "account_number": "example", "subscription_details": { "start_date": "01-01-2027", "end_date": "01-01-2028", "frequency": "DAILY" }, "msisdn": "example", "payment_method": "MpesaKE" }'

Sends an M-Pesa or Airtel Money PIN prompt directly to a phone number, with no hosted payment page and no redirect. This is the endpoint for in-app payment flows.

The request is an ordinary order body plus msisdn and payment_method. The response carries no redirect_url, and instead returns the business_number and account_number the customer can pay manually if the prompt does not arrive. Both are worth showing them.

Note that merchant_reference in the response does not echo the id that was sent, and msisdn is not validated for shape.

Unlike every other operation, a missing required field here returns HTTP 400 with an ASP.NET model-state object rather than the usual error envelope. An invalid payment_method value still returns HTTP 200 with the ordinary error shape.

Media typeapplication/json
object
id
required

Your own reference, which must be unique. Values between 51 and 150 characters fail with a generic decline that does not mention length.

string
<= 50 characters
currency
required

Validated against a lookup table. Acceptance at submission does not guarantee a customer can complete a payment in that currency.

string
<= 3 characters
Allowed values: KES UGX TZS RWF ZMW MWK ZWL BWP ZAR NGN GHS ETB EGP MAD XAF XOF BIF SOS CDF AOA MZN NAD LSL SZL USD GBP EUR JPY CHF CAD AUD CNY INR AED SAR
amount
required
One of:
number
description
required

Shown to the customer. No maximum length was enforced.

string
callback_url
required

Plain HTTP is accepted.

string
cancellation_url
string
notification_id
required

An ipn_id from registerIpn.

string format: uuid
billing_address
required

The object is mandatory on an order, but every field within it is optional. An empty object is accepted.

object
email_address
string
<= 60 characters
phone_number
string
first_name
string
<= 50 characters
middle_name
string
<= 50 characters
last_name
string
<= 50 characters
country_code

ISO 3166-1 alpha-2, for example KE.

string
<= 3 characters
line_1
string
line_2
string
city
string
state
string
postal_code
string
zip_code
string
branch
string
<= 30 characters
redirect_mode
string
Allowed values: TOP_WINDOW PARENT_WINDOW
account_number

Your identifier for a subscriber. Send with subscription_details.

string
<= 50 characters
subscription_details
object
start_date
required

Format dd-MM-yyyy. ISO 8601 is rejected. Must be in the future.

string
end_date
required

Format dd-MM-yyyy. The range is not validated, so an end date before the start date is accepted.

string
frequency
required

Case insensitive.

string
Allowed values: DAILY WEEKLY MONTHLY QUARTERLY YEARLY
msisdn
required

The phone number to prompt. Not validated for shape, so an unroutable number is accepted and an order is still created.

string
payment_method
required

Other values, including MpesaTZ, MtnUG, TigoTZ and VodacomTZ, are rejected with Invalid Payment method provided.

string
Allowed values: MpesaKE AirtelKE AirtelUG

Returned for a successful push and for an invalid field value.

Media typeapplication/json
One of:
object
business_number
required

The paybill or shortcode the customer can pay manually if the prompt does not arrive. 220222 for M-Pesa Kenya, AIRTELKE and AIRTELUG for Airtel.

string
account_number

The account reference to quote alongside business_number.

string
payment_message
string
order_tracking_id
string format: uuid
merchant_reference

A generated value that does not echo the id you sent. The order is stored under your id regardless: looking the transaction up afterwards returns it, and the IPN carries it. Ignore this field and key your records on order_tracking_id.

string
redirect_url

Always null. There is no hosted page in this flow.

null
error
null
status
string
Example
{
"error": {
"error_type": "api_error"
}
}

A required field was missing.

Media typeapplication/json

ASP.NET model validation, returned with HTTP 400 by directMobileMoneyStk when a required field is absent. No other operation returns this shape.

object
message
string
modelState
required
object
key
additional properties
Array<string>
Example
{
"message": "The request is invalid.",
"modelState": {
"minifiedMobileCheckoutDTO.Msisdn": [
"Phone Number is required"
]
}
}