Webhook contract
When your tenant registers a webhook_url on a campaign or integration, CallingEdge POSTs a CallEvent to that URL on every state change.
Headers
Section titled “Headers”| Header | Meaning |
|---|---|
Content-Type | application/json |
X-CallingEdge-Signature | sha256=<hex> HMAC of the raw body using your shared secret |
X-CallingEdge-Provider | Platform integration key (e.g. cisco-webex-cc) |
X-CallingEdge-Event-Id | Idempotency key, safe to dedupe on |
Compute the signature with:
import hmac, hashlibsig = hmac.new(secret.encode(), body, hashlib.sha256).hexdigest()# compare against the value after "sha256=" in X-CallingEdge-Signature{ "provider": "cisco-webex-cc", "kind": "answered", "call_id": "T-abc123", "direction": "outbound", "from": "+16505824074", "to": "+18005551234", "context": { "tenant_id": "tnt_pure_roofing", "campaign_id": "cmp_spring_outbound", "contact_id": "ctc_001", "intent": "follow_up_qualified", "merge_fields": { "first_name": "Sam" } }, "duration_sec": null, "disposition": null, "recording_url": null, "transcript_url": null, "raw": { "...": "vendor payload, untouched" }, "occurred_at": "2026-05-20T17:31:04Z"}Event kinds
Section titled “Event kinds”| Kind | When |
|---|---|
placed | Outbound call accepted by the upstream platform |
inbound_ringing | Inbound call arrived at the platform |
answered | A human or AI agent answered |
voicemail | Detected voicemail / answering machine |
no_answer | Rang out |
busy | Line busy |
transferred | Call handed to a new destination |
ended | Call complete; check disposition, duration_sec, recording_url |
error | Upstream returned an error condition |
Reliability
Section titled “Reliability”- We retry failed deliveries with exponential backoff for up to 24 hours.
- Use
X-CallingEdge-Event-Idfor idempotency. The same event may be delivered more than once. - A 2xx response (including 204) is treated as acknowledged. Any 4xx or 5xx triggers retry.