⌘K

Integration GuidesGuide

Webhooks & event reconciliation

Receiving, verifying, deduplicating and reconciling signed event deliveries.

On this page

Event catalog and envelope

Event types: order.created, order.updated, order.cancelled, specimen.updated, result.partial, result.final, result.corrected, result.critical, integration.action_required. Envelope fields: event_id, type, version (currently 1), occurred_at, environment, program_id, data.

data carries only allow-listed identifiers and coarse state: order_id, external_order_id, program_id, client_id, environment, lifecycle, next_action, specimen_state, result_id, result_version, result_provenance, result_is_critical, action_required_code, links.

Signing and timestamps

  • x-solia-signature: v1=<hex HMAC-SHA256> over <x-solia-timestamp>.<raw body>.
  • Reject timestamps more than 300 seconds from your clock.
  • Verify against the exact raw bytes before JSON parsing; compare in constant time.

Replay protection and deduplication

  • Store processed x-solia-delivery-id values and ignore repeats.
  • Make processing idempotent on x-solia-event-id / event_id; the same event can arrive more than once.

Delivery semantics and retries

  • Delivery is at-least-once and may be out of order.
  • Request timeout: 10 seconds. Respond 2xx fast and process asynchronously.
  • Retry schedule: 1m, 5m, 30m, 2h, 12h, 24h; at most 7 attempts. Retry-After is honoured up to 60 minutes.
  • Timeouts, network errors, 408, 409, 425, 429 and 5xx retry; other 4xx are permanent. A blocked (non-public) destination is never sent.
  • Exhausted deliveries are dead-lettered, stay visible in delivery logs and can be replayed as a new auditable attempt.

Reconciliation

GET /v1/events is cursor-paged and ordered. Events are retained for 30 days, so reconcile well inside that window. After a gap, page from your last stored cursor, then re-read orders and results — the API, not the event, is authoritative.

Sandbox testing

  • Use Send test event in the Control Plane to prove reachability and signing.
  • Use the webhook_failure_then_replay scenario to rehearse a failed delivery and replay.
  • Return a 5xx from your endpoint deliberately to observe the retry path in delivery logs.

Production recommendations

  • Deploy the new signing secret before rotating; rotation invalidates the old secret immediately.
  • Alert on repeated signature failures and on growth in your unprocessed-event queue.
  • Run a scheduled reconciliation against GET /v1/events even when webhooks look healthy.

Related resources