Webhook
The Netsipp Webhook product POSTs call events to an address you choose, at the
moment they happen on the PBX. You do not have to poll us to avoid missing an
event; when something happens, we call you.
Every request represents a single event, and the scenario field in the body
tells you which one. The first thing your application should do is read that
field and branch to the right handler.
Request format
| Method | POST |
| Content type | application/json |
| Body | A single JSON object (not an array) |
| Expected response | 2xx |
Your endpoint is expected to answer with 2xx within 10 seconds. If the
response is late or the status code is anything other than 2xx, the request is
considered failed.
Answer the incoming request with 2xx immediately and queue the actual work.
Long operations in your webhook receiver (database queries, third party calls) do
not slow down the call flow itself, but they do slow down event delivery.
The numbers, queue names, call identifiers and links on these pages are not taken
from real traffic; they are representative values produced to show the format.
Because the scenarios are told through one single example call, the same
unique_id and PBX number repeat across pages.
Scenarios
The typical life cycle of a call runs in this order:
InboundtoPBX → Queue → Inbound_call → Answer → Hangup → cdr
Each scenario is documented on its own page, together with a sample body and field descriptions:
| Scenario | When it is sent |
|---|---|
InboundtoPBX | An external call reached the PBX |
Queue | The call entered a queue |
QueueLeave | The call left the queue |
Queue_Member_Pause | A queue member was paused or came back from a break |
Inbound_call | An inbound call was routed to an extension |
Answer | The call was answered |
Outbound_call | An extension started an outbound call |
Local_call | An extension called another extension |
DTMF | The caller pressed a key |
Context | The call entered an announcement or menu step |
Hangup | The call ended |
cdr | Call record summary (with the recording link) |
Common fields
The fields below carry the same meaning in most of the call based scenarios. The
cdr scenario does not use this schema; it has its own field names.
| Field | Type | Description |
|---|---|---|
scenario | string | Event name. Branch on this field. |
pbx_num | string | Your PBX number the event happened on. |
unique_id | string | Unique identifier of the call, e.g. sip1-1767225600.10001. Use it to correlate the events of the same call. |
customer_num | string | Subscriber number on the other side. The caller on an inbound call, the called party on an outbound call. |
internal_num | string | The extension involved in the event. |
incoming_number | string | Your number the call landed on (the dialed number). |
timestamp | string | Event time as a Unix epoch in milliseconds. |
Fields such as talktime, holdtime, digit and timestamp are sent inside
quotes in the JSON, that is as strings. Remember to convert them to numbers
while parsing. The cdr scenario is the exception; there the numeric fields
really are numbers.
Correlating events with unique_id
You receive more than one event for a single call. Use the unique_id field to
treat them as belonging to the same call:
InboundtoPBX unique_id: sip1-1767225600.10001
Queue unique_id: sip1-1767225600.10001
Inbound_call unique_id: sip1-1767225600.10001
Answer unique_id: sip1-1767225600.10001
Hangup unique_id: sip1-1767225600.10001
Queue_Member_Pause belongs to an agent rather than a call, so it does not carry
a unique_id. cdr sends its own identifier in the asteriskId field.
Things to watch out for
- Order is not guaranteed. Events are sent separately; depending on network
conditions the
Answerevent may reach you before theInbound_callevent. Judge the state by thetimestampfield. - The same event may arrive more than once. Write your handler so that
running it again produces no side effects (idempotent); you can use the
unique_id+scenariopair for duplicate detection. - The field list may grow. New fields may be added in the future. Ignore fields you do not know, and do not apply strict schema validation.
- Not every field is always present. Depending on the path the call takes, some fields may be missing; check for presence while reading a field.