Fetch the live status of a single transaction by its transaction_id. If the transaction is still pending we poll the upstream provider and reconcile our ledger before responding; terminal transactions (approved or failed) are served straight from our ledger.
Endpoint
/v1/transactions/{transaction_id}transaction_id is the 12-digit id returned from /v1/collect/momo or /v1/checkout/session.Request
curl https://api.webrabbitmedia.com/v1/transactions/521888807466 \
-H "Authorization: Bearer wr_test_..."Response
{
"transaction_id": "521888807466",
"code": "00",
"reason_code": "approved",
"reason": "Transaction Successful",
"status": "approved",
"resolved_status": "approved",
"settled_at": "2026-09-11T11:54:31.402Z"
}Which field to trust
statusandresolved_statusare always the same value and both come from our ledger. Either is safe to act on. A collection only becomesapprovedafter the upstream provider returns an explicit terminal success for that transaction — an acknowledgement of the request ("transaction initiated") never approves it.reason_codeis the machine-readable outcome and is the field to switch on:approved,pending,prompt_sent,prompt_expired,insufficient_funds,declined,cancelled,reversed,failed,upstream_error.codeis the upstream provider's numeric status code (00success ·01failed ·02pending ·03processing) ornull. It is never a word — usereason_codefor logic andreasonfor display.settled_atis stamped only when the payment is confirmed collected, never at initiation. Apendingtransaction hassettled_at: null.correctionis present (non-null) only on a transaction that was reportedapprovedin error and has since been put right. Such a transaction readsstatus: "failed",reason_code: "settled_in_error",settled_at: null,reversed_at: null, andcorrection.previously_reported_status: "approved"withcorrection.corrected_at. The money was never collected, so this is a correction, not a reversal — if you credited on the earlier approval, unwind it.
reason_code is recorded at settlement time from that date onward. On older transactions it was filled in afterwards from the provider's message, so it is a faithful reading of what the provider said but was not captured at the moment of settlement.Unknown transaction — HTTP 404
If the id does not exist for your business + mode, we return HTTP 404 — never a synthetic failed body. Treat 404 as "no record yet"; if you have an Idempotency-Key for the request, look it up before assuming the payment did not happen.
{
"error": "transaction_not_found",
"transaction_id": "000000000000"
}Polling pattern
Poll every ~3 seconds for up to 60 seconds. If you're still pending after that, keep the transaction open in your UI and continue polling at a slower cadence (e.g. every 10s) — MoMo prompts can take longer than a minute to approve. See Webhooks — signed HMAC-SHA256 webhooks are live today and are the recommended path; polling is the fallback.
# poll every 3s until the transaction is no longer pending
for i in $(seq 1 20); do
out=$(curl -s https://api.webrabbitmedia.com/v1/transactions/521888807466 \
-H "Authorization: Bearer wr_test_...")
echo "$out"
echo "$out" | grep -q '"resolved_status":"pending"' || break
sleep 3
done