Payment matching and amount mismatches
This section describes the rule the service uses to match an incoming on-chain transaction to an issued invoice, what happens when the amount differs, and what the merchant can do in that case.
Invoice statuses, deadlines, and state transitions are described in Invoice lifecycle.
The amount match rule
At invoice creation, the service converts the fiat amount into crypto and locks the resulting amounts in for the invoice. They become the payment's identifier: the customer sees them on the payment form, and the service looks on-chain for a transaction of exactly that amount.
The payment amount must match the invoice amount exactly. There is no tolerance. The amount due is formed with 2 decimal places for the stablecoins USDT and USDC and 8 decimal places for other cryptocurrencies, and the incoming payment is compared against it precisely. Any deviation—underpayment or overpayment, however small—means no automatic matching will happen.
Example. An invoice for 100.00 USD is issued with a locked-in amount of 100.12 USDT.
| Incoming payment amount | Result |
|---|---|
| 100.12 USDT | The invoice automatically moves to Paid |
| 100.11 USDT | No automatic matching |
| 100.50 USDT | No automatic matching |
If several invoices for the same fiat amount are issued to one address at the same time, the service assigns each a slightly different crypto amount. Uniqueness is checked across all your unpaid invoices on that wallet, so one address can safely be used in several of your projects—the amounts will not collide.
The most common causes of a mismatch are the customer rounding the amount by hand or the network fee being deducted on a withdrawal from an exchange. Warn the customer to transfer exactly the amount shown on the payment form.
What happens on an amount mismatch
The service records that the funds arrived but takes no action on the invoice:
- The invoice does not change status. It stays unpaid until the payment deadline. The customer can still close it with the correct amount while the search window is open.
- No webhook is sent. The notification to the Webhook URL goes out only at the moment the invoice moves to Paid.
- Partial payment is not tracked. The service does not recognize underpayment and does not keep a balance due on the invoice.
- Payments are not added up. If the customer follows an underpayment with a second transaction for the missing difference, the two payments are not summed. Both remain separate unmatched payments.
- Overpayment is not refunded automatically. The funds go directly to your wallet; refunding the difference to the customer is handled outside the service.
There are no intermediate statuses like Partially paid or Overpaid in the service.
How the merchant learns about the problem
If notifications are enabled in the project settings, the merchant gets an email and a Telegram bot message about every incoming payment—whether or not it matched an invoice.
This gives a simple diagnostic rule: if an incoming payment notification arrived but no paid-invoice notification followed, the payment did not match because of an amount mismatch and needs manual handling.
The rule works only within the search window. The service monitors wallets only while at least one invoice still has an active search. If the customer pays when no such invoices exist, the payment never enters the system at all—no notification, and no way to match it manually.
You can also find unmatched payments programmatically. The payments/list method returns payments across all your wallets, and a payment not matched to an invoice has no invoice block in the response. These are the candidates for manual matching: compare the amount and time with the expected invoice and call invoices/bindPayment.
Manual payment matching
If you are certain which payment corresponds to which invoice, match them manually—in the dashboard on the invoice page or in the payment list, or via the API with the invoices/bindPayment method.
Matching conditions
Matching is possible only when all of the conditions hold at once:
- The invoice is Unpaid or Expired. Canceled and already paid invoices cannot be matched.
- The payment is not yet matched to another invoice. One payment can be tied to only one invoice.
- The payment arrived at a wallet involved in this invoice.
- The payment falls within the available payment window—24 hours before and 24 hours after invoice creation.
The window is wider than the invoice's validity, which opens two possibilities: you can match a payment to an already expired invoice, and you can match an invoice to a payment that arrived before the invoice was created. The latter is handy when the customer sent money on their own initiative and the invoice was issued after the funds arrived.
What happens after matching
- The invoice moves to Paid—just as with automatic matching.
- The webhook is always sent. The notification goes out on every transition to Paid, regardless of how the match was made.
- The invoice amount in USD is recalculated from the actual payment. The
amountFiatUSDfield is overwritten with the amount actually received, at the rate at the moment of matching. The original amount inamountFiatdoes not change. - The fee is recalculated from the actual amount. It is charged at the project's fee rate on the amount you received.