Skip to main content

When it fires

After the customer’s payment has received the required number of blockchain confirmations and the cumulative received amount meets or exceeds the invoice total. Settlx is now processing the conversion (if needed) and transfer to your wallet. This event fires for two outcomes — distinguished by data.payment_quality:
data.payment_qualityMeaning
fullThe customer paid exactly the required amount (within Settlx’s tolerance window).
overpaidThe customer paid more than the required amount. The excess is included in the settlement transfer to your wallet. data.excess_amount is the excess in data.excess_currency (the payment currency, e.g. BNB), not the settlement currency.
Partial payments (less than the required amount) do not fire this event — they fire invoice.underpaid instead, because the merchant action is fundamentally different.

What to do

Show the customer a “Payment received, processing…” status. Do not fulfil the order yet — funds are not in your wallet. Wait for invoice.settled before fulfilling. If data.payment_quality === 'overpaid', optionally log the excess for your records or notify the customer that they overpaid. The full received amount (including excess) lands in your wallet on invoice.settled.
This is an informational event. Its purpose is to let you update your customer-facing UI. All order fulfilment logic belongs in your invoice.settled handler.

Payload

Includes: invoice, payment, fees (estimated — final fees are in invoice.settled). The settlement object is not present yet.
{
  "event": "invoice.confirmed",
  "eventId": "evt_a1b2c3d4-e5f6-7890-abcd-ef1234567890_invoice.confirmed_1744455600000",
  "timestamp": "2026-04-12T11:00:00.000Z",
  "data": {
    "invoice": {
      "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "amount": "49.99",
      "currency": "USD",
      "settlementCurrency": "USDT",
      "settlementChain": "polygon",
      "status": "confirmed",
      "createdAt": "2026-04-12T10:00:00.000Z",
      "metadata": { "orderId": "order_123", "customerId": "cust_456" }
    },
    "payment": {
      "id": "c3d4e5f6-a7b8-9012-cdef-345678901234",
      "transactionHash": "0x9f4c3a8b7e6d5f4c3a8b7e6d5f4c3a8b7e6d5f4c3a8b7e6d5f4c3a8b7e6d5f4c",
      "amount": "49.99",
      "currency": "USDT",
      "chain": "polygon",
      "confirmations": 12,
      "status": "confirmed"
    },
    "fees": {
      "platformFee": "0.75",
      "platformFeePercent": "1.5%",
      "networkFee": "0.50",
      "providerFee": "0.00",
      "totalFees": "1.25",
      "currency": "USDT"
    },

    "payment_quality": "full"
  }
}
When payment_quality === 'overpaid', the payload also includes:
"payment_quality": "overpaid",
"excess_amount": "0.00076548",
"excess_currency": "BNB"
excess_amount is in excess_currency (the payment currency) — that’s the asset the customer overpaid in. The merchant still receives the full overpaid amount in their settlement currency on invoice.settled; this field tells you “the customer sent X more than required, in the asset they paid with.”

Handler example

Node.js
app.post('/webhooks/settlx', express.raw({ type: 'application/json' }), async (req, res) => {
  verifySignature(req);
  const event = JSON.parse(req.body);

  if (event.event === 'invoice.confirmed') {
    const { invoice, payment, payment_quality, excess_amount } = event.data;
    const orderId = invoice.metadata?.orderId;

    // Update the order status so your UI reflects the payment was seen
    await db.orders.update(orderId, { status: 'payment_confirmed' });

    if (payment_quality === 'overpaid') {
      await db.orders.update(orderId, {
        overpaymentAmount: excess_amount,
        overpaymentCurrency: invoice.settlementCurrency,
      });
    }

    // Notify the customer — do not fulfil yet
    await notifyCustomer(invoice.metadata?.customerId, {
      message: 'Your payment has been received and is being processed.',
      transactionHash: payment.transactionHash,
    });
  }

  res.status(200).json({ received: true });
});

Typical timeline

After invoice.confirmed fires, expect invoice.settled to follow within 1–10 minutes depending on network congestion and whether a token conversion is required.
  • invoice.settled — Funds have arrived in your wallet. Fulfil the order here.
  • invoice.underpaid — Customer paid less than the required amount. Different event; do not fulfil.