A customer's wallet says "Transaction Sent." From where you sit, nothing has happened yet. You don't know if the amount is correct, whether the transfer will stay on the canonical chain, or whether it's safe to ship anything. That gap between what the customer sees and what your business can act on is the entire reason payment infrastructure exists.
Most descriptions of crypto payments compress that gap into two words: unpaid, paid. It's a fine model for a personal wallet checking its own balance. It falls apart the moment a business has to decide, in code, exactly when to trust a transfer it didn't send.
Why unpaid/paid doesn't survive contact with production
A personal wallet only has to answer one question: did the money arrive? A merchant has to answer several, and they don't all resolve at the same moment.
Has the transfer been detected at all? Is the amount correct, given underpayment tolerance and any rounding? Could a chain reorganization still undo it? Has anything flagged it for compliance review? Is it safe to ship the order, or safe to let the customer withdraw the balance? Those are five different questions hiding inside one boolean, and a two-state model forces you to answer all five at once, at whatever moment you decide to call the payment "done."
Production payment systems avoid that trap by modeling the payment as a state machine instead of a switch. Suward's payment status moves through pending, accepted, success, or terminates at failed. A second, independent field, subStatus, tells you what's actually happening inside that status: awaitingPayment, confirming, completed, overpaid, underpaid, expired, cancelled, partiallyPaid. Two axes, read together, never inferred from one another.

The lifecycle, stage by stage
A payment is created in pending. If you configured an activation flow, it starts as pending / created with no address yet; otherwise it's pending / awaitingPayment the moment the deposit address is issued and the payment window starts counting. The first on-chain transfer moves it to pending / confirming, seen but not yet trusted.
From there it either reaches accepted (enough confirmations, balance credited, safe to fulfil) and later success (irreversible, withdrawable), or it terminates at failed — expired, cancelled, or invalidated without ever collecting a valid payment. That's the whole shape. Only the first stage and one of the two terminal outcomes are visible to the customer in any meaningful way. The stages in between exist to protect you.
Created, waiting for funds — or a transfer arrived and is confirming.
Safe confirmations reached. Balance credited. Ship, deliver, credit the user.
Irreversible. Funds are withdrawable.
Expired, cancelled, or invalidated without a valid payment. Terminal.
Static wallet deposits follow the same shape with different vocabulary: detected → accepted → confirmed, or ignored (the asset isn't on the wallet's allow-list, never credited) or invalidated (a reorg dropped it before acceptance). Each deposit lives on its own timeline, independent of every other deposit sitting on the same address.
What each transition actually buys you
The single most common mistake merchants make with crypto payments is treating detection as completion. A transaction showing up in a block explorer tells you a transfer was broadcast and included somewhere. It does not tell you that inclusion will hold.
accepted exists to close that gap. A payment reaches it only after several independent signals line up: enough confirmations for the network in question, no conflicting or competing transaction, the amount matches (within any configured tolerance), and compliance screening has cleared. Only then does the balance move, and only then does a payment.accepted webhook fire. Static deposits work the same way — static_deposit.accepted fires once a deposit clears the same bar.
That's the moment technical confidence turns into business confidence. It's also, deliberately, not the end of the story.

