Reversals
Reverse a recent C2B transaction on the business account.
Endpoint
POST https://sandbox.safaricom.co.ke/mpesa/reversal/v1/requestOverview
Reverses a Customer to Business (C2B) transaction: M-PESA refunds the customer, sends an SMS notification, and returns the result to the organization via Daraja.
Use cases
- An erroneous payment to your Pay Bill or Till.
- A duplicate payment.
- A payment for a service that was never fulfilled.
Prerequisites
- Daraja account and sandbox app.
- For production: a live Pay Bill/Till with Business Admin/Manager operators created.
Request
{
"Initiator": "apiop37",
"SecurityCredential": "jUb+dOXJiBDui8FnruaFckZJQup3kmmCH5XJ4NY/Oo3KaUTmJbxUiVgzBjqdL533u5Q435MT2VJwr/ /1fuZvA===",
"CommandID": "TransactionReversal",
"TransactionID": "PDU91HIVIT",
"Amount": "200",
"ReceiverParty": "603021",
"RecieverIdentifierType": "11",
"ResultURL": "https://mydomain.com/reversal/result",
"QueueTimeOutURL": "https://mydomain.com/reversal/queue",
"Remarks": "Payment reversal"
}| Field | Description | Sample value |
|---|---|---|
Initiator | API operator username. | johndoe |
SecurityCredential | Encrypted initiator password. | (encrypted string) |
CommandID | Only TransactionReversal is accepted. | TransactionReversal |
TransactionID | The M-PESA receipt number of the transaction to reverse. | PDU91HIVIT |
Amount | Amount to reverse. | 100 |
ReceiverParty | Your organization short code. | 600997 |
RecieverIdentifierType (sic) | Documented as always 11. | 11 |
Remarks | 2 to 100 characters. | Free text |
QueueTimeOutURL / ResultURL | Timeout and result callback URLs. | https://domain:port/path |
RecieverIdentifierType is spelled that way, "Reciever," in Safaricom's own
documentation, kept as-is since it's the literal field name expected in the
request.
Response
{
"OriginatorConversationID": "f1e2-4b95-a71d-b30d3cdbb7a7735297",
"ConversationID": "AG_20210706_20106e9209f64bebd05b",
"ResponseCode": "0",
"ResponseDescription": "Accept the service request successfully."
}This is only an acknowledgment; the actual outcome arrives at ResultURL.
Callback
Reversals use standard M-PESA result codes for 2001, 2006, 2028, 8006,
11, and 1, the same as the B2C result
codes, plus two reversal-specific codes.
{
"Result": {
"ResultType": 0,
"ResultCode": 0,
"ResultDesc": "The service request is processed successfully.",
"OriginatorConversationID": "dad6-4c34-8787-c8cb963a496d1268232",
"ConversationID": "AG_20211114_201018edbbf9f1582eaa",
"TransactionID": "SKE52PAWR9",
"ResultParameters": {
"ResultParameter": [
{
"Key": "DebitAccountBalance",
"Value": "Utility Account|KES|7722179.62|7722179.62|0.00|0.00"
},
{ "Key": "Amount", "Value": 1.0 },
{ "Key": "TransCompletedTime", "Value": 20211114132711 },
{ "Key": "OriginalTransactionID", "Value": "SKC82PACB8" },
{ "Key": "Charge", "Value": 0.0 },
{
"Key": "CreditPartyPublicName",
"Value": "254705912645 - NICHOLAS JOHN SONGOK"
},
{
"Key": "DebitPartyPublicName",
"Value": "600992 - Safaricom Daraja 992"
}
]
},
"ReferenceData": {
"ReferenceItem": {
"Key": "QueueTimeoutURL",
"Value": "https://internalsandbox.safaricom.co.ke/mpesa/reversalresults/v1/submit"
}
}
}
}| Field | Description |
|---|---|
DebitAccountBalance | Post-reversal balance on the debited account. |
Amount / Charge | Amount reversed and fee, if any. |
TransCompletedTime | YYYYMMDDhhmmss. |
OriginalTransactionID | The receipt number of the transaction that was reversed. |
CreditPartyPublicName / DebitPartyPublicName | Names of the parties involved. |
Result codes
| Code | Meaning | Explanation |
|---|---|---|
| 0 | Success | Reversal processed. |
R000002 | Original transaction ID invalid | TransactionID doesn't exist on M-PESA. |
R000001 | Already reversed | This transaction was already reversed once. |
| 11 | DebitParty invalid state | Account isn't active. |
| 21 | Initiator not allowed | Missing Org Reversals Initiator role. |
| 2001 | Initiator information invalid | Wrong credentials or encryption. |
| 2006 | Account rule declined | Account isn't active. |
| 2028 | Not permitted by product assignment | Short code lacks permission. |
| 8006 | Security credential locked | Business Administrator must unlock. |
| 1 | Insufficient balance | Short code lacks funds to complete the reversal. |
Error codes
| Code | Cause | Fix |
|---|---|---|
404.001.03 | Invalid access token | Regenerate before expiry. |
400.002.02 | Bad request, invalid field | Match the documented payload. |
404.001.01 | Resource not found | Check the endpoint. |
Testing and Go Live
Daraja Simulator with the Reversals product attached, or Postman against the sandbox endpoint above.
Going live requires the Org Reversals Initiator role on your API user; see Organization Portal & Go Live.
FAQs
No. Safaricom documents B2C reversals as a manual process on the M-PESA portal.
Wrong Content-Type header, an incorrect parameter name, or a missing/invalid value. The parameter name itself, misspelling included, is what the API expects.
Create a Business Manager, then create an API operator with the Org Reversals Initiator role, then set that operator's password via a Business Manager holding the Set Restricted ORG API Password role. See Organization Portal & Go Live for the full walkthrough.