On receiving a transaction, Sapama Cash will instantly send you the notification to the "Instant Payment Notification (IPN)" settings set under the till.
{"property_ids":[728,729,735]}
If you are using PHP, you can capture the fields like this or download this sample PHP
if( isset( $_POST['trans_type'] ) && strlen( $_POST['trans_type'] )){ $trans_type = $_POST['trans_type']; } if( isset( $_POST['trans_amount'] ) && strlen( $_POST['trans_amount'] )){ $trans_amount = $_POST['trans_amount']; }
Implement your code to listen to the notification
We'll post the following. Depending if you've configured your calleback as HTTP GET or POST, kindly ensure you use $_GET or $_POST to capture the values and not JSON
{ "organization_id": 2,//Organization ID on Sapama Cash system "customer_id": 50,//Customer ID on Sapama Cash system "location_id": 2,//Till ID on Sapama Cash system "trans_type": "Customer Merchant Payment",//From the gateway eg MPESA "trans_id": "OQWEREDS",//Gateway transction ID eg MPESA code "trans_time": "20200709220327",//Transaction time in this format - YmdHis "date": "2020-07-09",//Date of the transaction in this format Y-m-d "trans_amount": 350,//Transaction amount "short_code": "830830",//Short code "bill_ref_number": "Sapama - 305694",//Account number "description": "",//Description "org_account_balance": "65600.17",//Organization balance "phone": "254722906835",//Phone number "first_name": "JOHN", "middle_name": "OMONDI", "last_name": "KAMAU", "status": "received",//Status - Received means that the money has been received "reference_number": "",//In case of Checkout - The unique identifier of the transaction on your system "type": "receipt",//Can be receipt or invoice "proxy_trans_id": 305695,//Transaction ID on on Sapama Cash system "proxy_trans_uuid": "trans_5f0de4e0d2ebc", //Transaction ID on on Sapama Cash system "invoice_id": 305694,//In case of Checkout, this is the transaction ID of the invoice when the checkout was initiated. You can use this to cross reference as well. "invoice_uuid": "trans_5f0de4a7740b8",//Same as invoice_id "api_key": "",//API Key "hash": "a760c88594bedf7702271c378d641c0da6512980ce513bebf557c7ede6aaf596", "third_party_message"=>"Success",//Message from the gateway message }
{ "type": "success", "message": "Transaction reconciled successfully" }The "type" index can have the following values:
no : 'Not yet ipned. This is the default status', success:'Successfully recorded in your system', error:'A System error occurred when trying to reconcile', unreconciled:'An error occurred when trying to reconcile eg that transaction is in SapamaCash.com but not in your system',
To send or simulate a transaction, you don't have to make an actual MPESA or Equitel transaction every time, if there are no transaction, make one actual transaction, and UPDATE it as long as the ipned status IS NOT equal to "success" by click on this "Edit" icon . The system will send or push the transaction to your server. Kindly note that if the ipned status is "success", the IPN WILL NOT be sent
{"property_ids":[728,729,735]}
Implement your code to listen to the notification
We'll post the following
{ "type": "receipt", "trans_type": "Customer Merchant Payment", "trans_id": "I", "trans_time": "2020-07-09 22:03:27", "trans_amount": "350.00", "short_code": "830830", "org_account_balance": "65600.17", "phone": "254722906835", "bill_ref_number": "Acc#", - The Account number passed by the customer "first_name": "MICHAEL", "middle_name": "MUNGAI", "last_name": "MWENJA", "location_id": "2", "api_key": "", "hash": "96f831f457d3ff962a04b4fa8138d054550432e6abaade10102eda8eb5aed87d", "ip": "41.80.116.239", "agent": "Guzzle\/4.2.4 curl\/7.58.0 PHP\/5.6.40-29+ubuntu18.04.1+deb.sury.org+1" }
If you are using PHP, you can capture the fields like this or download this sample PHP
if( isset( $_POST['trans_type'] ) && strlen( $_POST['trans_type'] )){ $trans_type = $_POST['trans_type']; } if( isset( $_POST['trans_amount'] ) && strlen( $_POST['trans_amount'] )){ $trans_amount = $_POST['trans_amount']; }
Depending on the validation/check, you return the following json Success / Valid / Accept payment
{ "type": "success", "message": "Validation successful" }Reject payment or don't accept payment
{ "type": "error", "message": "Validation failed" }
On receiving a transaction, Sapama Cash can send a customised SMS to your customer.
:name - Customer name :currency - 'KES', :amount - Transaction amount :points - Points if running a loyalty scheme, :transid - MPESA or Equitel transaction code :proxytransid - Sapama Cash transaction id, :billrefnumber - MPESA or Equitel account number, :date - transaction date in d/m/Y fromat , :location' - Name of the till
Get a single or a list of transactions
This API will return a list of transactions. You can also filter by phone number or MPESA transaction code or status.
This API is useful if you have an off-line system eg a POS or ERP and need to get a list of all the transactions.
If you are getting the list of un-reconciled transaction, to avoid getting the same transactions again every time you you make a call to the "Get Transactions" API, you'll update the transaction that has been assigned to a sale using the "Update Transactions" API (below). This API will update the transaction status and indicate that it has been reconciled, this way it will not appear in the next request.
# | Field | Data type | Note | Required / Optional |
---|---|---|---|---|
1 | format | string | Must be 'json' | 1 |
2 | api_key | string | API key | 1 |
3 | hash | string | Hash | 1 |
4 | trans_id | string | MPESA confirmation Code | 0 |
5 | id | int | Integer Transation ID or Invoice ID eg 121323 | 0 |
6 | uuid | int | Unique Transation ID or Invoice ID eg trans_SFSDF12S | 0 |
7 | phone | integer | Customer phone number with 254 and without + eg 25472200000 | 0 |
7 | ipned | string | By default the API will return all un-reconciled transactions. This parameter is optional and if not included the API will return on UN-reconciled transactions (ie with ipned status received). If you are getting a single transaction irrespective of the status set ipned to any | 0 |
8 | page | integer | The page of the pagination to return eg page 1, 2 | 0 |
7 | per_page | integer | Number of transactions to be returned to return in a given page eg return 20 transactions (Defaults to 50)
|
0 |
If you check the transaction object, there is an optional transaction object. This is the corresponding invoice or receipt of the initial transaction.
For instance, when you make an STK push checkout request using the "Checkout" API, we'll create an invoice and save in the database. When the customer complete the payment, we'll create a receipt for the invoice created before. So if you check the invoice, it will have a transaction object of the receipt.
Likewise, if you get the receipt, there will be a corresponding transaction object of the invoice.
Action | Http status code | Note | Example |
---|---|---|---|
Success | 200 | List of transactions. Check the "data" parameter it will have an array of the transactions.
If you check the transaction object, there is an optional transaction object. This is the corresponding invoice or receipt of the initial transaction. For instance, when you make an STK push checkout request using the "Checkout" API, we'll create an invoice and save in the database. When the customer complete the payment, we'll create a receipt for the invoice created before. So if you check the invoice, it will have a transaction object of the receipt. Likewise, if you get the receipt, there will be a corresponding transaction object of the invoice. |
{ "httpStatusCode": 200, "systemCode": 700, "message": "Transactions list", "data": { "total": 1, "per_page": 2, "current_page": 1, "last_page": 1, "from": 1, "to": 1, "data": [{ "id": "380222", "uuid": "trans_5f1077b2e5e68", "organization_id": "255", "customer_id": "173846", "location_id": "266", "category_id": "0", "trans_type": "c2b", "trans_id": "OGG9SXHEST", "trans_time": "2020-07-16 15:52:18", "date": " 16\/07\/20 03:52 PM", "trans_amount": "1.00", "description": "API Integrations", "short_code": "", "bill_ref_number": "API Integrations", "invoice_number": "", "org_account_balance": "32.00", "third_party_trans_id": "22027-17924288-1", "phone": "254722906835", "name": "Edwin Mugendi Riungu", "first_name": "Edwin", "middle_name": "Mugendi", "last_name": "Riungu", "ipned": "received", "smsed": "", "emailed": "", "ipned_at": "0000-00-00 00:00:00", "smsed_at": "0000-00-00 00:00:00", "emailed_at": "0000-00-00 00:00:00", "customer_notified_at": "0000-00-00 00:00:00", "customer_notified": "", "message": "", "smsed_to": "", "emailed_to": "", "workflow": "0", "agent": "", "ip": "159.89.239.200", "status": "1", "created_by": "173186", "updated_by": "173186", "created_at": "2020-07-16 15:52:20", "updated_at": "2020-07-16 15:53:02", "third_party_message": "", "payload_response": "", "payload_count": "0", "gateway": "", "callback_url": "http:\/\/make_callback_to_this_link.com\/script\/callback\/mpesa_collection", "callback_http_method": "post", "b2c_in_status_code": "", "b2c_out_status_code": "", "b2c_reference_code": "ws_CO_160720201854241584", "b2c_account_balance_utility": "0", "b2c_account_balance_charges": "0", "mode": "", "direction": "c2b", "b2c_account_balance": "0", "reference_number": "REF2602", "type": "invoice", "currency": "KES", "environment": "live", "flow": "stkpush", "image_url": "image_url", "item_id": "0", "simulate": "", "b2c_request_payload": "", "b2c_response_payload": "", "address": "Address", "transaction_id": "380224", "date_original": "2020-07-16", "actions": "", "trans_amount_original": "1.00", "trans_time_unix": 1594914738, "transaction": { "id": "380224", "uuid": "trans_5f1077dba6139", "organization_id": "255", "customer_id": "173846", "location_id": "266", "category_id": "0", "trans_type": "Pay Bill", "trans_id": "OGG9SXHEST", "trans_time": "2020-07-16 18:55:37", "date": "2020-07-16", "trans_amount": "1.00", "description": "API Integrations", "short_code": "830830", "bill_ref_number": "API Integrations-380222", "invoice_number": "", "org_account_balance": "32.00", "third_party_trans_id": "", "phone": "254722906835", "name": "EDWIN MUGENDI RIUNGU", "first_name": "EDWIN", "middle_name": "MUGENDI", "last_name": "RIUNGU", "ipned": "received", "smsed": "", "emailed": "y", "ipned_at": "0000-00-00 00:00:00", "smsed_at": "0000-00-00 00:00:00", "emailed_at": "2020-07-16 15:53:04", "customer_notified_at": "0000-00-00 00:00:00", "customer_notified": "", "message": "", "smsed_to": "", "emailed_to": "edwin@sapamatech.com", "workflow": "1", "agent": "Agent", "ip": "127.0.0.1", "status": "1", "created_by": "1", "updated_by": "1", "created_at": "2020-07-16 15:53:02", "updated_at": "2020-07-16 15:53:04", "third_party_message": "", "payload_response": "", "payload_count": "0", "gateway": "mpesa", "callback_url": "", "callback_http_method": "", "b2c_in_status_code": "", "b2c_out_status_code": "", "b2c_reference_code": "", "b2c_account_balance_utility": "0", "b2c_account_balance_charges": "0", "mode": "live", "direction": "c2b", "b2c_account_balance": "0", "reference_number": "REF2602", "type": "receipt", "currency": "", "environment": "", "flow": "", "image_url": "", "item_id": "0", "simulate": "", "b2c_request_payload": "", "b2c_response_payload": "", "address": "", "transaction_id": "380222" } }], "controller": "transaction", "package": "payments", "imageable": 0, "action": "" } } |
Error | 400 | Validation error | { "http_status_code": 400, "system_code": 900, "message": "Input validation failed.", "data": [ { "field": "token", "error": "Invalid login token" } ] } |
Update transaction
This API is useful if you have an off-line system eg a POS or ERP and need to get a list of all the transactions.
If you are getting the list of un-reconciled transaction, to avoid getting the same transactions again every time you you make a call to the "Get Transactions" API, you'll update the transaction that has been assigned to a sale using the "Update Transactions" API (below). This API will update the transaction status and indicate that it has been reconciled, this way it will not appear in the next request.
# | Field | Data type | Note | Required / Optional |
---|---|---|---|---|
1 | format | string | Must be 'json' | 1 |
2 | api_key | string | API key | 1 |
3 | hash | string | Hash | 1 |
4 | id | integer | The transaction id (Not MPESA transaction id) | 1 |
5 | ipned | string | no : 'Not yet ipned. This is the default status', success:'Successfully recorded in your system', error:'A System error occurred when trying to reconcile', unreconciled:'An error occurred when trying to reconcile eg that transaction is in SapamaCash.com but not in your system', |
1 |
Action | Http status code | Note | Example |
---|---|---|---|
Success | 200 | Transaction updated | { "httpStatusCode": 200, "systemCode": 700, "message": "Transaction updated", "data": { "id": "1" } } |
Error | 400 | Validation error | {"httpStatusCode":400,"systemCode":900,"message":"Input validation failed.","data":[{"field":"api_key","error":"Invalid hash"}]} |
Get transactions
# | Field | Data type | Note | Required / Optional |
---|---|---|---|---|
1 | format | string | Must be 'json' | 1 |
2 | api_key | string | API key | 1 |
3 | hash | string | Hash | 1 |
4 | first_name | string | First name | 0 |
5 | middle_name | string | Middle name | 0 |
6 | last_name | string | Last name | 0 |
7 | trans_type | string | Transaction type | 0 |
8 | trans_id | string | Unique transaction reference number. Should be unique to avoid duplication | 1 |
9 | trans_time | string in this format Y:m:d H:i:s | 1 | |
10 | trans_amount | float | The amount | 1 |
11 | short_code | string | Used to identify the this till | |
12 | org_account_balance | float | The account balance | |
13 | phone | int | Phone number | |
14 | bill_ref_number | string | Same as account or customer number | 0 |
15 | invoice_number | string | Invoice number | 0 |
16 | description | string | Note | 1 |
17 | third_party_trans_id | string | Unique identifier on your system eg primary key on your system | 0 |
Action | Http status code | Note | Example |
---|---|---|---|
Success | 200 | Transaction updated | { "httpStatusCode": 200, "systemCode": 700, "message": "Succeed.", "data": [{ "third_party_trans_id": "third_party_trans_id", "trans_id": "trans_id", "sapama_id": 290047, "type": "success", "message": "Success" }] } |
Error | 400 | Validation error | {"httpStatusCode":400,"systemCode":900,"message":"Input validation failed.","data":[{"field":"api_key","error":"Invalid hash"}]} |
API to make Business to Customer transaction ie pay a customer directly from your account to their mobile money account
# | Field | Data type | Note | Required / Optional | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | format | string | Must be 'json' | 1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
2 | api_key | string | API key | 1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
3 | hash | string | Hash | 1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
4 | location_id | integer | The location id get this by logging in a going to Tills and using number in the first column or # | 1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
5 | mode | string | live : Production or live environment sandbox:Sandbox or test environment | 1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
6 | beneficiaries | array |
Parameters / indexes / keys in the beneficiary
|
1 |
Action | Http status code | Note | Example |
---|---|---|---|
Success | 200 | we turn an array in the "data" parameter. Loop through it and check for the "trans_id" that will be used to | { "httpStatusCode": 200, "systemCode": 700, "message": "2 transactions of 2 (100%) scheduled for B2C", "data": [ { "status": "success", "message": "Success", "proxy_trans_id": 305528, "trans_id": "trans_reference", "phone": "0722906830", "amount": "100" }, { "status": "success", "message": "Success", "proxy_trans_id": 305529, "trans_id": "trans_reference", "phone": "0722906832", "amount": "100" } ] } |
Error | 400 | Validation error | {"httpStatusCode":400,"systemCode":900,"message":"Input validation failed.","data":[{"field":"beneficiaries","error":"trans_reference at beneficiaries 0 should be set and it identifies this transaction on your system. Best if it's unique"}]} |
This API is used to intiate a checkout. A checkout is a request for payment that will allow the customer to complete the payment.
# | Field | Data type | Note | Required / Optional |
---|---|---|---|---|
1 | api_key | string | API key | 1 |
2 | first_name | string | John | 1 |
3 | middle_name | string | Mwangi | 1 |
4 | last_name | string | Otieno | 1 |
5 | string | info@company.com | 1 | |
6 | phone | string | 254722.... include country code | 1 |
7 | description | string | Item X | 1 |
8 | address | string | John Mwangi Otieno, P.O.Box 10231 Nakuru | 1 |
9 | amount | float | 1000 - without comma | 1 |
10 | currency | string | KES | 1 |
11 | reference_number | string | Number that uniquely identifies the transaction on your system. Eg the Order ID or primary key of your transactions table | 1 |
12 | bill_ref_number | string | The equivalent of the account number used to identify that customer. Eg customer number | 1 |
13 | location_id | integer | The location id get this by logging in a going to Tills and using number in the first column or # | 1 |
14 | format | string | json | 1 |
15 | flow | string |
Can be:
1. stkpush - This will intiate an STK push to the customers phone number 2. form - Coming soon 3. redirect - Coming soon 4. iframe - Coming soon
|
1 |
16 | environment | string | live | 1 |
17 | callback_url | string | url that the response will be sent to. | 1 |
18 | callback_http_method | string | Call back HTTP method ie can be get or post | 1 |
19 | image_url | string | URL to an image that could be displayed in the payment form | 1 |
Action | Http status code | Note | Example |
---|---|---|---|
Success | 200 | 1 smses of 1 (100%) scheduled for sending | { "httpStatusCode": 200, "systemCode": 700, "message": "Succeed.", "data": { "invoice_uuid": "trans_5f201281619c5", "invoice_id": 386578, "reference_number": "1595937591", "type": "success", "code": 200, "message": "STK push initiated, a response will be sent back to the callback URL" } } |
Error | 400 | Validation error | {"httpStatusCode":400,"systemCode":900,"message":"Input validation failed.","data":[{"field":"beneficiaries","error":"trans_reference at beneficiaries 0 should be set and it identifies this transaction on your system. Best if it's unique"}]} |
API to send SMS to an array of phone numbers. Messages can be different for each phone number
# | Field | Data type | Note | Required / Optional | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | format | string | Must be 'json' | 1 | |||||||||||||||
2 | api_key | string | API key | 1 | |||||||||||||||
3 | hash | string | Hash | 1 | |||||||||||||||
4 | location_id | integer | The location id get this by logging in a going to Tills and using number in the first column or # | 1 | |||||||||||||||
6 | to | array |
Parameters / indexes / keys in the beneficiary
|
1 |
Action | Http status code | Note | Example |
---|---|---|---|
Success | 200 | 1 of 1 (100%) scheduled for SMS | { "httpStatusCode": 200, "systemCode": 700, "message": "1 smses of 1 (100%) scheduled for sending", "data": [{ "status": "success", "message": "Success", "proxy_trans_id": 12376, "phone": "254722906835", "amount": "10" }] } |
Error | 400 | Validation error | {"httpStatusCode":400,"systemCode":900,"message":"Input validation failed.","data":[{"field":"beneficiaries","error":"trans_reference at beneficiaries 0 should be set and it identifies this transaction on your system. Best if it's unique"}]} |
This API initiates a transfer of funds from one paybill to another already on the system
# | Field | Data type | Note | Required / Optional |
---|---|---|---|---|
1 | format | string | Must be 'json' | 1 |
2 | api_key | string | API key | 1 |
3 | hash | string | Hash | 1 |
4 | location_from_id | integer | The location id get this by logging in a going to Tills and using number in the first column or # | 1 |
5 | location_from_id | integer | The till intiating the transfer. The location id get this by logging in a going to Tills and using number in the first column or # | 1 |
6 | amount | integer | Amount you are transfering | 1 |
7 | description | string | A description or note | 1 |
8 | type | string | This can be one of the Command ID's from M-Pesa can be
BusinessPayBill, MerchantToMerchantTransfer, MerchantTransferFromMerchantToWorking, MerchantServicesMMFAccountTransfer, AgencyFloatAdvance |
Action | Http status code | Note | Example |
---|---|---|---|
Success | 200 | Transfer intiated | { "httpStatusCode": 200, "systemCode": 700, "message": "Intiated", "data": { "description": "Testing", "location_from_id": "2", "location_to_id": "245", "workflow": "initiated", "id": 14 } } |
Error | 400 | Validation error | {"httpStatusCode":400,"systemCode":900,"message":"Input validation failed.","data":[{"field":"beneficiaries","error":"trans_reference at beneficiaries 0 should be set and it identifies this transaction on your system. Best if it's unique"}]} |