How to Do Polling Requests to an API in JavaScript (with MPESA STK Push Example)
Sospeter Mong'are

Sospeter Mong'are @msnmongare

About: Software Engineer passionate about developing for the web

Location:
Kenya
Joined:
Nov 22, 2018

How to Do Polling Requests to an API in JavaScript (with MPESA STK Push Example)

Publish Date: Oct 4
0 0

When you integrate payments like MPESA Daraja STK Push, the customer confirms the payment on their phone. The result (success or failure) is not immediate - Safaricom will notify your server via a callback URL.

But what about the user who is waiting on your web app? 🤔
This is where polling comes in.


🔑 Recap: MPESA STK Push Flow

  1. User clicks Pay Now.
  2. Your backend calls the Daraja STK Push API → Safaricom sends an STK prompt to the user’s phone.
  3. Backend saves the transaction in DB with status = PENDING.
  4. Safaricom calls your /callback once the user accepts/declines. Backend updates status → SUCCESS or FAILED.
  5. Frontend polls the backend every few seconds until the status changes from PENDING.

🖥️ Example Backend (Django / Node.js / Laravel – concept is same)

Pseudo-code:

# /stk-push endpoint (called when user clicks Pay Now)
def stk_push(request):
    # Call MPESA STK Push API here...
    tx = Transaction.objects.create(status="PENDING")
    return JsonResponse({"transaction_id": tx.id})

# /callback (Safaricom will call this)
def callback(request):
    data = json.loads(request.body)
    tx_id = data["MerchantRequestID"]  # example unique ID
    result_code = data["ResultCode"]

    status = "SUCCESS" if result_code == 0 else "FAILED"
    Transaction.objects.filter(id=tx_id).update(status=status)
    return JsonResponse({"Result": "OK"})

# /check-status (frontend polls this)
def check_status(request):
    tx_id = request.GET.get("tx_id")
    tx = Transaction.objects.get(id=tx_id)
    return JsonResponse({"status": tx.status})
Enter fullscreen mode Exit fullscreen mode

🌐 Frontend (JavaScript Polling)

<!DOCTYPE html>
<html>
<head>
  <title>MPESA STK Push Example</title>
</head>
<body>
  <button onclick="initiatePayment()">Pay with MPESA</button>
  <p id="statusMsg"></p>

  <script>
    function initiatePayment() {
      // Step 1: Call backend to trigger STK Push
      fetch("/stk-push", { method: "POST" })
        .then(res => res.json())
        .then(data => {
          const txId = data.transaction_id;
          document.getElementById("statusMsg").innerText = "STK Push sent. Enter your MPESA PIN...";
          pollStatus(txId); // start polling
        })
        .catch(err => console.error("Error:", err));
    }

    function pollStatus(txId) {
      // Step 2: Keep checking every 3s
      const interval = setInterval(() => {
        fetch(`/check-status?tx_id=${txId}`)
          .then(res => res.json())
          .then(data => {
            console.log("Payment Status:", data.status);

            if (data.status !== "PENDING") {
              clearInterval(interval);
              document.getElementById("statusMsg").innerText = "Payment " + data.status;
            }
          })
          .catch(err => console.error("Error:", err));
      }, 3000); // every 3 seconds
    }
  </script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

🔄 What Happens in Practice

  1. User clicks Pay with MPESA → STK push request sent.
  2. User enters MPESA PIN on phone.
  3. Frontend keeps showing “Waiting for confirmation…” and polls backend.
  4. Safaricom calls your /callback with result.
  5. Backend updates DB → SUCCESS or FAILED.
  6. Next poll request sees the new status → frontend updates instantly.

⚠️ Notes for Beginners

  • Always use a database (MySQL, Postgres, MongoDB) to store transaction status.
  • Don’t keep the frontend waiting forever → you can set a maximum wait time (e.g. 1 minute).
  • Polling is simple but not the most efficient → later you can upgrade to WebSockets for real-time push notifications.

Summary

  • MPESA STK Push is asynchronous → you don’t get instant results.
  • Polling lets your frontend “wait” while the user enters MPESA PIN.
  • Use /stk-push to initiate, /callback to receive result, and /check-status to poll for updates.

Comments 0 total

    Add comment