Crypto Payment Statuses 2026: 9 Gateways Compared
We read the payment status docs of nine crypto payment gateways in October 2026: 73 named states, five data shapes and six words for a paid invoice.
Key Takeaways
- Nine gateways, 73 named states, no two vocabularies alike. Cryptomus publishes 14 values; NOWPayments, CoinGate and OxaPay nine each; BitPay seven plus a second field; BTCPay Server five plus four exceptions; Plisio six labels. BlockBee and Blockonomics publish no status names at all.
- Six different words mean "the money is yours":
finished,paid,Complete,Settled,is_paid: trueand the integer2. On BitPay,paidis not one of them. - Only three of the nine tell you when to ship. CoinGate writes it into the status table, BTCPay Server publishes a Typical action column, and NOWPayments says it in a blog post rather than its API docs.
- One underpaid invoice, five designs — and on CoinGate and Blockonomics, no representation at all.
- Four statuses keep moving after they look final. BitPay promotes
invalidtocompleteif the transaction confirms late, BTCPay leaves a fully paid invoice atExpireduntil a human acts, and Blockonomics has a-1meaning a confirmed payment was reverted.
A webhook lands on your server carrying one word, and you have to decide from it whether to ship a product. On one gateway that word is finished; on the next it is paid, which on a third means the money arrived but nothing is confirmed; on a fourth there is no word at all, only four booleans. We read the published status reference of nine crypto payment gateways on 6 October 2026 and counted 73 named states between them, five ways of modelling the same invoice, and six spellings of the one state a merchant cares about. Three of the nine tell you which status is safe to fulfil on; the other six leave the most consequential decision in your integration undocumented.
These crypto payment statuses are not cosmetic. Pick the wrong one as your delivery trigger and you either hand over goods against a transaction that can still be dropped from the mempool, or you sit on a paid order while the customer opens a ticket. Both failures look like a bug in your code and are actually a misreading of someone else's enum. This is the map we wanted when we wired up our first one.
Every crypto payment status, in one map
No cross-gateway mapping of these vocabularies exists anywhere we could find, including on the gateways' own comparison pages. Here is all of it, read from each provider's current documentation:
| Gateway | Values | Published status names |
|---|---|---|
| Cryptomus | 14 | paid, paid_over, wrong_amount, process, confirm_check, wrong_amount_waiting, check, fail, cancel, system_fail, refund_process, refund_fail, refund_paid, locked |
| NOWPayments | 9 | waiting, confirming, confirmed, sending, partially_paid, finished, failed, refunded, expired |
| CoinGate | 9 | new, pending, confirming, paid, invalid, expired, canceled, refunded, partially_refunded |
| OxaPay | 9 | new, waiting, paying, paid, manual_accept, underpaid, refunding, refunded, expired |
| BitPay | 7 + 2 | Status: new, paid, confirmed, complete, expired, invalid, declined. Separate exceptionStatus: paidPartial, paidOver |
| BTCPay Server | 5 + 4 | Base: New, Processing, Settled, Expired, Invalid. Exception: Paid partial, Paid over, Paid late, Marked |
| Plisio | 6 | New, Pending, Complete (with an overpayment percentage, e.g. Completed 200%), Underpaid, Cancelled, Error |
| BlockBee | 4 | No names. Booleans: is_paid, is_pending, is_expired, is_partial |
| Blockonomics | 4 | No names. Integers: -1 reverted, 0 unconfirmed, 1 one confirmation, 2 two or more |
Cryptomus and Blockonomics sit at the extremes: 14 named states against four integers, for the same job. That is not a difference of detail, it is a difference of what the field is for, and it is the thing to work out before you write a single case statement.
Five ways to model one payment
Sort the nine by the shape of the data rather than the words in it and the field collapses into five designs. Each one puts a different question beyond your reach.
| Design | Gateways | What it cannot express |
|---|---|---|
| One flat enum | NOWPayments, CoinGate, OxaPay, Cryptomus, Plisio | Two facts at once. An invoice that is both expired and paid has to pick a side |
| Status plus an exception field | BitPay, BTCPay Server | Nothing much — this is the design that fits the problem |
| Independent booleans | BlockBee | Order. Four booleans have 16 combinations and no documented sequence |
| A confirmation counter | Blockonomics | Amount. The integer counts blocks and knows nothing about how much arrived |
| A label with a number inside it | Plisio | Machine parsing. Completed 200% is a sentence, not an enum member |
The two-field design is the one to copy, and only two of nine use it. BitPay keeps the lifecycle in status and the amount anomaly in exceptionStatus, which is false by default and becomes paidPartial or paidOver. BTCPay Server does the same with a base status and an exception, and it is the only one of the nine that can say "fully paid, but after the deadline" without losing either half: the base status stays Expired and the exception reads Paid late.
BlockBee is the outlier worth a warning. Its checkout logs endpoint returns no status name at all, and the field in that response literally called status is the status of your API request — it reads success on an invoice nobody has paid. The payment state is in is_paid, is_pending, is_expired and is_partial, alongside value, value_paid and value_outstanding per coin. Branching on response.status there is a bug that passes every happy-path test.
Six words for "the money is yours"
Across nine gateways the successful terminal state is spelled six different ways, and two of those words are used by other gateways to mean something earlier and weaker.
| Word | Means "money is yours" on | Means something weaker on |
|---|---|---|
finished | NOWPayments — funds have reached your address | — |
paid | CoinGate, Cryptomus, OxaPay | BitPay — the amount arrived, nothing is confirmed |
complete / Complete | BitPay (account credited), Plisio (sums match) | — |
| Settled | BTCPay Server — settlement conditions met | — |
confirmed | — | NOWPayments — confirmed on chain, not yet sent to you |
is_paid: true | BlockBee | — |
2 | Blockonomics — two or more confirmations | — |
BitPay is the trap in that table. Its documentation is explicit that paid only means the received amount met or exceeded the request; confirmation has not happened and the merchant account has not been credited. Two more statuses come after it. Anyone porting a handler from CoinGate, where paid is the final success state and the docs say goods can be safely delivered, to BitPay by matching the string is shipping against unconfirmed transactions and will not find out from an error.
NOWPayments contains the mirror image. Its confirmed means the customer's funds have accumulated enough blockchain confirmations — a strong-sounding word for a payment that has not yet been forwarded to you. sending comes next, and finished after that.
Which status actually lets you ship
This is the only question most integrations need answered, and six of the nine providers never answer it in their status documentation. Here is what each one does say, and the practical trigger.
| Gateway | Fulfil on | Does the vendor say so? |
|---|---|---|
| CoinGate | paid | Yes — its status table says purchased goods or services can be safely delivered |
| BTCPay Server | Settled | Yes — a Typical action column: fulfil according to your business policy |
| NOWPayments | finished and the amount matches | Yes, in a blog post — not in the API reference |
| BitPay | confirmed (earliest) or complete (safest) | Partly — confirmed is described as usable for fulfilment |
| Blockonomics | status of 2 or more | Partly — its callbacks guide recommends it for e-commerce |
| Cryptomus | paid or paid_over | No guidance published |
| OxaPay | paid | No guidance published |
| Plisio | Complete | No guidance published |
| BlockBee | is_paid: true | No guidance published |
BitPay separates fulfilment from settlement on purpose. confirmed fires after however many confirmations you configured through the transactionSpeed parameter, and the docs present it as the status merchants can use to fulfil orders. complete arrives later and means BitPay has credited your account in your settlement currency: for Bitcoin that is six confirmation blocks and roughly an hour. The default confirmation targets are published too — 6 for BTC, BCH and XRP, 40 for DOGE, and 50 for ETH and the stablecoins it supports — so the gap between the two statuses is a parameter you chose, not a fixed delay.
NOWPayments tells you not to trust its own status field, which is the most useful sentence any of these vendors has written on the subject. Its integration guidance says to deliver on your amount rather than the status, because partially_paid is a completed payment where the customer sent less than the price. Check that outcome_amount matches what you expected before releasing anything — advice that sits in a blog post rather than in the NOWPayments API reference a developer actually reads.
BTCPay Server says it plainly: do not fulfil an order merely because an on-chain transaction was broadcast. NOWPayments says of confirming that the payment is not final and the correct action is to do nothing. Blockonomics flags replace-by-fee on unconfirmed payments. A broadcast transaction can be replaced or dropped, which is exactly why a "seen it in the mempool" status exists on five of the nine — it is there to be waited on, not acted on.
Underpayment: five designs for one event
A customer whose wallet deducts the network fee from the send amount instead of adding it on top underpays by a few cents. It is the commonest non-failure in crypto checkout, and the nine gateways represent it five different ways.
| Approach | Gateway | Underpaid becomes | Overpaid becomes |
|---|---|---|---|
| Its own status | NOWPayments | partially_paid (a completed payment) | No separate status |
| Its own status | OxaPay | underpaid | Not published |
| Its own label | Plisio | Underpaid | Complete with a percentage, e.g. Completed 200% |
| Two statuses, by recoverability | Cryptomus | wrong_amount, or wrong_amount_waiting when a top-up is still possible | paid_over |
| A second field | BitPay | exceptionStatus: paidPartial — status stays new | paidOver, auto-refunded |
| A second field | BTCPay Server | Exception: Paid partial | Exception: Paid over |
| A boolean | BlockBee | is_partial: true | Not modelled |
| Not modelled | CoinGate, Blockonomics | Nothing in the published status set | Nothing in the published status set |
Two of these will surprise you in production. BitPay keeps a partially paid invoice at new — its docs say so in as many words, on the grounds that from a merchant's perspective an invoice is either paid or not and partial payments are refunded to the consumer automatically. So the status field never mentions the underpayment; exceptionStatus does, and a handler that only reads status sees an invoice still waiting for payment that will never be paid. Cryptomus is the only one that encodes recoverability, splitting the event into wrong_amount and wrong_amount_waiting depending on whether the customer can still top up. That distinction is genuinely useful and nobody else makes it.
The statuses a person sets, not the chain
Three of the nine have a status that records a decision rather than a blockchain fact, and if you treat it as evidence of payment you have built a hole in your own reconciliation.
- OxaPay
manual_accept— the invoice was manually accepted by you and the amount charged to your balance. It sits in the same enum aspaid, so string matching cannot distinguish a confirmed payment from an accepted shortfall. - BTCPay Server Marked — a store user manually marked the invoice settled or invalid. Its documentation adds the sentence that matters: this does not prove that a blockchain payment confirmed.
- NOWPayments
partially_paid— its guidance for a shortfall is to wait for the rest or complete the payment yourself from the dashboard, so one status covers "short" and "short but we accepted it".
If your accounting treats a terminal status as proof of funds received, at least three of these nine will let a human-set value through that check. Plisio is the same problem from the other direction: its published labels carry no marker for whether a Complete was reached by arithmetic or by a click.
Which statuses are final, and which move afterwards
Not one of the nine marks its statuses terminal or non-terminal. Four of them document transitions out of a state that reads like an ending.
| Looks final | Gateway | What can still happen |
|---|---|---|
invalid | BitPay | Set when a paid invoice is not confirmed within an hour. If it confirms later, BitPay updates the invoice to complete |
| Expired | BTCPay Server | Full payment arriving after expiry adds the exception Paid late; the base status stays Expired until a human acts |
2 (final) | Blockonomics | Its USDT monitoring endpoint documents a -1 meaning reverted — the only reorg state named anywhere in this set |
wrong_amount_waiting | Cryptomus | By definition recoverable: the client may still pay the balance |
declined | BitPay | Genuinely terminal: no longer eligible for completion, typically after 24 hours unconfirmed |
The windows that lead into these states differ by three orders of magnitude, which is worth knowing before you set a timeout of your own. CoinGate expires a new order after two hours and a pending one after twenty minutes. BitPay gives a purchaser a fifteen-minute payment window. NOWPayments only expires a payment when the funds have not arrived within seven days. A reconciliation job that assumes any single one of those is universal will mark live invoices dead on two of the three.
Where the docs disagree with themselves
We found the same drift the gateway error vocabularies show: the published reference is not always consistent with itself, and the copy you happen to read decides what you build.
NOWPayments publishes its payment status list five times in the Postman collection that is its API reference: under Create payment, Create payment by invoice, Get payment status, and twice more inside its casino use-case folder. Two of those five copies list eight statuses and omit refunded entirely, and the warning against automatically providing goods on a partially_paid payment appears in exactly one of the five. The same collection reuses waiting, sending, finished and failed for payouts in eleven more places, so finished names two different events in one API depending on which object you are holding.
Blockonomics documents three values in one place and four in another. Its callbacks guide lists 0, 1 and 2; its USDT monitoring endpoint adds -1 for reverted. A handler written from the guide has no branch for the one value that means money you counted has gone away.
Plisio publishes no status enum at all in its endpoint documentation — we checked its documentation index and its invoice-callback page. The only consolidated list we found is a support FAQ, which also notes that Underpaid used to be labelled Expired in an older API version. Cryptomus, by contrast, publishes 14 definitions with no sequence, no terminal markers and no delivery advice: the richest vocabulary in the set and the least guidance on what to do with it.
Searching for crypto payment status meanings still surfaces Coinbase Commerce's payment-status page at docs.cdp.coinbase.com/commerce/introduction/payment-status, with its New, Signed, Pending and Completed vocabulary. We fetched it on 6 October 2026 and it returns HTTP 404: Coinbase Commerce closed on 31 March 2026. If a status table you are coding against came out of a search result, check the product still exists.
What to put in your status handler
Everything above reduces to seven rules, and they hold on all nine gateways.
- Branch on an explicit allow-list, never on a substring.
paidis the end state on CoinGate and a mid-lifecycle state on BitPay;confirm_checkcontainsconfirmand means waiting. - Check the amount, not only the status. NOWPayments' own advice, and it generalises.
- Read the second field. On BitPay and BTCPay Server the status alone cannot tell you an invoice was underpaid, overpaid or paid late.
- Treat unknown values as unhandled, and alert. Two of nine have a documented value their main guide omits, so your enum is probably incomplete the day you ship it.
- Make the terminal set explicit in your own code, because no gateway publishes one. Then allow for the exceptions: a BitPay
invalidcan becomecomplete, and a Blockonomics2can become-1. - Make delivery idempotent. A status that moves after it looked final, plus webhook retries, means your fulfilment path will be entered twice for one order sooner or later.
- Log the raw payload. When a vocabulary changes under you, the only way to prove what the gateway sent is to have kept it.
Write that once and it does not transfer: there is no shared vocabulary here to abstract over, which is a real cost of switching processors and one that never appears in a fee comparison.
- NOWPayments Review 2026: Fees, Coins and Restrictions
- BTCPay Server Review: Self-Hosted and Non-Custodial
- CoinGate Review: Fees, Countries and Coin Support
- Cryptomus Review: Fees, Custody and the FINTRAC Penalty
- Blockonomics Review: Direct-to-Wallet Bitcoin Payments
- OxaPay Review: Fees, Features and Caveats
The status vocabulary is part of the integration cost. Weigh it before you sign up.
We track fees, custody, KYC, settlement timing and supported chains for every processor in the directory. How clearly a gateway models its own payment states belongs on that list, because it is paid for in engineering hours rather than basis points. NOWPayments publishes the most explicit delivery guidance of the nine; BTCPay Server has the cleanest model.
Compare Crypto Payment Gateways →FAQ
What does partially_paid mean on a crypto payment?
On NOWPayments it means the customer sent less than the invoiced price and the funds have arrived in your wallet, so it is a completed payment for a smaller amount rather than a failure. NOWPayments advises against automatically providing goods or services on it. Other gateways name the same event differently: OxaPay calls it underpaid, Cryptomus splits it into wrong_amount and wrong_amount_waiting, and BitPay and BTCPay Server keep it out of the status field and report it in a separate exception field instead.
Which crypto payment status means I can deliver the goods?
It depends on the gateway, and only three of the nine we checked say so in their documentation. CoinGate states in its status table that goods can be safely delivered at paid. BTCPay Server names Settled in a Typical action column. NOWPayments says, in a blog post rather than its API reference, to deliver on the amount rather than the status once a payment is finished. On BitPay the earliest safe status is confirmed and the safest is complete.
Is paid the same as confirmed on a crypto payment gateway?
Not on BitPay, where paid only means the received amount met or exceeded the request and confirmed comes afterwards once your configured number of blockchain confirmations is reached. On CoinGate it is the reverse order: confirming is the waiting state and paid is the confirmed, credited end state. The same two words carry opposite relationships on two gateways in the same directory, so never port a handler by matching strings.
Can a crypto payment status change after it looks final?
Yes, on four of the nine. BitPay updates an invoice from invalid to complete if the transaction confirms more than an hour after payment. BTCPay Server adds a Paid late exception to an expired invoice while leaving the base status at Expired until a human acts. Blockonomics documents a -1 meaning the transaction was reverted. Cryptomus defines wrong_amount_waiting as recoverable by a further payment.
Why does BlockBee not return a payment status?
Because it models payment state as four independent booleans rather than one enum. Its checkout logs response carries is_paid, is_pending, is_expired and is_partial, plus the requested, paid and outstanding values per coin. The field named status in that same response is the status of your API call and reads success even for an unpaid invoice, which is the single easiest mistake to make against that API.
How long before a crypto invoice expires?
It varies by three orders of magnitude across the gateways we checked. BitPay gives the purchaser a fifteen-minute payment window. CoinGate expires a new order two hours after creation and a pending order twenty minutes after the customer picks a currency. NOWPayments expires a payment only if the funds have not arrived within seven days. Read your own gateway's figure before you write any job that treats an old invoice as dead.
Which crypto payment gateway has the clearest payment statuses?
BTCPay Server, on the evidence of its own documentation. It separates the lifecycle from the amount anomaly into a base status and an exception, publishes a recommended action for each of its five base statuses, warns against fulfilling on a broadcast transaction, and states that a manually marked invoice does not prove a payment confirmed. BitPay uses the same two-field design but spreads the fulfilment decision across three statuses.
Affiliate disclosure: Payyd earns a commission if you sign up to NOWPayments through the link on this page. That does not change the status definitions, windows or caveats reported here, all of which come from the providers' own documentation.
Sources
Primary documentation read on 6 October 2026:
- NOWPayments API reference (Postman collection): payment and payout status lists
- NOWPayments: best integration practices (deliver on amount, not status)
- Cryptomus: payment statuses (14 values)
- CoinGate: order statuses and expiry windows
- OxaPay: payment status table
- BitPay: invoice statuses, exceptionStatus and targetConfirmations
- BTCPay Server: invoice statuses, exceptions and typical actions
- BlockBee: get checkout logs (is_paid, is_pending, is_expired, is_partial)
- Blockonomics: callbacks guide (status 0, 1, 2)
- Blockonomics: monitor USDT transaction (status -1 reverted)
- Plisio: transaction statuses FAQ — the only consolidated list we found; its documentation index and invoice-callback endpoint page publish no status enum