Transaction states

Every state a Scan to Pay transaction can be in, what it means, and what the integrator should do.

A Scan to Pay transaction progresses through a state machine. This page lists every state the system can return, grouped by what they mean for the integrator. Authoritative values are taken directly from TxState in the Scan to Pay platform source.

How to use this page

You will see transaction states in webhook payloads, in code/queryRef responses (merchants), in getTransactionState responses (wallet providers, on the Remote API), and in the Admin Portal.

Three things to remember:

  1. SUCCESS is the only positive terminal state. If you see anything else, the transaction did not complete normally — even if the state name sounds OK.
  2. END_* states are terminal. Stop polling. Do not retry the same transaction; create a fresh one if the customer wants to try again.
  3. States prefixed START_*, PROCESS_*, OFF_TO_*, RECEIVED_* are transient. Keep polling or wait for the webhook.
📘

Wallet naming note

Several enum values include MASTERPASS in their literal name (OFF_TO_MASTERPASS, END_MASTERPASS_COMPLETE, etc.). These are preserved for wire compatibility — treat them as the canonical Scan to Pay wallet states. Production traffic returns the literal values shown below.

Terminal — Success

StateMeaning
SUCCESSThe transaction has been completed successfully. Funds are committed.
END_3DS_PURCHASEA 3D Secure transaction completed (terminal success of the 3DS flow).
CODE_NOTIFY_SUCCESSThe merchant notification was delivered and acknowledged. Often paired with SUCCESS.
CODE_NOTIFY_SUCCESS_NOACKThe merchant notification was delivered but no acknowledgement was received from the merchant. The payment still succeeded — but check the merchant's webhook handler.
CODE_EXTERNAL_SUCCESSExternal code flow completed successfully.

Terminal — Customer didn't complete

The customer started the flow but didn't finish. Treat as "abandoned cart."

StateMeaning
END_CLIENT_CANCELThe customer cancelled while trying to pay (network/USSD only).
END_CLIENT_TIMEOUTThe customer timed out while trying to pay (network/USSD only).
END_CLIENT_CANCELLED_RECURRING_PAYMENTThe customer cancelled a recurring payment series.

Terminal — Declined by bank or issuer

The bank or card issuer rejected the transaction. The customer may be able to retry with a different card.

StateMeaning
END_BANK_NON_00The acquiring bank returned a non-00 ISO response code. Inspect the response code for the precise reason.
END_BANK_DECLINEThe bank declined the transaction.
END_INSUFFICIENT_FUNDS_OR_OVER_CREDIT_LIMITBlocked before reaching the bank because TPE rules (mandated by Visa/Mastercard) detected insufficient funds.
END_ACCOUNT_CLOSED_OR_FRAUDULENTThe card account is closed or flagged as fraudulent.
END_CARD_EXPIRY_NOT_ALLOWEDCard expiry date not permitted by the merchant or scheme.
END_BIN_NOT_WHITELISTEDThe card BIN is not in the merchant's allowed list.
END_NOTALLOW_BIN_CLASSIFICATIONThe merchant does not accept this BIN classification (e.g. international cards on a domestic-only merchant).
ISSUER_NEVER_APPROVEThe issuer has declined and will never approve this transaction (do not retry — present a different funding source).
ISSUER_NOT_APPROVE_NOWThe issuer declined for now (the customer may retry shortly).

Terminal — Authentication / 3D Secure failures

StateMeaning
END_BRE_REJECTIONBankServ / ACS rejected the 3D Secure step.
END_HASH_FAILEDA hash check failed (mismatched MSISDN / card number / cardholder data).

Terminal — Bank communication issues

These usually indicate a transient infrastructure problem on the bank side, not a card problem.

StateMeaning
END_BANK_EXPIREDThe transaction expired waiting for a bank response.
END_BANK_ERRORAn error occurred on the bank node.
END_BANK_OFFLINEThe bank node was offline or unreachable.
END_PIN_PUSH_ERRORError while pushing the PIN request to the customer.
END_PIN_PUSH_OFFLINEPIN push channel offline.

Terminal — Scan to Pay platform errors

Our side. Investigate before retrying.

StateMeaning
END_SYSTEM_ERRORUnexpected error in the Scan to Pay platform.
END_SYSTEM_FAULTUnhandled exception in the platform.
END_TIME_OUT_IN_QUEUETransaction waited too long in an internal queue (typically RabbitMQ to a bank node).
END_CODE_PURCHASE_ERRORError processing the code-based purchase.
END_VOUCHER_ERRORError during a voucher purchase.

Terminal — Validation failures

The request was rejected before reaching the bank.

