Guides & Tutorials
Jenga API
Receive Money
M-Pesa STK Push
Wallet Based Settlement

M-Pesa STK/USSD Push initiate(Wallet Based Settlement)

This API allows merchants to initiate Mpesa STK/USSD pushes to Customers.

  • Contrary to Account-based API, the funds are credited to Jenga Wallet where one can settle to any bank account on-boarded on Jenga.
  • The funds are available for settlement on a real-time basis.

Test URL

POSThttps://uat.finserve.africa/api-checkout/mpesa-stk-push/v3.0/init

Live URL

POSThttps://api.finserve.africa/api-checkout/mpesa-stk-push/v3.0/init

Interface Definition

Interface IDmpesaStkPush
Version1.0
Interface TypeREST/JSON
ModeSynchronous
MethodPOST
Endpoint/api-checkout/mpesa-stk-push/v3.0/init
DescriptionInitiate Mpesa STK Push

Request Parameters

FieldDescriptionFormatRequired
order.orderReferenceOrder reference, should be unique per orderStringY
order.orderAmountOriginal order amountNumberY
order.orderCurrencyCurrency of the orderStringY
order.sourceSource of the order, i.e, APICHECKOUTStringY
order.countryCodeSource country code i.e alpha-2 country code E.g KEStringY
order.descriptionDescription of the orderStringY
customer.nameCustomer's nameStringY
customer.emailCustomer's emailStringY
customer.phoneNumberCustomer's phone numberStringY
customer.identityNumberCustomer's identity numberStringY
customer.firstAddressCustomer's first addressStringN
customer.secondAddressCustomer's second addressStringN
payment.paymentReferencePayment reference, should be unique per requestStringY
payment.paymentCurrencyCurrency of the paymentStringY
payment.channelChannel of the payment, e.g., MOBILEStringY
payment.servicePayment service, i.e., MPESAStringY
payment.providerPayment provider, i.e., JENGAStringY
payment.callbackUrlCallback URL to notify merchant when the transaction is completed or failedStringY
payment.details.msisdnNumber to push the STKStringY
payment.details.paymentAmountAmount to pay on the requestNumberY
signature formula
order.orderReference+payment.paymentCurrency+payment.details.msisdn+payment.details.paymentAmount

Example Request

Example Request
POST /api-checkout/mpesa-stk-push/v3.0/init
Content-Type: application/json
Authorization: Bearer {{ access_token }}
Signature: {{ generated_signature }}
Request Body
 
{
    "order": {
        "orderReference": "OR28922980077", //Order reference, should be unique per order 
        "orderAmount": 2, //Origininal order amount
        "orderCurrency": "KES",
        "source": "APICHECKOUT",
        "countryCode": "KE",
        "description": "Purchase"
    },
    "customer": {
        "name": "John Doe",
        "email": "xyx2@gmail.com",
        "phoneNumber": "0722000111",
        "identityNumber": "0000000",
        "firstAddress": "",
        "secondAddress": ""
    },
    "payment": {
        "paymentReference": "MKQR28922980073", //Should be unique per request
        "paymentCurrency": "KES",
        "channel": "MOBILE",
        "service": "MPESA",
        "provider": "JENGA",
        "callbackUrl": "https://webhook.site/5c74a733-1caa-4f10-b876-3df9c0d7453c",
        "details": {
            "msisdn": "0722000000", //Number to push the stk
            "paymentAmount": 2 //Amount to pay on the request
        }
    }
}

Response Parameters

FieldDescriptionFormatReq
statusResponse statusStringY
codeResponse codeNumberY
messageResponse messageStringY
dataResponse dataObjectY

Example Response

Example Response
HTTP/1.1 200 OK
Content-Type: application/json
 
{
    "status": true,
    "code": "0",
    "message": "Success. Request accepted for processing",
    "data": {
        "amount": 2.0,
        "charge": 1.0,
        "paymentReference": "MKQR28922980073",
        "invoiceNumber": "INVDBU",
        "orderReference": "OR28922980077",
        "amountDebited": 2.0
    }
}
Http Response CodeStatus CodeDescription
401106401Not Authorized to access this Telco,Kindly contact support@finserve.africa
200-1Transaction has been successfully acknowledged, await final transaction status on callback
200106201Failed to initiate push. Kindly try again after a few minutes or contact support@finserve.africa
500106500Error loading service
500106501Error mapping service

Jenga Callbacks

  • Once a payment is complete , you will receive a callback in this format if you provide a callback url on the request.
  • We dont recommend making your final decision based on this callback, but this can help when troubleshooting, We recommend the Complete Callback Response listed below.
Mpesa Confirmation Callback Response
HTTP/1.1 200 OK
Content-Type: application/json
{
  "status": true,
  "code": "0",
  "message": "The service request is processed successfully.",
  "transactionReference": "MKQR28922980073",
  "data": {
    "Body": {
      "stkCallback": {
        "MerchantRequestID": "0528-4964-bbde-4f38e64fe5f147817775",
        "CheckoutRequestID": "ws_CO_0908202416223944722000000",
        "ResultDesc": "The service request is processed successfully.",
        "ResultCode": 0,
        "CallbackMetadata": {
          "Item": [
            {
              "Value": 2,
              "Name": "Amount"
            },
            {
              "Value": "SH90HU7FO2",
              "Name": "MpesaReceiptNumber"
            },
            {
              "Name": "Balance"
            },
            {
              "Value": 20240809162247,
              "Name": "TransactionDate"
            },
            {
              "Value": 254722000000,
              "Name": "PhoneNumber"
            }
          ]
        }
      }
    }
  }
}
 

Complete Callback Response

  • We recommend registering a callback URL on Jenga HQ under Settings > IPNs as this is a confirmation of payment been processed successfully both on Mpesa and Jenga.
  • To find more about IPN callbacks navigate to IPN
