Got a tip? Let us know


Lipa na M-Pesa STK Push with Nodejs

October 14,2020 0 comments


The goal of this article is to educate you on how to consume Safaricom’s Lipa na M-Pesa Online Payment API using Nodejs as your programming language of choice. Just a heads up, Safaricom is a telecommunication company based in Kenya. Other than the telecom services (mobile network) it offers, Safaricom also offers M-Pesa, which is a mobile phone-based money transfer, financing and microfinancing service, launched back in 2007. Although native to East African countries, M-Pesa is currently a global service operating in more than 200 countries worldwide with the help of more than 500,000 Western Union money transfer service agents. With the increase in the number of ecommerce services across Africa, there is a need to use payment services in these web applications. M-Pesa is such a service. Herein you’ll be introduced on the ins and outs of this service.

M-Pesa APIs (Optional Reading)

M-Pesa service lists various APIs that a developer can consume. These are listed below. Their discussions have been uplifted from the official documentation.

  1. B2C API. This API enables Business to Customer (B2C) transactions between a company and customers who are the end-users of its products or services. Use of this API requires a valid and verified B2C M-Pesa Short code.
  2. B2B API. This API enables Business to Business (B2B) transactions between a business and another business. Use of this API requires a valid and verified B2B M-Pesa short code for the business initiating the transaction and the both businesses involved in the transaction.
  3. C2B API. This API enables Paybill and Buy Goods merchants to integrate to M-Pesa and receive real time payments notifications.
  4. Account Balance API. This API requests for the account balance of a Short code.
  5. Transaction Status API. Transaction Status API checks the status of a B2B, B2C and C2B APIs transactions.
  6. Reversal API. Reverses a B2B, B2C or C2B M-Pesa transaction.
  7. Lipa na M-Pesa Online Payment API. The API is used to initiate a M-Pesa transaction on behalf of a customer using STK Push. This is the same technique mySafaricom App uses whenever the app is used to make payments.

Why Lipa na M-Pesa Online Payment API?

This API uses a new feature introduced by Safaricom known as STK Push. This feature transfers the transaction initiation process from the paying customer to the Payee Organization. But what does this mean for everyone? For the paying customer, you no longer need to remember or jot down the business paybill and account numbers. Also, there will be no need to enter the amount. An STK Push prompt will simply appear on your phone. You will have to confirm the ongoing transaction by simply entering your PIN and Vwallah! Transaction complete. For the businesses, this API will enable you to preset all the correct info in the payment request and this reduces the chances of you receiving the wrong payments on your system.


Knowledge of JavaScript programming language is mandatory. You must have worked with Node.js and Express.js, the Node web framework. If not, you will have a rough time understanding the code because this is not a beginner tutorial. The explanations will be made as clear as possible.

Setting up the development environment


NodeJS is a JavaScript runtime environment that lives outside the browser. For more info, read this article. In a nutshell, NodeJS allows us to write apps using JavaScript language and then it gives us the functionalities of a web server from where we can host and run our JavaScript applications. Download and install it. Node comes with npm which is a package manager that allows you to install third party packages from the official repository. After installing it, open the command prompt and type the following codes that will output the versions of node and npm that are installed. 

node -v


To check for npm version, type 

npm -v 

The node version I am using is v12.18.3 while npm version is 6.14.6


Git is a version control tooling  software ecosystem that we will use to deploy our application to and also update our application as we see fit. Download and install it. After installing it, open the command prompt and type the following to check the version installed.


 git --version 


Heroku Cli

We will use cloud services from Heroku to deploy our node app. Heroku, unlike other web hosting solution providers, provides support for different programming languages with automatic detection and easy to use tools for deployment. Download and install it here. After installing it. Open the command prompt and check for its version by typing.


heroku --version


Text Editor

Use your own text editor of choice from the list below.

VisualStudio Code, SublimeText, Atom, Brackets, etc.


Connecting to Safaricom’s Daraja.

Visit Safaricom’s developer page and sign up or login if you already have an account. Got to my apps and create a new app.

While creating the app, ensure you select Lipa na M-Pesa sandbox option as shown. If you want to use your app with other APIs such as C2B, then you can select the other options too.

After your app has been created, click on it and you'll have a dropdown of your app’s details as below.

Note down your app’s Consumer Keys and Consumer Secret. We will need them later.

Next on, visit the docs tab and then the test credential side menu and then follow the link provided in the description as shown below.