StateMeaning
END_INVALID_AMOUNTThe amount on the purchase was rejected (zero, negative, exceeds maximum, or doesn't match the code amount).
END_VALIDATION_FAILEDGeneric validation error while processing the transaction.
END_CODE_IN_USEA use-once code was already used.

Terminal — Risk / fraud / limit blocks

The platform blocked the transaction. Customer is not at fault; retry with caution.

StateMeaning
END_LIMIT_FAILEDThe transaction failed a limit check (e.g. daily / monthly airtime limit).
END_FRAUD_DETECTIONThe transaction was flagged by fraud detection rules.
END_BLACKLISTEDThe card, MSISDN, or device is blacklisted.
END_TX_RATE_BLOCKEDThe customer exceeded the allowed transaction rate (velocity check).

Terminal — Refunds and reversals

These appear on the original transaction when a refund or reversal is applied.

StateMeaning
END_REVERSEDThe transaction has been reversed successfully.
END_REVERSAL_FAILEDA reversal attempt failed (e.g. outside the reversal window).
END_REFUNDEDThe transaction has been refunded (full or partial).
END_REFUND_FAILEDA refund attempt failed.
MARKED_FOR_REVERSALThe transaction is queued for reversal (transient — wait for END_REVERSED or END_REVERSAL_FAILED).

Terminal — WIG / USSD timeout failures

Specific to feature-phone and Wallet Initiation Gateway flows. The customer didn't respond to a prompt in time.

StateMeaning
END_TIMEOUT_PURCHASECustomer received the WIG push but did not select/add a card and authorise.
END_TIMEOUT_PURCHASE_3DSA 3DS transaction was initiated but not completed.
END_TIMEOUT_BALANCETimed out waiting for the balance response.
END_TIMEOUT_CARD_DETAILSCustomer entered card details but the transaction timed out before completion.
END_TIMEOUT_ADD_CARDAdd-card request sent; no response from customer.
END_TIMEOUT_RELINK_MSISDNTimeout while relinking the MSISDN to a card.
END_TIMEOUT_CARD_VALIDATIONTimeout on a card-validation call.
END_TIMEOUT_LINK_CARD_FAILEDThe card link failed because the customer didn't pass the bank's hash check.
END_TIMEOUT_HASH_CHECK_FAILEDHash check failed during card linking.
END_TIMEOUT_CARD_NOT_SUPPORTEDCustomer entered a BIN that isn't supported.
END_TIMEOUT_REMOVE_CARDTimeout removing a card.
END_TIMEOUT_INVALID_PINCustomer entered an invalid PIN format.
END_TIMEOUT_INVALID_CVVCustomer entered an invalid CVV format.
END_TIMEOUT_INVALID_CARD_NUMBERCustomer entered an invalid card number.
END_TIMEOUT_INVALID_ACC_TYPECustomer entered an invalid account type.
END_TIMEOUT_INVALID_EXPIRYCustomer entered an invalid expiry date.
END_TIMEOUT_INVALID_DOBCustomer entered an invalid date of birth.
END_TIMEOUT_REQUEST_QOSNo quality-of-service feedback from WIG on the initial request.
END_TIMEOUT_REQUEST_QOS_GET_CARD_READYSystem failed to send a QOS message during get-card-ready.
END_TIMEOUT_REQUEST_QOS_GET_CARD_READY_SENTQOS message sent for get-card-ready; user didn't respond within the limit.
END_TIMEOUT_REQUEST_QOS_SELECT_BANKSystem failed to send a QOS message at the select-bank step.
END_TIMEOUT_REQUEST_QOS_SELECT_BANK_SENTQOS message sent for select-bank; user didn't respond within the limit.

Terminal — Code lifecycle

For codes (QR codes) themselves, not for transactions.

StateMeaning
CODE_NOTIFY_FAILThe merchant notification webhook failed to deliver.
CODE_NOTIFY_FAIL_NOACKNotification delivered but no acknowledgement received.
CODE_EXTERNAL_FAILEDExternal code flow failed.

Transient — Start / mid states

You generally only see these inside the platform or in admin tools, not in webhooks delivered to integrators. Listed for completeness.

StateStageMeaning
START_CODE_PURCHASEStartA code-based purchase has been initiated.
START_NETWORK_PURCHASEStartA network (USSD/WIG) purchase has been initiated.
START_NETWORK_BALANCEStartA network balance check has been initiated.
START_MOBILE_PURCHASEStartA mobile-initiated purchase has been initiated.
START_WIG_3DS_PURCHASEStartA WIG 3D Secure purchase has been initiated.
START_3DS_PURCHASEStartA 3D Secure purchase flow has been initiated.
START_3DS_PURCHASE_PENDINGStartA 3DS purchase is pending the customer's auth step.
START_VOUCHER_PURCHASEStartA voucher purchase has been initiated.
START_STRIKE_PURCHASEStartA strike (chargeback-style) purchase has been initiated.
START_CCPI_PURCHASEStartA card-on-file recurring purchase has been initiated.
START_CODE_NOTIFYStartThe merchant-notify flow has started for a completed code.
PROCESS_CODE_NOTIFYMidThe merchant-notify HTTP call is in flight.
PROCESS_VOUCHER_PURCHASEMidA voucher purchase is being processed.
OFF_TO_BANKMidThe transaction has been sent to the acquiring bank for authorisation.
OFF_TO_MASTERPASSMidThe transaction has been sent to the Scan to Pay wallet, awaiting a reply.
RECEIVED_MASTERPASS_WALLET_REPLYMidA reply has been received from the Scan to Pay wallet.
RECEIVED_PIN_RESPONSEMidPIN entry response received from the customer's device.
END_MASTERPASS_ERRORMid → terminalError returned from the Scan to Pay wallet (during the wallet leg, before bank).
END_MASTERPASS_COMPLETEMid → terminalThe wallet leg completed successfully (typically followed by OFF_TO_BANKSUCCESS).

Notes for integrators

  • Polling cadence. If you do not have a webhook configured, poll the transaction state at no faster than once every 5 seconds. Most transactions reach a terminal state within 30 seconds.
  • Idempotency. Do not treat any transient state as success. Only SUCCESS and END_REFUNDED / END_REVERSED (for refund and reversal flows) are settle-positive.
  • Display to customers. Never show raw state names to end users. Map them to human-readable copy in your UI.

What's next

  • Receive states via webhookWebhooks
  • Map bank decline reasons to customer messagesISO response codes
  • HTTP error codes you'll see before a state is reachedErrors
  • Retry safely with the same referenceIdempotency