Accepted vs Success: two different questions
These two states get collapsed together constantly, and they answer different questions.
Accepted answers: can my business safely act on this right now? Success answers: has this payment reached final settlement under the finality policy for its network? A payment.accepted webhook credits your balance to a bucket that isn't withdrawable yet. A payment.success webhook moves the same funds to the bucket you can withdraw from or sweep with an auto-withdrawal rule. Terminal in both cases means the state won't change again — but "terminal for goods" and "terminal for money" happen at different points on the timeline.
Picture two merchants selling the identical product for the identical price. Merchant A credits the customer's account the instant a transfer is detected on-chain. Merchant B waits until the payment reaches accepted. On a demo, Merchant A looks faster. In production, Merchant A is exposed to every reorg and every race condition a distributed ledger can produce, because nothing it acted on was ever verified as safe. Merchant B built the same feature on a state that was actually checked.
Now stretch the comparison further. A SaaS platform activating a $29/month subscription can reasonably treat accepted as good enough to unlock the product — the cost of being wrong once is a support ticket. An institutional trading platform crediting a $5,000,000 deposit cannot afford the same tolerance; it waits for success, because reversing a bad decision at that scale is not a support ticket, it's a loss. Same two states, same API, completely different threshold applied by two different businesses. Suward doesn't pick that threshold for you — it hands you both stages and lets your integration decide which one gates which action.
Reorgs are already resolved by the time you see Accepted
Whether a chain reorganization can still undo a transfer is a question accepted has already
answered by the time you receive it — it's the outcome of verification, not the middle of it.
Confirmation depth, finality checkpoints, reorg recovery: the mechanics live in
Confirmations, Finality, and Reorgs
; this piece isn't going to re-derive them.
From blockchain event to business decision
Every state change your system reacts to travels the same corridor: a blockchain event gets verified, screened, weighed against an acceptance policy, and only then turned into a business action. payment.detected tells you a transfer showed up and is confirming — show the customer something, fulfil nothing. payment.accepted and static_deposit.accepted tell you it's safe to act. payment.success and static_deposit.success tell you it's safe to release the funds themselves. payment.failed and static_deposit.failed close the loop the other way — expired, cancelled, invalidated, or rejected by screening, with nothing credited.
Compliance sits inside that corridor rather than after it. A payment can be held in pending while a transaction is under compliance review, and a deposit that's rejected by screening has its credit reversed rather than ever having been paid out. None of that is a separate workflow bolted onto the payment afterward — it's one more gate the state machine already accounts for.

Designing for the case that isn't rare at scale
A network request that times out halfway through processing. A webhook delivered twice because your server's 200 response got lost on the way back. A customer who double-clicks "Pay" and fires the same create-payment request twice. None of these are edge cases in the sense of being unlikely — at meaningful transaction volume, each one happens routinely. Infrastructure that only works when nothing goes wrong isn't infrastructure, it's a demo.
Two mechanisms in Suward exist specifically for this category of problem, and both matter more as volume grows rather than less.
Atomic balance updates
When a payment moves from accepted to success, the status change and the balance change are not two operations that happen to run close together — they're one atomic write. Either both happen, or neither does. There's no window where a webhook reports one state and a balance query reports another, because they're never allowed to disagree in the first place. Without that guarantee, a crash between "update status" and "update balance" leaves you with a payment marked success and a balance that never moved, or the reverse — and reconciling that by hand across thousands of payments is not a task anyone wants.
Idempotent payment creation
The same retry problem hits payment creation itself: a network blip can lose the response to a POST /v1/payments call that actually succeeded, and a naive retry would create a second payment for the same order. Suward closes that gap with externalId — a repeat call is rejected with 409 instead of creating a duplicate. → Webhooks and Idempotency covers the full mechanism end to end.

How does this connect to webhook delivery?
Every state transition described here reaches your backend as a signed webhook —
payment.detected, payment.accepted, payment.success, payment.failed, and their
static_deposit.* equivalents. Delivery is at-least-once, so your handler has to assume the same
event can arrive more than once and stay correct anyway. That's a separate problem from the
lifecycle itself, and
Webhooks and Idempotency covers the
handler pattern — verify, deduplicate on eventId, commit in one transaction — end to end.
Reading state instead of guessing at it
None of this is about slowing payments down for its own sake. It's about giving your integration two honest checkpoints instead of one guessed one. accepted tells you when a transfer has cleared enough independent checks to act on. success tells you when it's actually yours to spend. A subscription can fire on the first checkpoint. A treasury withdrawal should wait for the second. Neither answer is wrong — they're calibrated for different amounts of money moving at different levels of risk.
The state machine is what makes that calibration possible. Collapse it back down to unpaid/paid and you lose the ability to make that call at all — you're stuck picking one threshold and applying it to every payment regardless of what it's for.
Further reading
- Confirmations, Finality, and Reorgs — how the accepted/success thresholds are actually calibrated per network, and what happens when a chain reorganizes underneath a pending payment.
- Webhooks and Idempotency — a handler that verifies, deduplicates, and commits every state transition without ever double-fulfilling.
- Payments vs. Static Wallets — the other axis of the same decision: which object should carry this lifecycle for your use case.
- The Complete Guide to Crypto Payment Gateways — the wider evaluation framework this lifecycle sits inside.
- Payment lifecycle & statuses — the full status and sub-status reference.
- Settlement & finality — atomic balances and the two-bucket model in full.