Skip to main content

When it fires

After Settlx successfully transfers the settled funds to your configured wallet address. At this point the payment lifecycle is complete and the money is yours.

What to do

Fulfill the order. This is the only event that confirms funds have arrived in your wallet.
  • Release the digital product
  • Activate the subscription
  • Ship the physical order
  • Grant account access
Do not fulfill on any earlier event such as invoice.confirmed. Payment confirmation does not mean settlement is complete.

What lands in your wallet

The amount that arrives in your wallet is data.settlement.netAmount — the gross amount minus all fees.
FieldDescription
data.settlement.grossAmountAmount before fees are deducted
data.settlement.netAmountAmount that lands in your wallet
data.fees.platformFeeSettlx platform fee
data.fees.networkFeeOn-chain gas fee
data.fees.totalFeesSum of all fees deducted

Payload

Includes: invoice, payment, settlement, fees. Also includes conversion if a token swap occurred.
{
  "event": "invoice.settled",
  "eventId": "evt_a1b2c3d4-e5f6-7890-abcd-ef1234567890_invoice.settled_1744455900000",
  "timestamp": "2026-04-12T11:05:00.000Z",
  "data": {
    "invoice": {
      "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "amount": "49.99",
      "currency": "USD",
      "settlementCurrency": "USDT",
      "settlementChain": "polygon",
      "status": "settled",
      "createdAt": "2026-04-12T10:00:00.000Z",
      "metadata": { "orderId": "order_123", "customerId": "cust_456" }
    },
    "payment": {
      "id": "c3d4e5f6-a7b8-9012-cdef-345678901234",
      "transactionHash": "0xabc123...",
      "amount": "49.99",
      "currency": "USDT",
      "chain": "polygon",
      "confirmations": 12,
      "status": "confirmed"
    },
    "settlement": {
      "id": "d4e5f6a7-b8c9-0123-def0-456789012345",
      "transactionHash": "0xdef456...",
      "grossAmount": "49.99",
      "netAmount": "48.74",
      "currency": "USDT",
      "chain": "polygon",
      "status": "completed"
    },
    "fees": {
      "platformFee": "0.75",
      "platformFeePercent": "1.5%",
      "networkFee": "0.50",
      "providerFee": "0.00",
      "totalFees": "1.25",
      "currency": "USDT"
    }
  }
}

Handler example

Node.js
app.post('/webhooks/settlx', express.raw({ type: 'application/json' }), async (req, res) => {
  // Verify signature first — see Webhook Overview for full verification code
  verifySignature(req);

  const event = JSON.parse(req.body);

  if (event.event === 'invoice.settled') {
    const { invoice, settlement, fees } = event.data;

    // Always identify the order by your own metadata, not by invoice.id
    const orderId = invoice.metadata?.orderId;
    if (!orderId) {
      console.error('Missing orderId in invoice metadata', invoice.id);
      return res.status(200).json({ received: true }); // Acknowledge but log the issue
    }

    // Use eventId for idempotency — store it and skip if already processed
    const alreadyProcessed = await db.events.exists(event.eventId);
    if (alreadyProcessed) {
      return res.status(200).json({ received: true });
    }
    await db.events.insert(event.eventId);

    // netAmount is what landed in your wallet after all fees
    const amountReceived = settlement.netAmount;
    const currency = settlement.currency;

    // Fulfill the order
    await db.orders.update(orderId, { status: 'fulfilled' });
    await fulfillOrder(orderId, { amountReceived, currency });

    console.log(`Order ${orderId} fulfilled. Received ${amountReceived} ${currency}.`);
  }

  res.status(200).json({ received: true });
});
Always use data.invoice.metadata.orderId to identify the order. Never rely on data.invoice.id alone as your order identifier — invoice IDs are internal to Settlx and not meaningful to your system without the metadata link.