Complete Callback Response
HTTP/1.1 200 OK
Content-Type: application/json
{
  "callbackType": "IPN",
  "customer": {
    "name": "John Doe",
    "mobileNumber": "0722000000",
    "reference": "OR28922980077"
  },
  "transaction": {
    "date": "2024-08-09 16:22:50",
    "reference": "SH90HU7FO2",
    "paymentMode": "MPESA",
    "amount": 2,
    "currency": "KES",
    "serviceCharge": 1,
    "billNumber": "INVDBU",
    "servedBy": "JENGA",
    "additionalInfo": "MPESA",
    "orderAmount": 2,
    "orderCurrency": "KES",
    "status": "SUCCESS",
    "remarks": "ED990222"
  },
  "bank": {
    "reference": "NONE",
    "transactionType": "C",
    "account": "NONE"
  }
}

Notifications

Sender ID: JENGA
 
~ Mpesa 
 
Mpesa payment confirmed. You have successfully completed your transaction of KES 5.00 to Spotify 
 Kenya on 13-06-2024 at 02:22:51 PM. Service charge, KES 0.00. Ref. SH90HU7FO2
 
 

Error Responses

400 Bad Request

Missing or invalid parameters in the request body.

{
  "status": false,
  "code": 400,
  "message": "Invalid request parameters",
  "error_code": "INVALID_REQUEST"
}

401 Unauthorized

Invalid or expired access token.

{
  "status": false,
  "code": 401,
  "message": "Invalid or expired access token",
  "error_code": "UNAUTHORIZED"
}

403 Forbidden

Valid credentials but invalid signature or insufficient permissions.

{
  "status": false,
  "code": 403,
  "message": "Invalid signature or insufficient permissions",
  "error_code": "FORBIDDEN"
}

404 Not Found

Account not found or invalid account number.

{
  "status": false,
  "code": 404,
  "message": "Source or destination account not found",
  "error_code": "ACCOUNT_NOT_FOUND"
}

Transaction Status Errors

Response StatusResponse CodeResponse Message
false111102Transaction with the passed reference cannot be found

📖 Step-by-Step Guide

Step 1: 🔑 Set Up Security Keys

Generate your private and public key pair and share your public key with Finserve. See the Security & Signatures Documentation (opens in a new tab) for detailed instructions.

Step 2: 🎫 Authenticate

Obtain an access token using the authentication endpoint. See the Authentication API documentation (opens in a new tab) for details.

Step 3: 📋 Prepare Transaction Details

Gather all required information.

Step 4: ✍️ Generate Signature

Create the signature string by concatenating in this exact order:

order.orderReference+payment.paymentCurrency+payment.details.msisdn+payment.details.paymentAmount

Sign this string using your private key, then Base64 encode the result.

Step 5: 📝 Set Up Headers

Include the following headers in your request:

  • Content-Type: application/json
  • Authorization: Bearer [your_access_token]
  • Signature: [your_base64_encoded_signature]

Step 6: 🔧 Construct Request Body

Create a JSON object with all required fields following the structure shown in the example request.

Step 7: 🚀 Send POST Request

Make a POST request to the internal bank transfer endpoint with your headers and body.


🌍 Supported Countries & Currencies

CountryCountry CodeCommon Currency Codes
KenyaKEKES
UgandaUGUGX
TanzaniaTZTZS
RwandaRWRWF
South SudanSSUSD
DRCDRCUSD

Best Practices

  1. ** Security**

    • Store your private key securely and never expose it in client-side code or version control
    • Always use HTTPS for API requests
    • Store access tokens securely
    • Regenerate signatures for each request
  2. ** Signature Generation**

    • Ensure exact string concatenation order: order.orderReference+payment.paymentCurrency+payment.details.msisdn+payment.details.paymentAmount
    • Do not include spaces, separators, or special characters in the concatenated string
    • Always Base64 encode the signature before including it in headers
    • Verify the values in the signature match exactly with the request body values
  3. ** Transaction Reference**

    • Use unique reference numbers for each transaction
    • Implement a reference generation system to avoid duplicates
    • Store reference numbers for reconciliation and audit purposes
    • Never reuse reference numbers, even for failed transactions
  4. Amount Formatting

    • Always use decimal format with two decimal places (e.g., "500.00")
    • Pass amounts as strings, not numbers
    • Ensure the amount is positive and within allowed limits
    • Verify amount matches exactly in signature and request body
  5. Error Handling

    • Implement retry logic with exponential backoff for transient errors
    • Log transaction attempts and responses for audit purposes
    • Handle signature validation errors by regenerating the signature
  6. Testing

    • Always test with the UAT endpoint before using the live endpoint
    • Use test account numbers provided in the documentation
    • Verify signature generation with sample data first
    • Test error scenarios to ensure proper handling
  7. Data Validation

    • Validate all account numbers match the expected format
    • Verify country codes are valid and supported
    • Ensure transfer dates are in the correct format (YYYY-MM-DD)
    • Validate currency codes match the destination country

Troubleshooting

Invalid Signature Error (403)

If you receive a 403 error with "Invalid signature":

  1. Verify the concatenation order: order.orderReference+payment.paymentCurrency+payment.details.msisdn+payment.details.paymentAmount
  2. Ensure no spaces or separators are included in the concatenated string
  3. Check that the signature is Base64 encoded
  4. Verify your public key is correctly registered with us
  5. Ensure the values in the signature match exactly with the request body values

Common Signature Mistakes

  • Using wrong concatenation order
  • Adding spaces or separators between values
  • Not Base64 encoding the final signature
  • Values in signature don't match request body values

Support

For questions or issues with this API: