Skip to main content

Reconciliation

Notifications can be missed — a webhook endpoint is down past the retry window, a callback never fires because the customer closed the tab. Reconciliation is the safety net that guarantees every payment eventually reaches the right end state on your side, without a human chasing it.

The whole approach rests on one property: verify is idempotent and always returns the current authoritative state, including a harmless PENDING for payments that have not resolved yet. That makes it safe to call verify as often as you like.

The pattern

  1. Store paymentUid at creation. It is your correlation key for the callback, the webhook, and verify — persist it against your order immediately.
  2. Deduplicate triggers by paymentId. Webhook delivery is at-least-once; if you have already processed a terminal status for a payment, acknowledge with 200 and do nothing.
  3. Fulfil only from a verified outcome. On any trigger, call verify and act on its status — never on the callback or webhook payload.
  4. Sweep unresolved payments. Run a periodic job that calls verify for every payment still unresolved on your side after its deadline (createdAt + timeoutSeconds, i.e. past expiresAt). A missed webhook can then never strand an order.

Which statuses to act on

Verified statusAction
SUCCESS, ACCEPTABLEFulfil the order.
MISMATCHHold for manual review — check deviationUsd.
EXPIREDCancel the order.
PENDINGNot resolved yet — leave it; the sweep will pick it up on a later pass.

Do not auto-fulfil PENDING, MISMATCH, or EXPIRED.

Notes

  • Verifying quiets a still-pending webhook — if your sweep verifies first, Finomesh skips the now-redundant webhook. The two channels self-dedupe.
  • A reasonable sweep cadence is every few minutes over payments created in the last day that you have not yet marked resolved. Tune to your volume.
  • If a customer insists they paid but the payment is still PENDING well past its expiry, you can hand us their transaction hash directly — see Submit transaction inquiry. It's a support escalation, not part of the sweep: attempts are limited and each one drives live chain lookups.