Event ids are derived from the underlying resource ids (ledger entry, reservation, member), so idempotent request replays re-deliver events with the same CloudEvent
source + id. Receivers deduplicate on that pair, as the spec requires.
Enabling delivery
Set environment variables before starting the server:Subscriptions can also be added, deleted, and rotated at runtime from the Admin API view. Runtime subscriptions persist in SQLite and take precedence over boot-time environment configuration after their first write. Signing secrets are write-only in Admin responses — the local reference runtime stores them in its protected SQLite database; production adapters should use envelope encryption or an external secret manager.
platform.webhooks exposes the dispatcher, including flush() to await the current retry cycle, pendingDeliveries() for the durable queue, and deliveries() for recent process-local delivery results.
Delivery semantics
- Each event is POSTed as JSON with
LIP-Webhook-TimestampandLIP-Webhook-Signature: v1=<base64url>headers. - Failed deliveries (network errors or non-2xx responses) are retried with exponential backoff, three attempts per process run by default.
- Pending deliveries are stored in SQLite under a separate webhook-outbox state key. A normal server restart reloads and retries them; successful 2xx deliveries are removed.
--resetclears both loyalty state and the outbox. - Delivery is at-least-once. Receivers must verify the signature over the raw body and deduplicate using CloudEvent
source+id. - Receivers can verify with the SDK’s
verifyWebhook— see the TypeScript SDK guide.
Operator visibility
The Admin dashboard’s Developer view manages persisted receivers and secret rotation, shows pending outbox entries, retry attempts, last errors, and durable completed outcomes, and can immediately retry pending deliveries or replay a completed event. Deleting a receiver also removes its pending deliveries. Completed history and event payloads are retained in SQLite up to the configured history limit. Programmatic and Admin API subscription writes may set aretry_policy:
Omitted values use the server defaults.
Cutover health probe
Authenticated Admin clients can poll a secret-free summary — useful before unfreezing a migration cutover:enabled, pending outbox count, recent delivered/failed counts, success_rate, and healthy (true when webhooks are enabled, the outbox is empty, and no retained recent delivery failed).
The normative signing and replay-protection rules live in
spec/webhooks.md in the repository.TypeScript SDK
Verify signatures with
verifyWebhook.Migration
Use the health probe during a zero-loss cutover.