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
| Status | Terminal | Fires webhook | Meaning |
|---|---|---|---|
pending | no | no | Payment created, customer has not started yet. |
awaiting_payment | no | no | Customer picked a token, waiting for the transaction / manual transfer. |
confirming | no | no | Transaction submitted, waiting for on-chain confirmation. |
processing | no | no | Cross-chain swap/bridge order is executing. |
kyc_required | no | ✅ payment.kyc_required | Swap provider asked the customer to complete KYC. Payment is paused, not failed. |
needs_manual_check | no | ✅ payment.needs_manual_check | Unknown provider status — MutoPay support will investigate. |
completed | ✅ | ✅ payment.completed | Funds settled in your wallet. |
failed | ✅ | ✅ payment.failed | Payment failed. See failure_reason. |
expired | ✅ | ✅ payment.expired | Customer did not complete before expires_at. |
underpaid | ✅ | ✅ payment.underpaid | Customer 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, orunderpaidonce. Those are terminal. kyc_requiredandneeds_manual_checkare recoverable — they can transition back toprocessing, then continue tocompletedorfailed.- Recovery transitions fire no webhook. When
kyc_requiredclears back toprocessing, your webhook endpoint will not hear about it. Your signal is the eventualpayment.completedorpayment.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_reasonfor 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
- Webhooks — event list and payload.
- Create a Payment — where payments begin.