This document covers all transaction-related API operations: requesting payments, sending money, checking statuses, reversals, and querying transaction history.
Initiates a payment request from the customer. For M-Pesa Express, this triggers an STK Push prompt on the customer's phone.
POST /api/pay/{payment_app}/requestPayment
Requires Bearer token.
| Parameter | Type | Description |
|---|---|---|
payment_app |
integer | Payment App ID |
{
"phone_number": "254712345678",
"amount": 100,
"reference": "INV-2026-001",
"description": "Payment for Order #001"
}
| Parameter | Type | Required | Description |
|---|---|---|---|
phone_number |
string | Yes | Customer's phone number (format: 2547XXXXXXXX) |
amount |
numeric | Yes | Amount to charge |
reference |
string | Yes | Account reference / order ID |
description |
string | No | Human-readable transaction description |
{
"data": {
"MerchantRequestID": "29115-34620561-1",
"CheckoutRequestID": "ws_CO_191220191020363925",
"ResponseCode": "0",
"ResponseDescription": "Success. Request accepted for processing",
"CustomerMessage": "Success. Request accepted for processing"
},
"status": "success",
"message": "Payment request initiated"
}
| Code | Description |
|---|---|
200 |
STK push sent successfully |
401 |
Unauthenticated |
403 |
You do not own this Payment App |
422 |
Validation error (missing or invalid fields) |
500 |
Provider returned an error |
Sends money from your business account to a customer's phone number or bank account.
POST /api/pay/{payment_app}/sendMoney
Requires Bearer token.
| Parameter | Type | Description |
|---|---|---|
payment_app |
integer | Payment App ID (must be B2C-capable, e.g., MpesaKeB2C or MpesaKeB2B) |
{
"phone_number": "254712345678",
"amount": 500,
"command_id": "BusinessPayment",
"remarks": "Salary payment",
"occasion": "January 2026"
}
| Parameter | Type | Required | Description |
|---|---|---|---|
phone_number |
string | Yes | Recipient phone number |
amount |
numeric | Yes | Amount to send |
command_id |
string | Yes | M-Pesa command: BusinessPayment, SalaryPayment, or PromotionPayment |
remarks |
string | No | Comments about the transaction |
occasion |
string | No | Occasion for the payment |
{
"data": {
"ConversationID": "AG_20191219_00004492b1b6f0af4f53",
"OriginatorConversationID": "16740-34861180-1",
"ResponseCode": "0",
"ResponseDescription": "Accept the service request successfully."
},
"status": "success",
"message": "Money sent successfully"
}
| Code | Description |
|---|---|
200 |
Send request accepted |
401 |
Unauthenticated |
403 |
You do not own this Payment App |
422 |
Validation error |
500 |
Provider error |
Sends airtime to a phone number via a supported provider.
POST /api/pay/{payment_app}/sendAirtime
Requires Bearer token.
{
"phone_number": "254712345678",
"amount": 50,
"currency": "KES"
}
| Parameter | Type | Required | Description |
|---|---|---|---|
phone_number |
string | Yes | Recipient phone number |
amount |
numeric | Yes | Airtime amount |
currency |
string | No | Currency code (defaults to KES) |
| Code | Description |
|---|---|
200 |
Airtime sent |
401 |
Unauthenticated |
422 |
Validation error |
500 |
Provider error |
Retrieve a single transaction by ID.
GET /api/pay/{payment_app}/transaction/{transactionId}
Requires Bearer token.
| Parameter | Type | Description |
|---|---|---|
payment_app |
integer | Payment App ID |
transactionId |
integer | Salami transaction ID |
{
"data": {
"id": 42,
"payer_account": "254712345678",
"payer_name": "JOHN DOE",
"payee_account": "174379",
"payee_name": "My Business",
"reference": "INV-2026-001",
"transaction_id": "QJI3R7GXWV",
"amount": "100.00",
"currency": "KES",
"transaction_time": "2026-03-15T14:30:00.000000Z",
"narration": "Payment for Order #001",
"status": "STATUS_COMPLETED",
"transaction_type": "PAYMENT_IN",
"transaction_sub_type": "CustomerPayBillOnline",
"payment_provider": "MpesaKeExpress",
"app_id": 1,
"created_at": "2026-03-15T14:30:00.000000Z",
"updated_at": "2026-03-15T14:30:05.000000Z"
}
}
| Code | Description |
|---|---|
200 |
Success |
401 |
Unauthenticated |
403 |
You do not own this Payment App |
404 |
Transaction not found |
Query all transactions for a payment app with pagination.
GET /api/pay/{payment_app}/queryTransactions
Requires Bearer token.
| Parameter | Type | Description |
|---|---|---|
payment_app |
integer | Payment App ID |
{
"data": {
"current_page": 1,
"data": [
{
"id": 42,
"payer_account": "254712345678",
"payer_name": "JOHN DOE",
"payee_account": "174379",
"payee_name": "My Business",
"reference": "INV-2026-001",
"transaction_id": "QJI3R7GXWV",
"amount": "100.00",
"currency": "KES",
"status": "STATUS_COMPLETED",
"transaction_type": "PAYMENT_IN",
"payment_provider": "MpesaKeExpress",
"created_at": "2026-03-15T14:30:00.000000Z"
}
],
"per_page": 15,
"total": 1
}
}
| Code | Description |
|---|---|
200 |
Success |
401 |
Unauthenticated |
403 |
You do not own this Payment App |
Fetches transaction records directly from the payment provider's servers.
GET /api/pay/{payment_app}/fetchTransactions
Requires Bearer token.
| Parameter | Type | Description |
|---|---|---|
payment_app |
integer | Payment App ID |
| Code | Description |
|---|---|
200 |
Transactions fetched |
401 |
Unauthenticated |
403 |
Forbidden |
500 |
Provider error |
Checks the status of a transaction at the payment provider.
GET /api/pay/{payment_app}/getTransactionStatus/{transaction}
Requires Bearer token.
| Parameter | Type | Description |
|---|---|---|
payment_app |
integer | Payment App ID |
transaction |
integer | Salami transaction ID |
{
"data": {
"ResponseCode": "0",
"ResponseDescription": "The service request has been accepted successfully",
"OriginatorConversationID": "16740-34861180-1",
"ConversationID": "AG_20191219_00004492b1b6f0af4f53",
"TransactionID": "QJI3R7GXWV",
"ResultCode": "0",
"ResultDesc": "The service request is processed successfully."
},
"status": "success"
}
| Code | Description |
|---|---|
200 |
Status retrieved |
401 |
Unauthenticated |
404 |
Transaction not found |
500 |
Provider error |
Checks the status of a previously initiated payment request (e.g., STK Push query).
GET /api/pay/{payment_app}/checkPaymentRequestStatus/{transaction}
Requires Bearer token.
| Parameter | Type | Description |
|---|---|---|
payment_app |
integer | Payment App ID |
transaction |
integer | Salami transaction ID |
{
"data": {
"ResponseCode": "0",
"ResponseDescription": "The service request has been accepted successfully",
"MerchantRequestID": "29115-34620561-1",
"CheckoutRequestID": "ws_CO_191220191020363925",
"ResultCode": "0",
"ResultDesc": "The service request is processed successfully."
},
"status": "success"
}
| Code | Description |
|---|---|
200 |
Status retrieved |
401 |
Unauthenticated |
404 |
Transaction not found |
Reverses a completed transaction at the provider.
POST /api/pay/{payment_app}/reverseTransaction/{transaction}
Requires Bearer token.
| Parameter | Type | Description |
|---|---|---|
payment_app |
integer | Payment App ID |
transaction |
integer | Salami transaction ID to reverse |
{
"data": {
"OriginatorConversationID": "16740-34861180-1",
"ConversationID": "AG_20191219_00004492b1b6f0af4f53",
"ResponseCode": "0",
"ResponseDescription": "Accept the service request successfully."
},
"status": "success"
}
| Code | Description |
|---|---|
200 |
Reversal initiated |
401 |
Unauthenticated |
403 |
Forbidden |
404 |
Transaction not found |
500 |
Provider error or reversal not supported |
Checks the account balance at the payment provider.
GET /api/pay/{payment_app}/checkBalance
Requires Bearer token.
| Parameter | Type | Description |
|---|---|---|
payment_app |
integer | Payment App ID |
{
"data": {
"OriginatorConversationID": "16740-34861180-1",
"ConversationID": "AG_20191219_00004492b1b6f0af4f53",
"ResponseCode": "0",
"ResponseDescription": "Accept the service request successfully."
},
"status": "success"
}
| Code | Description |
|---|---|
200 |
Balance retrieved |
401 |
Unauthenticated |
403 |
Forbidden |
500 |
Provider error or not supported |
Parses transaction details from an SMS message body and creates a transaction record.
POST /api/pay/{payment_app}/extractTransaction
Requires Bearer token.
{
"message": "QJI3R7GXWV Confirmed. Ksh100.00 received from JOHN DOE 0712345678 on 15/3/26 at 2:30 PM. New M-PESA balance is Ksh1,500.00."
}
| Parameter | Type | Required | Description |
|---|---|---|---|
message |
string | Yes | Raw SMS message text |
{
"data": {
"transaction_id": "QJI3R7GXWV",
"amount": 100.00,
"payer_name": "JOHN DOE",
"payer_account": "0712345678",
"transaction_time": "2026-03-15T14:30:00.000000Z",
"status": "STATUS_COMPLETED"
},
"status": "success"
}
| Code | Description |
|---|---|
200 |
Transaction extracted |
401 |
Unauthenticated |
422 |
Message could not be parsed |
Simulates a C2B transaction in sandbox mode for testing.
POST /api/pay/{payment_app}/simulateTransaction
Requires Bearer token.
{
"phone_number": "254708374149",
"amount": 100,
"reference": "TEST001"
}
| Code | Description |
|---|---|
200 |
Simulation successful |
401 |
Unauthenticated |
422 |
Validation error |
500 |
Simulation failed (check if app is in sandbox mode) |
Retrieves payment instructions (e.g., paybill number, account number) to display to the customer.
GET /api/pay/{payment_app}/getInstructions/{transaction}
Requires Bearer token.
| Parameter | Type | Description |
|---|---|---|
payment_app |
integer | Payment App ID |
transaction |
integer | Salami transaction ID |
Returns an HTML view with payment instructions formatted for the specific provider.
| Code | Description |
|---|---|
200 |
Instructions returned |
401 |
Unauthenticated |
404 |
Transaction not found |