Skip to Content
ReferenceWebhooks

Webhooks

Webhooks are how Omniflow tells your systems about things that happened — a conversation resolved, a ticket was created, a scorecard was scored. They’re HTTP POSTs with a JSON body and an HMAC signature header.

Event catalog

EventTriggered when
conversation.createdA new conversation lands in the inbox.
conversation.message_addedA new message is sent or received on a conversation.
conversation.resolvedA conversation is marked resolved.
conversation.reopenedA resolved conversation gets a new reply.
ticket.createdA new ticket is opened.
ticket.updatedA ticket’s status, priority, or assignee changes.
ticket.resolvedA ticket is resolved.
ticket.mergedOne ticket is merged into another.
contact.createdA new contact is created.
contact.updatedA contact’s data changes.
scorecard.createdThe QA grader scores a conversation.
scorecard.overriddenA coach overrides an AI score.
agent.publishedAn AI agent config is published.
agent.failedAn AI agent failed at runtime (failover triggered).
training_attempt.completedA trainee finishes a practice call.
training_attempt.reviewedA coach reviews an attempt.
automation.triggeredA routing or notification rule fired.
sla.breach_imminentAn SLA target is within 30 minutes of breach.
sla.breachedAn SLA target was breached.

Payload shape

Every payload has a stable envelope:

{ "id": "evt_a1b2", "type": "conversation.resolved", "created_at": "2026-05-01T14:30:00Z", "workspace_id": "ws_demo", "data": { ... event-specific ... } }

data is the resource at the moment of the event. Nested resources are included by reference (contact_id) — fetch with the API if you need details.

Headers

HeaderNotes
Content-Typeapplication/json.
X-Omniflow-EventThe event type (conversation.resolved).
X-Omniflow-SignatureHMAC-SHA256 of the body, hex-encoded.
X-Omniflow-TimestampUnix seconds; reject if more than 5 minutes off.
X-Omniflow-DeliveryUUID for this delivery attempt; same per retry.

Signature verification

import crypto from 'node:crypto' function verify(req: Request, secret: string): boolean { const signature = req.headers.get('x-omniflow-signature')! const timestamp = req.headers.get('x-omniflow-timestamp')! const body = await req.text() // Reject stale deliveries const skew = Math.abs(Date.now() / 1000 - parseInt(timestamp, 10)) if (skew > 300) return false const expected = crypto .createHmac('sha256', secret) .update(`${timestamp}.${body}`) .digest('hex') return crypto.timingSafeEqual( Buffer.from(expected), Buffer.from(signature) ) }

Always verify the signature. Don’t trust the source IP — IPs change and aren’t authentication. The signature + timestamp combo is what proves the request is from Omniflow.

Delivery semantics

  • At-least-once. Your endpoint must be idempotent on id. Two deliveries of evt_a1b2 should produce one outcome.
  • Ordered per resource. Events for the same conversation_id arrive in order; events across resources can interleave.
  • Retries. Failed deliveries (non-2xx response or timeout) retry with exponential backoff up to 24 hours: 30s, 1m, 5m, 30m, 2h, 6h, 24h.
  • Backoff on sustained failure. After 24h of failure, the delivery is dropped and the endpoint is flagged in the dashboard.
  • Timeout. Omniflow waits 8 seconds for a response; longer is treated as a failure.

Best practices for handlers

  • Return 2xx fast. Acknowledge in <1s; do work in a background queue.
  • Idempotency. Dedupe on the event id.
  • Replay-safety. Treat each event as an upsert — re-running shouldn’t break state.
  • Schema flexibility. Omniflow may add fields; ignore unknown fields gracefully.

Replay

Failed deliveries can be replayed manually:

  1. Settings → Integrations → Webhooks → Deliveries.
  2. Filter by failed.
  3. Click Replay on individual deliveries or Replay all.

Test endpoint

For development:

  1. Create a webhook subscription pointing to a tunneling tool (ngrok, cloudflared).
  2. Trigger events from Omniflow (resolve a conversation, create a ticket).
  3. Inspect the request locally.

Disable a webhook

Toggle off in Settings → Integrations → Webhooks. Disabling preserves the subscription and history but stops new deliveries until re-enabled.

Open in Omniflow

If you want to…Go to
Use the APIAPI Reference
Receive Slack notifications insteadNotifications
Build a custom inbound integrationCustom API & Webhooks