Skip to main content

Webhooks

Webhooks let Konvoq push data to you the moment something happens — a new lead, a new conversation, a handoff request. Instead of polling "did anything happen?", Konvoq notifies you automatically.

Set up webhooks at Dashboard → Connect → Webhooks.


Setting up a webhook

  1. Go to Connect → Webhooks
  2. Click Add Webhook
  3. Enter a name and your endpoint URL — must be https://
  4. Select the events you want to subscribe to (or leave empty to receive all)
  5. Click Save — Konvoq immediately sends a test request to verify your endpoint responds

Available events

EventWhen it fires
lead.createdVisitor submits the lead capture form
lead.updatedLead data is edited
lead.stage_changedLead moves to a new CRM pipeline stage
lead.deletedLead is deleted
conversation.startedVisitor opens the chatbot
conversation.endedConversation is closed
conversation.handed_offConversation transferred to a human agent
message.receivedA new message arrives in a conversation
handoff.createdVisitor requests a human agent
handoff.assignedAgent picks up a handoff
handoff.resolvedAgent closes a handoff
knowledge.syncedA knowledge base re-index completes

Payload format

Every webhook request is an HTTP POST with a JSON body:

{
"id": "evt_abc123",
"type": "lead.created",
"occurredAt": "2025-04-23T10:00:00Z",
"payload": {
"id": "lead_xyz",
"name": "Jane Doe",
"email": "jane@example.com",
"pipeline_stage": "new",
"created_at": "2025-04-23T10:00:00Z"
}
}

The payload shape varies by event type. Use type to route to the right handler.


Request headers

Every webhook request includes these headers:

HeaderDescription
X-Konvoq-Event-IdUnique ID of this event delivery
X-Konvoq-Event-TypeEvent type string (e.g. lead.created)
X-Konvoq-TimestampUnix timestamp of delivery (seconds)
X-Konvoq-SignatureHMAC-SHA256 signature — sha256=<hex>

Verifying requests are from Konvoq

Every request includes an X-Konvoq-Signature header — an HMAC-SHA256 signature computed from timestamp + "." + body using your webhook's signing secret.

Always verify this signature before processing the payload.

// Node.js
const crypto = require('crypto');

function verifySignature(rawBody, headers, secret) {
const timestamp = headers['x-konvoq-timestamp'];
const signature = headers['x-konvoq-signature'];

const expected = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(timestamp + '.' + rawBody)
.digest('hex');

return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
# Python
import hmac, hashlib

def verify_signature(raw_body: bytes, headers: dict, secret: str) -> bool:
timestamp = headers.get('x-konvoq-timestamp', '')
signature = headers.get('x-konvoq-signature', '')
message = f"{timestamp}.{raw_body.decode('utf-8')}"
expected = 'sha256=' + hmac.new(
secret.encode(), message.encode(), hashlib.sha256
).hexdigest()
return hmac.compare_digest(signature, expected)

:::tip Use the raw body Compute the signature over the raw request body bytes, before any JSON parsing. Parsing and re-serializing can change whitespace and break the signature check. :::

The signing secret is shown when you create or view a webhook in the dashboard.


Retries

If your endpoint returns a non-2xx response (or times out), Konvoq retries with exponential backoff:

AttemptDelay
15 seconds
210 seconds
320 seconds
440 seconds
580 seconds
6160 seconds
7320 seconds
8 (final)— marked dead

Maximum 8 attempts total. After 8 failures, the event is marked dead and no further retries occur.

You can manually retry dead events from Connect → Webhooks → [webhook name] → View Events.

:::tip Respond fast, process later Return 200 OK immediately, then process the payload asynchronously. If your handler takes more than ~30 seconds, Konvoq treats it as a failure and retries. :::


Delivery log

Every delivery attempt is logged. View them at Connect → Webhooks → [webhook name] → View Events.

Each log entry shows:

  • Event type and ID
  • Delivery status (delivered, retrying, dead)
  • HTTP response status from your endpoint
  • Error message (if failed)
  • Timestamp of each attempt

Testing your webhook

Click Test on any webhook to send a sample lead.created payload immediately — useful for verifying your endpoint and signature logic before going live.


Disabling a webhook

Toggle a webhook inactive from the webhook list. Events still fire internally but are not delivered until you re-enable it. All queued events are discarded when a webhook is disabled.