Payment Statuses
A payment starts PENDING and ends in exactly one terminal status:
| Status | Terminal | Meaning | Merchant action |
|---|---|---|---|
PENDING | No | Awaiting payment — the customer has not completed an on-chain transfer yet. | Do not fulfil yet. |
SUCCESS | Yes | Paid — the received amount matches the expected amount. | Fulfil after verify. |
ACCEPTABLE | Yes | Paid with a small deviation that is within the tolerance you configured. | Fulfil after verify. |
MISMATCH | Yes | Paid, but under- or over-paid outside your tolerance. | Hold for manual review. |
EXPIRED | Almost | The payment window elapsed with no payment. | Do not fulfil — but see below. |
SUCCESS, ACCEPTABLE and MISMATCH are final: a payment never leaves them, and never changes into another one.
EXPIRED has one exception, described next.
An EXPIRED payment can still be paid
A customer who sends the transfer after the payment window has closed is still paid into the address Finomesh gave them — the blockchain does not know the window elapsed. Rather than lose those funds, Finomesh keeps watching that address for a grace period after expiry. If the money arrives inside it, the payment reopens and resolves to SUCCESS, ACCEPTABLE or MISMATCH exactly as a timely payment would.
This means:
- An
EXPIREDpayment can change status days later, with no action by you or the customer. - You receive a second webhook for that payment, carrying the new status. If you cancelled the order on the
EXPIREDnotification, treat this one as a genuine late payment, not a duplicate — webhooks are delivered once per status change. - The amount is judged against the price quoted when the payment was created, not the price on the day it arrived. For a stablecoin that makes no difference. For a volatile asset, a deposit that lands days late may resolve
ACCEPTABLEorMISMATCHwhere a fresh quote would have saidSUCCESS. - Verify still decides. Call verify as usual;
depositPathon the response tells you why a payment resolved after expiring (see below).
A payment that expired and was never paid stays EXPIRED forever — which is the overwhelming majority of them.
depositPath — how the deposit reached us
Verify returns depositPath once a payment has a recorded deposit:
| Value | Meaning |
|---|---|
scanner | The ordinary case: paid inside the payment window. |
late_confirmation | Paid inside the window, but the blockchain confirmation reached us after it closed. The customer was on time. |
late_capture | Paid after the window closed, and credited anyway through the grace period described above. |
manual_inquiry | Matched to the payment from a transaction hash submitted after the fact. |
You do not need to branch on it to fulfil correctly — status remains the decision. It exists so a payment that resolved days after it expired can be explained rather than guessed at.
How SUCCESS / ACCEPTABLE / MISMATCH is decided
Finomesh compares the USD value of what arrived on-chain (minus any fees the customer covers) against the USD value of what was expected:
- Exact match →
SUCCESS - Deviation within your configured tolerance (
overAcceptableDiff/underAcceptableDiff, as flat USD or a percentage) →ACCEPTABLE - Anything else →
MISMATCH
You configure the tolerance per payment at creation (or inherit your gateway's defaults). Setting checkAmountDeviation: false disables the check entirely — any paid amount resolves to SUCCESS.
SUCCESS and ACCEPTABLE are the only statuses you should fulfil on, and only after a server-side verify call — never from the callback or webhook alone.