Workflow guide

Confirm settlement

Settlement should be webhook-first. Read APIs are your reconciliation fallback, not the primary source of realtime truth.

Recommended confirmation model

  1. Receive a webhook and verify its signature against the raw body.
  2. Apply the event to your order state only after validating the event type and resource ID.
  3. If the webhook is delayed or disputed, read the invoice detail as fallback.
  4. Use `paidAmount`, `settledByTolerance`, `toleranceRaw`, and `shortfallRaw` to record the real settled amount.

Webhook envelope example

json
{
  "id": "evt_2b3f1fa0",
  "event": "invoice.paid",
  "timestamp": "2026-03-14T13:46:04.903Z",
  "data": {
    "invoiceId": "inv_123",
    "businessId": "biz_123",
    "status": "paid",
    "amount": {
      "raw": "150000000",
      "decimals": 6,
      "display": "150",
      "symbol": "USDC",
      "chain": "eth",
      "networkId": "base-mainnet"
    },
    "paidAmount": {
      "raw": "149750000",
      "decimals": 6,
      "display": "149.75",
      "symbol": "USDC",
      "chain": "eth",
      "networkId": "base-mainnet"
    },
    "settledByTolerance": true,
    "toleranceRaw": "500000",
    "shortfallRaw": "250000",
    "txHash": "0x9ee6..."
  }
}

Node.js signature verification

ts
import crypto from 'node:crypto';

export function verifyPayChainHQWebhook(rawBody, signatureHex, webhookSecret) {
  const expected = crypto.createHmac('sha256', webhookSecret).update(rawBody).digest('hex');
  return crypto.timingSafeEqual(Buffer.from(signatureHex, 'hex'), Buffer.from(expected, 'hex'));
}

Settlement cases you must support

CaseWhat PayChainHQ doesWhat you should do
Exact paymentInvoice becomes `paid` after confirmations.Fulfill normally.
Underpayment within toleranceInvoice becomes `paid` with `settledByTolerance=true`.Fulfill, but store the true `paidAmount` and shortfall metadata.
Underpayment above toleranceInvoice stays `partially_paid` until top-up or expiry.Do not fulfill automatically.
OverpaymentInvoice becomes `overpaid` and keeps the actual paid amount.Fulfill and decide your refund or credit policy.
Unsupported asset / internal transferInvoice does not settle from the wrong asset class.Do not infer settlement from raw address activity alone.
Confirm settlement | PayChainHQ