The test credentials page will list some details you’ll need for simulating your app. Grab the ones shown below (

Also note down the authentication url by following the instructions in the image below. Go to the Authentication side menu and then on the code highlighter.

Lastly, Pick out the STK push processing url by following the instructions in the image below.

Writing our node Application

Aw we code together we will also learn the process flow of STK Push. Follow the steps below:

Step 1: Initializing a node project

Create a folder in a directory of your choice. Open the command prompt and navigate to the folder you’ve created.  Initialize an npm project by typing

npm init

Answer the questions presented. You can finish this up also by pressing enter throughout. On completion, this would create a ‘package.json’ file that will track  you packages and their versions installed. Open the package.json file and edit it as shown below.

“scripts”: { 
        “start”: “node index”


After this, install the following third-party packages from npm.


  • Express. Express is a Node framework for building HTTP based applications e.g web applications. 
  • Request. It’s a package used for making asynchronous API requests. It’s similar to Axios and Fetch APIs. We will use it to make requests to Safaricom APIs.
  • Moment. It’s a library for interacting with date-time. It simplifies a lot of hustle that one would face while dealing with JavaScript’s Data().

To install all this packages at once, run: 

npm install --save express request moment

After running this, you should have a ‘node_modules’ directory in your folder structure. This folder contains the third-party packages that you’ve installed. However, since all the tracking of these packages is done in ‘package.json’ file with the help of another file ‘package-lock.json’ which holds the exact package version dependency tree, you will not have to upload ‘node_modules’ folder to a repository or to a hosting server. Your server will only need the two json files with which it should run ‘npm install’ and then it will look into these files to see exactly what packages and version to install. On that note, ‘node_modules’ folder should be ignored by the version control system. Therefore, create a ‘.gitignore’ file on the root directory. Open up the file and write to it, on the first line, ‘node_modules’ without the quotation marks. ‘.gitignore’ file tells Git tooling to ignore all files and folder plus its file contents listed  therein during commits and pushing. 

Your folder structure should look like below:

Finally, create our main file and name it index.js. This is where our code will be written.

Step 2: Creating our server.

Inside index.js, write the following

const express = require('express'); //importing express
const request = require('request'); //importing request api
const moment = require('moment'); //importing moment

const app = express(); //creating express instance

//Mounting application routes
app.get('/', (req, res)=>{
     console.log("Logger working fine")
     res.send("Hello World"); //Sending response to client

const port = process.env.PORT || 3000;
app.listen(port, ()=>{
      console.log(`App listening on port ${port}`);

The above code, as commented out, imports the three third party libraries we need by storing their instances in constant  variables. It then invokes an express server instance and stores it in a variable named ‘app’. Hereon, express will be available via this ‘app’ variable. After these, we create our app routes that will handle client requests. The default route is the home route represented by ‘/’. When a client visits it (sends a get request), we log to the console some Info and then send a “Hello World” string back to the client. Last but not least, we create a port variable and initialize it to the default given port by the running process or a fallback port of 3000. Lastly, we direct our server to listen on this port and if successful, we log some message to the console via a callback function. Run your server by typing 

node index.js

Ensure you run this command in the same directory where you app lives. You should get a message saying “App running on port 3000” logged in your console. Visit the home url ‘localhost:3000’ on a browser. and you should get the Hello world response in addition to the logs in your console.

Step 3: Taking to M-Pesa APIs

To note, all M-Pesa requests (except Register URL API) are asynchronous in nature. This means that when you send a request, you will not immediately receive a result showing completion of the transaction. Instead, when you make a request, you’ll receive an acknowledgement that the request was received and is currently being processed, and then, you’ll wait for feedback when the processing of your request is done. This feedback will be delivered to you via a Listener / Callback URL or a Webhook. Therefore, we will make use of the callback URLs earlier noted. To make it clearer, you first make a request, then, if your request passes all the checks, you get an Acknowledgement (which is not the result of the transaction) that the request has been received and is being processed asynchronously. Then, after processing is done, you get the feedback via the callback URL. The callback URLs can be created via two means, to state, you can register the URLs on the system (used by C2B API only), or rather preset it in your initial request (used by the other APIs). Also to note, depending on the transaction type and the outcome of the transaction, the result can either be a success or failure but don't mistake the acknowledgement response for a successful transaction. 


Very important to note is that, every API call you’ll make to M-Pesa APIs must be authenticated. To aid in this, M-Pesa has an authentication API for generating the tokens you’ll need for authenticating your calls. This is the first API we will interact with. Express makes it very easy to create and use middlewares. Middlewares are functions that have access to both request and response objects. To mean, middleware functions can access and modify the request object payload before you send it to a server and can also access and modify the response object payload before it’s sent to the client by the server. Therefore, we will create a middleware function for generating the access tokens. We will then plug this middleware function into whatever API requests we will make. Let’s get to it.


After your get route you mounted, add the following code.

function access(req, res, next){
//Access token
let consumer_key = 'iABCDEFGH12your app consumer key’ //your consumer key
let consumer_secret = 'v5mysecret'; //your app consumer secret
let url = ""; //Authentication url 
let auth = new Buffer.from(`${consumer_key}:${consumer_secret}`).toString('base64');
            url: url,
            headers: {
            Authorization": `Basic ${auth}`
        (error, response, body)=>{
                  req.access_token = JSON.parse(body).access_token


In the above code, we have created a function called ‘access’. We have then saved our app’s consumer key and secret keys on variables of the same names. We have also saved the authentication URL on a variable named ‘url’.  The M-Pesa APIs require  a base64 encoded ‘Basic’ authentication token string from the consumer key and secret. To generate this, we have combined the two and saved them in a buffer and then stringified the contents of the buffer to a base64 encoding then saved the instance in a variable called ‘auth’. Finally, we have used the request API to make the apis call to the authentication URL. The request API takes the first parameter as the payload which contains the url and the authorization headers. The second parameter is a callback function which logs the errors in case of any else it converts the access token string and metadata to JSON and then patches them to the request object by adding the access_token variable. Given its use is done, it then passes functionalities to the next middleware or function in the chain using the next() function. With this, we have a function for generating the access token whenever we call it. 

Getting the access token:

It’s time to put our function to test.  Create a new ‘get’ app route and pass to it the token generator middleware as shown below: 

app.get('/access_token', access, (req, res)=>{
              access_token : req.access_token


The route has been named ‘access_token’. So everytime this route is hit, we will receive the access token. In that route the server is responding to the client with a status code of 200 to mean everything went ok. It also responds with a json object that has a key named ‘access_token’ whose value is obtained from the request object as appended earlier. Run your server again and hit the route  ‘localhost:3000/access_token’. You should see something like below. 

Step 4: Lipa na M-Pesa STK Push API

This is the real deal, so get ready. To begin with, Here is the theory on the STK push transaction flow.

  1. The Business (you) sets the data in the request and sends it to the API.
  2. The API receives your request and validates it internally first, then sends you an acknowledgement response. As mentioned earlier , this is not the final transaction response.
  3. The API then sends an STK Push request to the target customer's mobile phone. The customer's phone has to be online (connected to mobile network and not Internet) and unlocked to receive the request.
  4. The customer then confirms the payment amount and business name via the message displayed on-screen, then either enters the PIN or cancels the request accordingly.
  5. The API receives the customer's response. If the response is a negative, it cancels the transaction and sends a corresponding  callback to the initiating 3rd party via the predefined callback URL in the initial request. This payload contains the info on why the transaction was cancelled. Possible negative responses could caused by:                                    
    • An invalid PIN entered by the customer
    • Timeout due to customer not entering the PIN within a given time period (usually 1 min 30 secs)
    • The customer's SIM card not having the STK applet on it
    • A literal request cancellation by the user on their phone
    • Insufficient balance on the customer’s account.
    • Another STK transaction is already underway on the customer's phone (no more than one request can be processed at the same time on the same phone)           
  6. If the PIN is correct, then this means the customer accepted the request and therefore the API forwards the transaction to M-Pesa.
  7. M-Pesa automatically processes the request, then sends the response back to the API system which then forwards it to you via the callback URL specified in your initial request. Here, the callback can also either be a success or failure, just like a normal C2B transaction.
  8. To note, there are no repeat calls for failed callbacks, thus if the API is unable to send the callback to you, you can use the Transaction Status Query API to confirm the status of the request.

To end with, simulating this API requires an active line and real cash will be transacted. For the amount used during tests, kindly use values as low as 1 - 10 Kenya shillings to perform your transactions. This will lengthen the number of tries you make and also prevent unnecessary losses if M-Pesa doesn’t reverse the amounts to your account every midnight as they claim. Mine were not reversed back to me . Also beware, the API does not allow one to perform more than 5 consecutive STK requests without completing them. This will be marked as phishing, and will cause your line to be blocked from making any more STK requests for the next 24 hours.

Theory aside, let's write the code as below: Add the code below your access token code.


Add the above line right below the express app instantiation line. It attaches express inbuilt bodyparser middleware for parsing POST request bodies. The code below is added below your access_token route code.

app.get('/stk',access, (req, res)=>{
     let endpoint = "";
     let auth = `Bearer ${req.access_token}`;
     let shortcode = 174379;
     let passkey = "bfb279f9aa9bdbcf158eyourpasskeyhere";
     let timestamp = moment().format('YYYYMMDDHHmmss');

     const password = new Buffer.from(`${shortcode}${passkey}${timestamp}`).toString('base64');

        url: endpoint,
        method: "POST",
        headers: {
            'Authorization': auth
    json: {
        "BusinessShortCode": "174379",
        "Password": password,
        "Timestamp": `${timestamp}`,
        "TransactionType": "CustomerPayBillOnline",
        "Amount": "1",
        "PartyA": "2547xxxxxxxx",
        "PartyB": "174379",
        "PhoneNumber": "2547xxxxxxxx",
        "CallBackURL": "",
        "AccountReference": "123TEST ",
        "TransactionDesc": "Process activation"

    function(error, response, body){

The code begins by declaring a new app route name ‘/stk’. This means that for you to fire your stk push, you will hit this url. Also note that we have made use of the access token  function created earlier. This will avail for us the access token via req.access_token. We have then saved our stk URL in a variable named endpoint. Then generated a bearer access token and saved in a variable named auth. We have also saved our passkey in a variable of the same name. Before I resume the code explanation, understand the following. The STK push API requires various fields as explained below:

  • BusinessShortCode. This is the shortcode of the organization initiating the request and expecting the payment. For tests, use the one you saved from your developer account.           
  • Password. This is the Base64-encoded value of the concatenation of the Shortcode + LNM Passkey + Timestamp.
  • Timestamp. This is the same Timestamp used in the encoding above, in the format YYYMMDDHHmmss. It’s the current timestamp       
  • TransactionType. The type of transaction being performed. These are the same values as the C2B command IDs (CustomerPayBillOnline and CustomerBuyGoodsOnline) and the same rules apply here. For now, only CustomerPayBillOnline is supported.           
  • Amount. Self explanatory                       
  • PartyA. The Debit party of the transaction/the party paying out in the transaction, hereby the phone number of the customer.                       
  • PartyB. The credit party of the transaction/the party being paid in the transaction, hereby being the shortcode of the organization. This is the same value as the Business Shortcode
  • PhoneNumber. Same as PartyA.                       
  • CallBackURL. This is the endpoint where you want the results of the transaction delivered. Same rules for Register URL API callbacks apply                       
  • AccountReference. This is the value the customer would have put as the account number on their phone if they had performed the transaction via phone.
  • TransactionDesc. Short description of the transaction. Optional, but element must be present.

Back to the code. We have used moment library to generate the current timestamp  and then generated the base64 password. A request is then sent to the API. Note that it’s a POST request since we are adding content to the server. You can put whatever name you choose under account reference. The M-Pesa API will send a callback via the URL listed. I have used an active server url because of some issues with the API not able to POST to my local machine. You will get your active URL once we have created a hosting environment on Heroku. Finally we have passed a callback function which responds with the acknowledgement info from the API. If you hit ‘localhost:3000/stk’ and everything goes as expected, then you should see something like below.

Step 5: Callback route

As explained earlier, when M-Pesa is done processing your request, It fires your application callback URL and POSTs to it data pertaining the transaction information. We should therefore have a POST route for handling this callback. Add the below code after the ‘stk’ route code.'/stk_callback', (req, res)=>{

In a nutshell, M-Pesa will hit this URL and then send the info as a request body. We have access to this body via the req object. We will log the response object as shown below.

Once we have hosted our app, you’ll be able to see these info more clearly on your heroku cli console. The request body object has a ‘Body’ property which is also an object that has another object called stkCallback which is also an object that has the transaction info that we need. If successful, then access the CallbackMetadata object that has this info. You can do whatever you want with this data including saving it to the database for processing your carts and application.


Deploying to Heroku.

Visit and signup or login to your account dashboard. Use the ‘new’ button provided to create a new app. Name it whatever you like and leave the rest as defaults. After you have created your app, you will be taken to the deploy tab of your app. Scroll down to the section for deploying using heroku Git as shown below.

The instructions therein are fairly straightforward. I will not spend any time here. After you are done deploying your app. Run 

heroku open

 This will fire your application in a new browser tab. You can also use the ‘open app’ button in your dashboard. If all went well, you should see hello world in the browser. Now copy the address of the app and update your code’s CallBackUrl  to reflect the new domain. Do this in your text editor. Do not forget to append ‘/stk_callback’ to it otherwise M-Pesa API will  not be able to fire this url. Finally add the changes to your git’s staging area, commit them and then push them to heroku master. Use the commands below.

git add . 
git commit -m “My message”
git push heroku master

After these, open up your app again and see if hello world is still running. Now open you heroku logs by typing 

heroku logs --tail

Everytime you fire a route e.g ‘/’, ‘/stk’, you will see the appropriate logs. Try firing ‘/stk’ and then complete the transaction from your phone and then see the logs. Congratulations for staying with me for such a long article. You can find the complete code ready for cloning and edits from my github page. Feel free to ask any questions. 

Michael Jaroya

He is a technology enthusiast, a writer, and motivator.An individual with the love for humanity..

More in this category: New Kenyan banks mobile cash transfer systems ยป


Add Comment