Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.moflay.com/llms.txt

Use this file to discover all available pages before exploring further.

Use this page to interpret values returned by the Moflay API and dashboard. Status reflects Moflay’s stored state, which is updated from Safaricom’s STK callback and, when needed, Daraja STK Push Query reconciliation—not from a live Safaricom lookup on every read.

Moflay transaction status

Each Express payment has a transaction status drawn from this set:
StatusMeaningTypical next step
initiatingMoflay is creating the payment attempt and sending the STK request to Daraja.Wait; poll GET /v1/payments/{id} or use webhooks when the status advances.
pendingSTK was accepted; waiting for the customer or for a final callback/reconciliation result.Wait for webhook or poll; customer may still complete or cancel on the phone.
completedPayment succeeded; Moflay recorded success.Fulfill the order; handle payment.completed if subscribed.
failedPayment did not complete (M-Pesa rejection, timeout, limits, etc.).Allow retry; handle payment.failed if subscribed.
canceledThe customer canceled the STK prompt (for example Daraja result 1032).Handle payment.canceled if subscribed; optionally offer a new attempt.
unknownMoflay could not determine a definitive outcome after reconciliation (for example missing or non-final Daraja signal).Manual review; no standard payment.* webhook is sent for this status.

Daraja ResultCode reference

When Moflay resolves an STK callback or query response, it maps Safaricom ResultCode values to the settlement outcome and user-facing detail. Known mappings include:
ResultCodeMaps toMessage (summary)
0Success → completedPayment completed successfully
1failedThe customer did not have enough available M-Pesa funds to complete the payment.
2failedThe requested amount is below M-Pesa’s minimum transaction amount.
3failedThe requested amount exceeds M-Pesa’s allowed transaction amount.
4failedThe customer or shortcode exceeded an M-Pesa transaction limit.
17failedM-Pesa rejected a duplicate or repeated request for the same amount.
1019failedThe STK prompt expired before the customer completed authorization.
1025failedM-Pesa rejected the request because one or more transaction fields were too long.
1032canceledThe customer cancelled the STK prompt.
1037failedM-Pesa could not reach the customer’s phone or the customer did not respond to the STK prompt.
2001failedThe customer entered an incorrect M-Pesa PIN.
2028failedM-Pesa rejected the request because the transaction configuration is invalid.
4999Still processing (pending path)The transaction is still under processing.
SFC_IC0003failedM-Pesa rejected the request because the shortcode, passkey, or initiator configuration is invalid.
Other or missing codes may still produce failed, canceled, or unknown depending on payload and reconciliation. Safaricom may also return a ResultDescription alongside the code; Moflay may surface that in status detail.

Webhooks

When a payment reaches a terminal webhook-eligible status, Moflay enqueues delivery to your endpoint:
Transaction statusWebhook event
completedpayment.completed
failedpayment.failed
canceledpayment.canceled
unknown(none — subscribe to polling or dashboard)
initiating and pending do not emit these completion webhooks. See Webhook events and Daraja callbacks.

Polling the Payments API

GET /v1/payments/{id} returns the current payment (and related transaction fields) from Moflay’s database. It does not query Safaricom on each request. For latency-sensitive UIs, combine short polling with webhooks.