Converse Logo
Developers

Webhooks

Get notified in real-time when events happen — calls complete, agents escalate, campaigns finish.

Setup

Configure webhooks in Settings → Webhooks or via the API:

typescript
// Register a webhook endpoint
await fetch('https://api.converse.axllabs.in/v2/webhooks', {
  method: 'POST',
  headers: { 'Authorization': 'Bearer sk_live_...', 'Content-Type': 'application/json' },
  body: JSON.stringify({
    url: 'https://your-app.com/webhooks/converse',
    events: ['call.completed', 'call.escalated', 'campaign.completed'],
    secret: 'whsec_your_signing_secret',
  }),
});

Event Types

call.started

A new call session began (inbound or outbound).

call.completed

Call finished. Includes transcript, summary, sentiment, duration, engagement score.

call.escalated

Agent determined human intervention is needed.

call.answered

Outbound call was answered by the contact.

call.no_answer

Outbound call was not answered.

call.voicemail

Voicemail detected (if AMD enabled).

call.failed

Call failed (network error, provider issue, timeout).

transcript.final

Final transcript segment available (real-time).

tool.called

Agent invoked a tool during the call.

campaign.started

Campaign transitioned to running state.

campaign.paused

Campaign was paused (manual or auto-pause due to low health).

campaign.completed

Campaign finished all contacts or reached its goal.

campaign.cancelled

Campaign was cancelled.

contact.interested

Contact scored 70+ (high engagement). Includes score and summary.

contact.not_interested

Contact scored below 40. Marked as not interested.

contact.callback_requested

Contact asked to be called back later.

contact.dnc

Contact requested Do Not Call. Auto-added to DNC list.

score.updated

Engagement score changed for a contact. Includes new score and factors.

goal.reached

Campaign reached its configured goal target.

health.low

Campaign health score dropped below threshold.

budget.warning

Campaign has used 80%+ of its budget cap.

budget.exhausted

Campaign budget exhausted. Auto-paused.

agent.published

An agent was published (configuration changed).

channel.connected

A phone number or WhatsApp was successfully connected.

Payload Format

All webhook payloads follow the CloudEvents specification:

json
{
  "id": "evt_abc123",
  "type": "call.completed",
  "created_at": "2026-07-01T10:30:00.000Z",
  "data": {
    "call_id": "call_xyz",
    "agent_id": "agent_abc",
    "channel": "voice",
    "direction": "inbound",
    "duration_ms": 45000,
    "from_number": "+919876543210",
    "summary": "Customer inquired about order #4521 delivery status. Resolved.",
    "sentiment_score": 0.8,
    "sentiment_label": "positive",
    "resolution": "resolved",
    "transcript": [
      {"role": "assistant", "content": "Hello! How can I help?"},
      {"role": "user", "content": "Where is my order?"},
      {"role": "assistant", "content": "Order #4521 is out for delivery..."}
    ]
  }
}

Security — Signature Verification

Every webhook includes an X-Converse-Signature header containing an HMAC-SHA256 signature. Always verify this to ensure the request came from Converse.

Node.js / Express

typescript
import { verifyWebhookSignature } from '@converse/sdk/webhook';

app.post('/webhooks/converse', express.raw({type: 'application/json'}), (req, res) => {
  const isValid = verifyWebhookSignature(
    req.body,
    req.headers['x-converse-signature'],
    process.env.WEBHOOK_SECRET!,
  );
  if (!isValid) return res.status(401).send('Invalid');
  // Process event...
  res.status(200).send('ok');
});

Python / FastAPI

python
import hmac, hashlib
from fastapi import FastAPI, Request, HTTPException

app = FastAPI()
WEBHOOK_SECRET = "whsec_..."

@app.post("/webhooks/converse")
async def handle_webhook(request: Request):
    body = await request.body()
    signature = request.headers.get("x-converse-signature", "")

    expected = "sha256=" + hmac.new(
        WEBHOOK_SECRET.encode(), body, hashlib.sha256
    ).hexdigest()

    if not hmac.compare_digest(signature, expected):
        raise HTTPException(status_code=401)

    event = await request.json()
    print(f"Event: {event['type']}", event['data'])
    return {"status": "ok"}

Retry Policy

Testing

Use the webhook test button in your dashboard, or the CLI:

bash
# Send a test event to your endpoint
curl -X POST https://api.converse.axllabs.in/v2/webhooks/test \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{"webhook_id": "wh_abc", "event_type": "call.completed"}'