BTC$68,420▲ 0.82% / ETH$3,841▼ 0.31% / LTC$94.05▲ 1.14% / SOL$221.60▲ 3.02% / USDT·TRC20$1.0000 / USDC·ERC20$0.9999 / XMR$168.42▼ 0.18% / TON$6.02▲ 0.47% / XRP$2.41▼ 0.09% / GAS·ETH18 gwei / Indicative prices · illustrative ticker / No-KYC · non-pooled · 0.4% flat / BTC$68,420▲ 0.82% / ETH$3,841▼ 0.31% / LTC$94.05▲ 1.14% / SOL$221.60▲ 3.02% / USDT·TRC20$1.0000 / USDC·ERC20$0.9999 / XMR$168.42▼ 0.18% / TON$6.02▲ 0.47% / XRP$2.41▼ 0.09% / GAS·ETH18 gwei / Indicative prices · illustrative ticker / No-KYC · non-pooled · 0.4% flat
OrbChain
UTC 18:47:02 Get started →
§ Guide · 2026-08-17

The buyer types
the amount.

Card payments charge an exact figure; crypto payments request one. The buyer's wallet does the typing, their exchange skims a withdrawal fee off the top, and your 100.00 USDT invoice meets 99.20 in the wild. Any invoice system that only understands "paid" and "not paid" turns these near-misses into support tickets. Here's the machinery that absorbs them instead.

The tolerance window: don't litigate dust

The most common shortfall isn't a dishonest buyer — it's an exchange deducting its withdrawal fee from the sent amount. So invoices carry an underpay tolerance (on the order of 1%): a payment inside the window counts as paid in full, credits, and fires payment.paid like any other. The alternative — chasing every buyer for the last 0.4% — costs more in support than it recovers in dust, every single time.

Below the window: Underpaid, a state that isn't a failure

A payment materially short doesn't fail and doesn't disappear. It moves to Underpaid — an explicit, non-terminal state with its own payment.underpaid webhook carrying two fields your order system should surface verbatim: paid_amount (credited so far) and remaining (what completes it). The money received is real and tracked; the order just isn't done.

The important property: top-ups work. The buyer sends the difference to the same address, deposits accumulate, and the moment the total crosses the threshold the payment flips to Paid and the normal webhook fires. No new invoice, no refund-and-retry dance. Your UI's job is one line: "received 80, send 20 more to the same address." Handle the webhook, show the numbers, and most underpayments resolve themselves without a human.

  • Don't ship on Underpaid. Obvious, but worth stating — partial credit is never treated as fulfillment-worthy by default, precisely so the decision stays yours.
  • Decide your cleanup policy up front: for orders that stall underpaid past expiry, either refund the partial (a standard partial refund of what actually credited) or settle out of band. Write it into your terms before it happens.

Overpayments: the happy problem

Buyers double-send, fat-finger, or round up. The excess isn't lost — every deposit to the payment's address is recorded and credited, and your dashboard shows exactly what arrived versus what was asked. The excess is simply money you owe the buyer: issue a partial refund of the difference to a destination they confirm. (The refund API's cumulative cap math handles "refund the overage, keep the invoice amount" cleanly.) Publishing a one-line overpayment policy — "we refund excess over X automatically, keep-the-change below it" — turns the whole category into a non-event.

Paid after the deadline

Invoices expire; blockchains don't. A buyer can broadcast five minutes before expiry and confirm twenty minutes after, or dig up last week's payment page from a tab. Late money is never dropped: a deposit landing after expiry still credits your balance — recorded at the current market rate rather than the invoice's long-stale locked rate — while the order stays expired. That split is deliberate: rate locks can't be honored indefinitely in a moving market, but customer funds must never evaporate on a technicality. Operationally: match the deposit to the customer (the dashboard shows the address and amounts), then either fulfill anyway or refund — your call, made with the money safely in hand.

The integration checklist

  • Fulfill on payment.paid only; treat everything earlier as UI.
  • Handle payment.underpaid: surface paid_amount / remaining and the same-address top-up instruction.
  • Have a written policy for the three edges — stalled underpayments, overpayments, late payments — before your volume finds them for you.
  • Skip the whole genre where you can: static-address top-up flows have no requested amount to miss, and fiat-priced invoices at least guarantee the target was right when the buyer saw it.
§ Keep reading

Related posts.

Hand-picked
Same rails, next questions