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)
lead.capturedcollect_lead skill captures a new lead
lead.qualifiedsdr_lead_qualifier skill completes qualification
knowledge.gap_detectedQuery returned with low confidence
channel.errorA channel's webhook delivery or auth fails repeatedly
payment.succeededRazorpay or Stripe payment success (subscription product)
subscription.cancelledCustomer cancels subscription
sentiment.threshold_crossedsentiment_router skill triggers
custom_webhook.triggeredcustom_webhook skill fires

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

Configure a webhook endpoint

Under Dashboard > Webhooks > Add Endpoint:

  1. URL. Where AskVault POSTs. HTTPS only.
  2. Events. Pick the events you want to subscribe to. Subscribe only to what you'll act on; noisy subscriptions burn quota.
  3. Authentication. HMAC signature (recommended) or Bearer token in the Authorization header.
  4. Active toggle. Disable temporarily without deleting.

Click Save. AskVault sends a test event to verify your endpoint responds with 200.

Payload format

Every event POST looks like:

{
"event": "lead.captured",
"workspace_id": "wt_xxx",
"timestamp": "2026-05-15T13:42:11.123Z",
"data": {
"lead_id": "lead_xxx",
"email": "jane@example.com",
"name": "Jane Doe",
"phone": "+1 555 0100",
"source_channel": "widget",
"source_url": "https://acme.co/pricing",
"conversation_id": "conv_xxx",
"captured_at": "2026-05-15T13:42:10.987Z"
},
"delivery_id": "del_xxx"
}

Common fields across all events:

  • event. The event name (matches the table above).
  • workspace_id. Which workspace it belongs to.
  • timestamp. When the event fired (ISO 8601).
  • data. Event-specific payload.
  • delivery_id. Unique ID for this delivery attempt. Use for idempotency.

HMAC signature

AskVault signs every webhook with HMAC-SHA256:

X-AskVault-Signature: sha256=hexdigest_here
X-AskVault-Timestamp: 1747353600

Verify on your end:

import { createHmac, timingSafeEqual } from 'crypto';
function verifyWebhook(body, signature, secret) {
const expected = 'sha256=' + createHmac('sha256', secret)
.update(body)
.digest('hex');
return timingSafeEqual(Buffer.from(expected), Buffer.from(signature));
}
import hmac, hashlib
def verify_webhook(body: bytes, signature: str, secret: str) -> bool:
expected = 'sha256=' + hmac.new(secret.encode(), body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, signature)

The signing secret is per-endpoint. Generate or rotate it under Dashboard > Webhooks > [endpoint] > Signing Secret.

Retry policy

Failed deliveries (status >= 400 or timeout) retry on an exponential backoff schedule:

  • Attempt 1: immediately.
  • Attempt 2: after 30 seconds.
  • Attempt 3: after 2 minutes.
  • Attempt 4: after 10 minutes.
  • Attempt 5: after 1 hour.

After 5 failed attempts, the delivery enters the failed-deliveries log under Dashboard > Webhooks > [endpoint] > Failed Deliveries. You can manually retry from the dashboard.

A delivery is considered successful when your endpoint returns HTTP 2xx within 10 seconds.

Idempotency

Use the delivery_id field for idempotency. Store the IDs you've processed; reject duplicates on retry.

Common pattern: maintain a Redis or Postgres table of processed delivery_ids with a 7-day TTL. On every webhook POST:

  1. Read body, verify signature, parse JSON.
  2. Check if delivery_id is in your processed set.
  3. If yes, return 200 (ack) without re-processing.
  4. If no, process the event, then add delivery_id to the set.
  5. Return 200.

Without idempotency you risk processing the same event twice if AskVault retries (e.g., because your endpoint returned 200 but the response was lost in transit).

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

Every delivery (success or failure) appears in the log:

  • Dashboard > Webhooks > [endpoint] > Deliveries.
  • Search by date, event type, or status.
  • Inspect the exact request body sent and your endpoint's response.
  • Manually retry failed deliveries.

The log retains the last 30 days by default; configurable up to 1 year on Business and Enterprise. Business+

Limits

  • Plan availability. Webhooks are on every paid plan. Free plan can configure them for testing but events are rate-limited to 10 per day.
  • Throughput. AskVault delivers up to 100 events per second per endpoint. Above that, events queue and deliver in order.
  • Body size. Up to 1 MB per event.
  • Endpoint count. Up to 10 endpoints per workspace on Growth, 50 on Business.

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. The retry policy backs off but you'll still see many retries in the first hour. Fix the handler quickly to break the loop.

Wrong workspace in payload. Multi-workspace endpoints need to inspect workspace_id in every payload. Don't assume one endpoint = one workspace.

FAQ

Can I filter events to specific workspaces?

Yes. Each endpoint is bound to a single workspace. To handle multiple workspaces, configure one endpoint per workspace, OR use the org-level webhook endpoint (Enterprise only) that includes events from all workspaces under one account.

Are webhook events idempotent on the AskVault side?

We send each delivery_id at most once successfully. If your endpoint times out and we retry, you might see the same delivery_id twice with different timestamp values. Always dedupe on delivery_id.

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. AskVault's webhook test button under Dashboard > Webhooks > [endpoint] > Test sends a sample event you can iterate against.

Will I get charged for webhook deliveries?

No. Webhook deliveries don't count against your monthly query quota. They're free.

What happens to webhooks when I downgrade plans?

If your endpoint count exceeds the lower plan's cap, endpoints beyond the cap are paused (not deleted). They re-activate if you upgrade back.

Was this page helpful?