Receive and Replay Callbacks

Daraja Local sends an HTTP callback when you approve, fail, or timeout an STK transaction.

Flow

1. Your app includes CallBackURL in the original STK Push request.

2. Daraja Local stores that callback URL on the pending transaction.

3. You approve, fail, timeout, or replay the transaction.

4. Daraja Local builds a Daraja-style callback payload from the transaction state.

5. Daraja Local -> Your callback URL
   Sends an HTTP POST with JSON.

6. Your app receives the callback.

7. Your app updates its payment record using CheckoutRequestID and ResultCode.

8. Daraja Local records the callback attempt on the transaction.

Your callback handler should be idempotent. A replay sends the callback again for the same CheckoutRequestID.

Configure the Callback URL

The callback URL comes from the original STK Push request:

{
  "CallBackURL": "http://127.0.0.1:3000/callback"
}

Your application should expose that URL and accept JSON POST requests.

Success Callback Shape

{
  "Body": {
    "stkCallback": {
      "MerchantRequestID": "1760000000000-abcd1234",
      "CheckoutRequestID": "ws_CO_1760000000000_abcd1234ef56",
      "ResultCode": 0,
      "ResultDesc": "The service request is processed successfully.",
      "CallbackMetadata": {
        "Item": [
          { "Name": "Amount", "Value": 100 },
          { "Name": "MpesaReceiptNumber", "Value": "DLOCALabcd1234" },
          { "Name": "TransactionDate", "Value": 20260603101010 },
          { "Name": "PhoneNumber", "Value": 254712345678 }
        ]
      }
    }
  }
}

Failure and Timeout Callback Shape

Failure and timeout callbacks do not include CallbackMetadata.

{
  "Body": {
    "stkCallback": {
      "MerchantRequestID": "1760000000000-abcd1234",
      "CheckoutRequestID": "ws_CO_1760000000000_abcd1234ef56",
      "ResultCode": 1,
      "ResultDesc": "The balance is insufficient for the transaction."
    }
  }
}

Replay a Callback

curl -X POST http://127.0.0.1:8080/simulator/stk/ws_CO_1760000000000_abcd1234ef56/replay-callback

Replay uses the transaction’s current state and sends the callback payload again.

Callback Delivery Failures

If the callback URL is unavailable, Daraja Local records a failed callback attempt on the transaction. It does not retry automatically in the current MVP.

Configure Callback Timeout

PowerShell:

$env:DARAJA_LOCAL_CALLBACK_TIMEOUT_MS = "10000"
daraja-local start