Hybrid SIP Trunk webhooks
Hybrid SIP Trunk webhooks tell you about calls and registrations on a trunk in real time. They are the most flexible webhooks on the platform: you choose exactly which events to receive, can send them straight to a chat app, can send a test message, and can see a full delivery history.
Where to set it up
For one trunk
- Go to Products > SIP Trunks (Hybrid) > Manage Trunks and open the trunk you want to manage.
- In the settings menu, choose Webhooks.
- Click Configure webhook.
- Turn on Enable webhook for this trunk.
- Paste your address into Webhook URL. It must start with
https://. - Choose which events you want under Event types.
- Fill in any optional settings (see below).
- Click Save webhook.
- Click Send test ping to check everything is working.
Each trunk has one webhook subscription.
See all trunk webhooks on your account
Go to Products > SIP Trunks (Hybrid) > Webhooks. The Trunk Webhooks page lists every trunk with a webhook, showing its status, format, destination, events and last delivery. You can search, filter by Enabled, Disabled or Circuit open, and click Manage to edit a trunk's webhook.
Send to a chat app or your own system
Paste a chat app webhook URL and Crazytel detects it automatically and sends a nicely formatted message:
| Destination | How it is detected |
|---|---|
| Discord | A discord.com webhook URL |
| Slack | A hooks.slack.com URL |
| Microsoft Teams | A webhook.office.com URL |
| Google Chat | A chat.googleapis.com URL |
| JSON webhook (your own system) | Any other https:// address |
For chat apps, we recommend subscribing to Call hangup only, so your channel gets one tidy message per call rather than several. The Suggest chat events (hangup only) link sets this up for you.
Settings explained
| Setting | What it does |
|---|---|
| Enable webhook for this trunk | Turns delivery on or off without deleting your settings. |
| Webhook URL | Where events are sent. |
| Failover URL (optional) | A backup address used if your main URL cannot be reached. JSON webhooks only. |
| Signing secret | Used to sign each message so your system can confirm it came from Crazytel. Required for JSON webhooks, minimum 16 characters. Not used for chat apps. |
| Rotate secret | Creates a new signing secret. The new secret is shown once, so copy it straight away. |
| Custom auth header (optional) | An extra header added to every request, for example Authorization: Bearer your-app-token, if your system needs one. JSON webhooks only. |
| Include extra detail fields | Adds more technical call detail to JSON webhook messages. Does not affect chat app messages. |
| Event types | Which events you want to receive. |
When you first save a signing secret, it is shown once so you can copy it. After that it cannot be viewed again. If you lose it, use Rotate secret to create a new one, then update your system.
Events you can choose
Call events
| Event | Label in portal | When it is sent |
|---|---|---|
call.initiated | Call initiated | A call started being set up on the trunk. |
call.ringing | Call ringing | The other end is ringing. |
call.answered | Call answered | The call was answered. |
call.hangup | Call hangup | The call ended. Includes the call length when it was answered. |
call.hold | Call hold | The call was put on hold. |
call.unhold | Call unhold | The call was taken off hold. |
call.transfer | Call transfer | The call was transferred. |
call.forward | Call forward | The call was forwarded (busy, no answer or always forward). |
Recording events
| Event | Label in portal | When it is sent |
|---|---|---|
recording.started | Recording started | Call recording started. |
recording.failed | Recording failed | Call recording could not start, or stopped part-way through. |
Trunk events
| Event | Label in portal | When it is sent |
|---|---|---|
trunk.registered | Trunk registered | A phone or PBX registered to the trunk. |
trunk.deregistered | Trunk deregistered | A phone or PBX stopped being registered. The reason is included: it was removed, replaced by a newer registration, or expired. |
trunk.dnd_changed | DND changed | Do Not Disturb was turned on or off for the trunk. |
New webhooks start with Call initiated, Call answered and Call hangup selected.
Registration events are sent for each individual device registration, so a trunk with two registered phones produces two events.
Example message (JSON webhook)
{
"id": "evt_deadbeef001122334455667788",
"type": "call.hangup",
"api_version": "2026-07-18",
"created_at": "2026-07-18T10:16:00Z",
"account_code": "10036558",
"data": {
"call_id": "abc123@10.0.0.1",
"trunk_aor": "10036558",
"direction": "outbound",
"peer": "61412345678",
"did": null,
"destination": "61412345678",
"state": "ended",
"started_at": "2026-07-18T10:15:28Z",
"answered_at": "2026-07-18T10:15:30Z",
"ended_at": "2026-07-18T10:16:00Z",
"end_reason": "busy",
"sip_code": 486,
"duration_seconds": 30,
"recording": false
}
}
| Field | What it means |
|---|---|
id | A unique ID for this event. Use it to ignore duplicates. |
type | Which event this is. |
api_version | The message format version. |
created_at | When the event happened (UTC). |
data.call_id | A unique ID for the call. The same ID appears on every event for the call. |
data.trunk_aor | The trunk's SIP username. |
data.direction | inbound or outbound. |
data.peer | The other party's number. |
data.did | Your number that was called (inbound calls). |
data.destination | The number dialled. |
data.state | Where the call was up to, for example answered or ended. |
data.started_at / answered_at / ended_at | When each stage happened. |
data.end_reason | Why the call ended, for example busy. |
data.sip_code | The technical SIP result code, for example 200 (answered) or 486 (busy). |
data.duration_seconds | Call length in seconds (on hangup, when answered). |
data.recording | Whether the call was recorded. |
Click Webhook documentation on either the trunk Webhooks section or the Trunk Webhooks page to browse an example of every event, in every format, with a Copy JSON button.
Security (JSON webhooks)
Each JSON webhook includes these headers:
Content-Type: application/json
User-Agent: Crazytel-Hybrid-Webhooks/1.0
X-Hybrid-Timestamp: <time the message was sent, in Unix seconds>
X-Hybrid-Signature: <signature>
The Hybrid signature is calculated over the timestamp and the message body together. Reject messages where the timestamp is more than 5 minutes old. See Verifying webhook signatures.
Chat app messages are not signed. Chat apps secure their webhooks with the secret token built into the URL, so keep your chat webhook URL private.
Testing and delivery history
- Send test ping sends a
webhook.pingtest event to your URL. The portal waits and then shows whether it succeeded, for example "Test delivery succeeded (HTTP 200)". - The Webhook events tab shows every delivery attempt for the trunk over the last 14 days, including the time, event, HTTP result, any error, the attempt number and how long your server took to respond.
Delivery history is kept for 14 days. Your webhook settings are kept until you remove them.
"Delivery paused" and how to fix it
If your URL keeps failing, Crazytel pauses delivery to protect both systems. You will see a Delivery paused banner on the trunk's Webhooks section with the reason:
| Reason shown | What it means | What to do |
|---|---|---|
| Too many delivery failures | Your URL failed repeatedly, so delivery was paused. | Fix the problem with your URL or server, then click Clear circuit & save and Send test ping. |
| URL rejected or revoked | The destination refused the webhook or no longer accepts it. | Update the URL, then click Clear circuit & save. |
| Chat channel removed | The chat channel the webhook posted to was deleted. | Create a new channel webhook, paste its URL, then click Clear circuit & save. |
| Manually disabled | The webhook was turned off. | Turn on Enable webhook for this trunk and save. |
Delivery also resumes automatically after the pause period shown in the banner, or after a successful test ping.
Removing a webhook
Click Remove on the trunk's Webhooks section and confirm. Delivery history from the last 14 days is kept until it expires. You can set up a new webhook at any time.
Sub-logins and the Hybrid portal
If you give staff or customers their own login to a Hybrid trunk, you can control their webhook access with two permissions:
| Permission | What it allows |
|---|---|
| View webhooks & deliveries | See the webhook settings and delivery history for the trunk. |
| Configure / test webhooks | Create, edit, disable and test the trunk's webhook. |
Give both permissions to someone who needs to set up and monitor webhooks. Sub-logins only see the trunk they have access to. The account-wide Trunk Webhooks list is only available on the main account.
