Skip to content
Try Free →

Outbound webhooks from AskVault

Last updated: · 5 min read

Event list

AskVault POSTs to your endpoint when these events happen:

EventWhen it fires
conversation.startedNew conversation begins on any channel
conversation.escalatedescalate_to_human skill fires
conversation.resolvedConversation marked as resolved (auto or by agent)
conversation.feedbackA visitor leaves thumbs-up / thumbs-down feedback on a message
message.createdAny assistant or human-agent message is sent in a conversation
lead.capturedcollect_lead skill captures a new lead
agent.action_triggeredA teammate triggers an action from the Help Desk Actions menu (Issue Refund, Create Support Ticket, Send Follow-up Email, Escalate to Manager). The action slug is in both action and data.action_id; use the endpoint's optional action filter to receive only the slugs you handle
knowledge.gap_detectedAuto-train records a new knowledge-gap suggestion: a question asked at least twice in the last 14 days that your agent couldn't answer well. Fires once per new suggestion, only for workspaces with auto-train set to Suggest or Auto, never per individual low-confidence answer. Its fields are top-level (no data object); see Knowledge gaps
knowledge.sync_completedA crawl or scheduled re-sync finished indexing. Payload carries indexed / failed / retrying page counts
knowledge.sync_failedA crawl or integration sync failed permanently (transient retries are not reported)

The exact event payload schema for each is documented in their respective skill or feature page.

Automation rule notifications (conversation.notify)

When an Autopilot automation rule with the action Send notification → Webhook fires on a conversation, AskVault sends conversation.notify to every enabled endpoint in that workspace that is subscribed to it. Endpoints that are not subscribed, and endpoints in your other workspaces, never receive it. The rule does not pick an endpoint. To receive these notifications, tick Automation Rule Notification on the endpoint(s) you want. It is signed like every other event.

{
"event": "conversation.notify",
"timestamp": "2026-10-03T09:12:44.512Z",
"data": {
"conversation_id": "conv_xxx",
"rule_id": "rule_xxx",
"rule_name": "Refund keyword alert",
"reason": "Customer mentioned a refund",
"channel": "webhook"
}
}

reason is the rule's optional note, or null when the rule has none.

There is no billing webhook (payment.succeeded, subscription.cancelled) on this endpoint: those are events AskVault receives from the payment gateway, not events it sends to you. There is also no channel.error or sentiment.threshold_crossed event; for channel health use Channels, and for sentiment escalation subscribe to conversation.escalated.

Configure a webhook endpoint

Add endpoints on the Webhooks page (Add Endpoint):

  1. URL. Where AskVault sends events. HTTPS only.
  2. Events. Tick only the events you will act on.
  3. Active toggle. Pause an endpoint without deleting it.

AskVault creates a signing secret for every endpoint when you save it. To check the endpoint works, press Test, which sends a sample payload for an event of your choice and shows your server's response.

Payload format

Every event is a JSON POST shaped like this:

{
"event": "lead.captured",
"timestamp": "2026-05-15T13:42:11.123Z",
"data": {
"lead_id": "lead_xxx",
"email": "[email protected]",
"name": "Jane Doe",
"source": "ai_skill",
"conversation_id": "conv_xxx"
}
}
  • event. The event name from the table above.
  • timestamp. When the event fired, in ISO 8601.
  • data. The event's own fields. Exception: knowledge.gap_detected sends its fields at the top level, with no data object.

Delivery details travel in headers, not the body:

HeaderMeaning
X-AskVault-DeliveryUnique delivery id, repeated on retries. Use it to drop duplicates.
X-AskVault-EventThe event name, handy for routing before you parse.
X-AskVault-Signaturesha256= plus the hex HMAC.
X-AskVault-TimestampUnix time used in the signature.

HMAC signature

Every delivery to your own endpoint is signed with HMAC-SHA256 using the endpoint's secret. Deliveries to Slack or Discord incoming-webhook URLs are reformatted as messages for that service and are not signed. The signed string is the X-AskVault-Timestamp value, a dot, then the raw request body:

