OpenPoly logo
Webhooks

Overview

Overview of the OpenPoly webhook delivery model.

Overview

OpenPoly webhooks notify operator backend after business state already committed.

Delivery model

  1. OpenPoly business flow commits DB state.
  2. OpenPoly writes outbox event.
  3. Dispatcher creates per-endpoint delivery records.
  4. Dispatcher signs raw JSON payload and sends POST request.
  5. Operator receiver verifies signature, deduplicates event_id, then processes event.

Webhook send is not part of a wallet mutation or trade/ticket transaction. Delivery, retry, and replay never authorize another debit, credit, or reversal.

Opinion and Polyflight use the same signed snake_case envelope and event_id idempotency boundary. Polyflight's data is camelCase; stakeMinor, feeMinor, netStakeMinor, and potentialPayoutMinor are the immutable purchase snapshot, while amountMinor on payout/refund events describes the owed or confirmed credit according to event type and status. A full refund or debit compensation reverses the stake and is not another fee.

Important guarantees

  • business state does not roll back if webhook delivery fails
  • same outbox event can produce multiple delivery attempts
  • replay creates another delivery attempt for same event
  • disabled endpoint receives no new deliveries
  • dead-letter delivery stays visible for operator review and replay

What receiver must do

  • read raw request body
  • verify X-Polynion-Signature
  • reject stale timestamp
  • dedupe by event_id in the same durable transaction as business handling
  • return 2xx only after durable processing, including when the event_id was already committed

Never sign or verify a dashboard JSON preview: it is reconstructed event data, not the original signed request bytes. The receiver must verify the raw bytes actually received.

State model

Outbox event statuses:

  • pending
  • dispatching
  • dispatched
  • failed
  • dead_letter

Delivery statuses:

  • pending
  • sent
  • failed
  • dead_letter

Delivery boundaries

  • 2xx -> delivery marked sent
  • 410 -> delivery marked dead_letter immediately
  • other non-2xx -> retry until max attempts, then dead_letter
  • timeout/network/DNS/TLS failure -> retry until max attempts, then dead_letter

Where operators configure webhooks

Copyright © 2026