Payment Statuses

Every MutoPay payment has one of ten statuses. This page lists them, explains when each fires, and shows the legal state transitions you should expect to see.

Every MutoPay payment has a status field that transitions through a small state machine. Webhooks fire on terminal states and on states that need merchant attention. This page documents every value and the transitions between them.

Statuses

StatusTerminalFires webhookMeaning
pendingnonoPayment created, customer has not started yet.
awaiting_paymentnonoCustomer picked a token, waiting for the transaction / manual transfer.
confirmingnonoTransaction submitted, waiting for on-chain confirmation.
processingnonoCross-chain swap/bridge order is executing.
kyc_requirednopayment.kyc_requiredSwap provider asked the customer to complete KYC. Payment is paused, not failed.
needs_manual_checknopayment.needs_manual_checkUnknown provider status — MutoPay support will investigate.
completedpayment.completedFunds settled in your wallet.
failedpayment.failedPayment failed. See failure_reason.
expiredpayment.expiredCustomer did not complete before expires_at.
underpaidpayment.underpaidCustomer sent less than the required amount.

Transitions

pending ─▶ awaiting_payment ─▶ confirming ─▶ completed
                │                  │              │
                │                  ├─▶ processing ┤
                │                  │              │
                │                  │              ├─▶ failed
                │                  │              ├─▶ underpaid
                │                  │              └─▶ kyc_required ─▶ processing ─▶ completed
                │                  │                                              ╲─▶ failed
                │                  └─▶ needs_manual_check ─▶ (resolved off-band)
                └─▶ expired (anytime before terminal)

Key rules:

  • A payment can only transition to completed, failed, expired, or underpaid once. Those are terminal.
  • kyc_required and needs_manual_check are recoverable — they can transition back to processing, then continue to completed or failed.
  • Recovery transitions fire no webhook. When kyc_required clears back to processing, your webhook endpoint will not hear about it. Your signal is the eventual payment.completed or payment.failed.

Handling non-terminal alert statuses

For kyc_required:

  • Inform the customer that the swap provider requested identity verification. You may want to keep the order “pending” in your own system rather than cancelling it — it can still complete.
  • The customer’s next action happens off-MutoPay (in the swap provider’s flow).

For needs_manual_check:

  • Support will contact you if action is needed. Don’t auto-cancel the order — payment may still complete.
  • Check failure_reason for a hint.

Idempotency for webhook handlers

Since a payment can fire multiple webhooks across its lifetime (kyc_required → eventually completed, for example), your handler must be idempotent. The simplest pattern:

dedupe_key = payment_id + ":" + event
if already_processed(dedupe_key):
    return 200  // still ACK, so MutoPay stops retrying
record(dedupe_key)
handle(event)

See also