import { createHmac, timingSafeEqual } from 'node:crypto';
function verifyWebhook(rawBody, signature, timestamp, secret) {
const expected = 'sha256=' + createHmac('sha256', secret)
.update(`${timestamp}.`)
.update(rawBody)
.digest('hex');
const a = Buffer.from(expected);
const b = Buffer.from(signature || '');
return a.length === b.length && timingSafeEqual(a, b);
}
import hmac, hashlib
def verify_webhook(raw_body: bytes, signature: str, timestamp: str, secret: str) -> bool:
expected = hmac.new(
secret.encode(), f"{timestamp}.".encode() + raw_body, hashlib.sha256
).hexdigest()
return hmac.compare_digest(f"sha256={expected}", signature)

To guard against replays, also reject timestamps more than a few minutes old. Rotate the secret from the endpoint's menu on the Webhooks page; the old secret stops working straight away.

Retry policy

AskVault retries a delivery when your endpoint returns a 5xx status, the connection times out or the connection fails, up to 3 attempts in total, with the pause between attempts doubling and capped at 30 seconds. Each attempt waits up to 10 seconds for a response.

A 4xx response is treated as final and is not retried, and neither is 410 Gone. A delivery counts as successful on any 2xx.

Every attempt is recorded in the endpoint's delivery log, and you can resend a failed delivery from there.

Idempotency

Retries can deliver the same event more than once, for example when your server processed it but the response was lost. Deduplicate on the X-AskVault-Delivery header:

  1. Read the raw body and verify the signature.
  2. If the delivery id is already in your processed set, return 200 and stop.
  3. Otherwise process the event, store the id, and return 200.

A table of processed ids with a 7-day expiry is plenty.

Performance

Your endpoint should return 200 within 10 seconds. Faster is better. For slow downstream work:

  • Pattern 1: ack-then-process. Return 200 immediately, then process async in your worker queue.
  • Pattern 2: fast inline. Process the event inline if it takes under 1 second.

Avoid keeping AskVault's TCP connection open for 8+ seconds. We don't pipeline webhook deliveries to the same endpoint, so a slow handler blocks subsequent events.

Delivery log

Each endpoint has a delivery log on the Webhooks page showing every attempt with its event, status code and response. Use it to debug failures and to resend a delivery.

Limits

  • Plan availability. Outbound webhooks need the Growth plan or above.
  • Timeout. 10 seconds per attempt.
  • Attempts. Up to 3 per delivery, on 5xx, timeout or connection failure.

Common pitfalls

Endpoint returns 200 but I never see events arrive. Your endpoint is being called but the request body parsing is silently failing. Add explicit JSON parse error handling.

Signatures fail intermittently. You're computing HMAC over a parsed (not raw) body, and JSON.stringify ordering differs from what AskVault signed. Always sign the raw bytes, not the parsed object.

Retries flood my endpoint. A bug in your handler keeps returning 500, so every event is tried 3 times. Fix the handler, or return a 4xx for events you never want resent.

Events from the wrong workspace. Each endpoint belongs to one workspace. If you reuse one URL across workspaces, use a different path or query string per workspace so you can tell them apart.

FAQ

Can I filter events to specific workspaces?

Each endpoint belongs to a single workspace. For several workspaces, add an endpoint in each one.

Are webhook events idempotent on the AskVault side?

No. If your endpoint times out after processing an event, the retry delivers it again with the same X-AskVault-Delivery id. Always dedupe on that header.

How do I test webhooks during development?

Use a tool like ngrok or smee.io to expose your local endpoint, then configure the webhook URL to point at it. The Test button on the endpoint sends a sample event you can iterate against.

Will I get charged for webhook deliveries?

No. Webhook deliveries do not use message credits.

What happens to webhooks when I downgrade plans?

Your endpoints are kept, but you can no longer add or edit them below Growth. Stopping deliveries on a plan without webhooks is rolling out; once it is on, delivery resumes automatically if you upgrade again, with nothing to reconfigure.

Was this page helpful?