Our systems can send webhooks in real-time to notify your chosen endpoint of call events as they happen.
Webhooks are POSTed to your http/https endpoint in JSON format. All data that is available in CDRs is also sent in webhooks.
A phone call will generate multiple webhooks as it progresses.
There are some fields which appear in every webhook. In addition to these, other fields are present depending on the type of call event/events the webhook is reporting.
Common fields:
tstamp (integer) - when the call event happened; number of seconds since the epoch (unix timestamp)tstamp_ms (integer)- when the call event happened; number of milliseconds since the epoch (higher resolution unix timestamp)uniqueID (string) - a unique string identifier for the call. All webhooks for the same call will have the same value in this field, allowing you to associate all webhooks for the same call together. The uniqueID value will be unique to this call.seq (integer) - sequence number for the webhook. The first webhook for a call will have a seq value of 1, the next one a seq value of 2, etc. This allows you to not only re-order any webhooks arriving out of order, but also allows you to identify duplicates that may result as a result of network timeouts causing re-tries (if configured).events (array of strings) - the events that this webhook is declaring
The events listed in the events field determine which other fields appear in the webhook.
Most of the calls we carry or generate consist of multiple call legs.
Event names and field names relating to a specific call leg will start legX_, where X is the leg number. For example, when leg 2 starts, an event leg2_start will be reported, and when that leg ends, its clear cause will be reported in the leg2_clearcause field (for a PSTN call) or leg2_sipcause for a SIP call.
No single webhook contains complete call data. For any individual call, each webhook sends a bit more information as events occur, filling in more pieces of the jigsaw. Your endpount needs to retain the interim data associated with the call (identified in every webhook by the uniqueID field) until all pieces of the jigsaw are sent.
The first thing to note is that a call generates many webhooks. Call webhooks are quite verbose. Information is there if you want it, and can be ignored if not.
The body payload for webhooks has no additional spacing or indentation. However, for readability in this document, the examples shown here are spaced and indented.
In this example, a caller on 01632758802 calls 01632754115. The called number (01632754115) is hosted by us and set to redirect to 01632272014. The following webhooks are sent to your endpoint:
{ "uniqueID":"1742502077.9328368_13",
"seq":1,
"tstamp":1742502078,
"tstamp_ms":1742502078046,
"events":["start", "leg1_start"],
"service":"nts",
"service_number":"01632754115",
"custID":22774",
"custIDpath":[22774],
"leg1_dni":"01632754115",
leg1_direction":"ingress",
"leg1_cli":"01632758802",
"leg1_transport":"pstn"
}
The above webhook is sent when the call starts. The caller has called a number that is hosted on our system. We have not yet initiated any call out to the eventual destination.
The fields in the webhook are as follows:
uniqueID - this is the uniqueID value that will be unique to this call, but appear in every webhook for this call.seq - as this is the first webhook for this call, it has the value of 1.tstamp - the unix timestamp identifying when the event happened. Unless there are connectivity issues, you will receive the webhook within a small fraction of a second of when it was generated.tstamp_ms - a higher resolution timestamp value, in milliseconds. You shouldn't rely on the absolute time being accurate to the millisecond (though it will be close), but more importantly it can be used to accurately determine relative durations between events in situations where this matters.events - declares what actually happened at this time:
start declares that this is the very start of this call and is always the starting event of any callleg1_start declares that leg 1 of the call has also started at this time. In practice, unless there are exceptional circumstances these events always happen together.service - identifies the service the call relates to (eg the type of call). service_number - the value of this field depends on the service the call falls under, but for NTS calls it is the same as the called number (see leg_dni below)custID - identifies the customer account in which the call lies; most of the time this will be your own account, but for resellers it could be a sub-account of your own. You can probably ignore this.custIDpath - if your customers are also resellers and the call happens in one of their accounts, this field will indicate the direct customer, any interim customers and the end user custtomer. You can probably ignore this.leg1_dni - dni (dialled number indicator) - for inbound (to our equipment) call legs, this shows the dialled number.leg1_direction - here, ingress declares that this call leg is inbound to our equipment (if outbound, it would be egress)leg1_cli - the caller number (assuming that they did't withhold their number)leg1_transport - pstn means that this call came in over the public phone network (the main alternative being sip for a call being sent to us over SIP (VoIP) directly over the Internet){
"uniqueID":"1742502077.9328368_13",
"seq":2,
"tstamp":1742502078,
"tstamp_ms":1742502078068,
"events":["leg2_start", "leg2_dial"],
"leg2_direction":"egress",
"leg2_transport":"pstn",
"leg2_desttype":"number",
"leg2_cli":"01632758802",
"leg2_dest":"01632272014"
}
To build a complete picture of the call, information in this webhook should be merged with that from the first one. The above webhook declares:
uniqueID - same value as the above webhook, so this is an update on the same call.seq - 2 - next webhook in the sequence for this call.events
leg2_start leg 2 of the call is being initiatedleg2_dial leg2 of the call is now dialling the ongoing destinationevents included leg2 start and dial events, the following fields about leg 2 were also sent:
leg2_direction - the value of egress means that we are sending the call outbound.leg2_transport - pstn means that we are sending this call out over the public phone network (eg not a SIP/VoIP destination)leg2_desttype - number means that we are sending this call to a phone number; leg2_cli - this shows the caller number that we're sending on the outbound leg, which is what the called party will see. Usually this will be the same as the calling number on the inbound leg, but there are some situations where this won't be the case depending on what has been configuredleg2_dest - shows the destination for this call leg; in the case of leg2_desttype being number, this is the phone number the call is going to{
"uniqueID":"1742502077.9328368_13",
"seq":3,
"tstamp":1742502078,
"tstamp_ms":1742502078837,
"events":["leg2_progress"]
}
Again, merge data with previous webhooks to build full data for the call; this should always be assumed. The above webhook declares:
events - leg2_progress means that we have received "progress" indication on leg 2 (the outbound leg). Usually this is synonimous with "ringing" indication but there are exceptions.{
"uniqueID":"1742502077.9328368_13",
"seq":4,
"tstamp":1742502078,
"tstamp_ms":1742502078844,
"events":["leg2_ringing"]
}
The above webhook declares:
events - leg2_ringing means that we have received "ringing" indication on leg 2 (the outbound leg), stating that the remote phone has started actually ringing. Often (but often not) both ringing and progress indication are received.{
"uniqueID":"1742502077.9328368_13",
"seq":5,
"tstamp":1742502083,
"tstamp_ms":1742502083874,
"events":["leg2_answer"]
}
The above webhook declares:
events - leg2_answer the call recipient for leg 2 (the outbound/egress leg in this example) has answered.{
"uniqueID":"1742502077.9328368_13",
"seq":6,
"tstamp":1742502083,
"tstamp_ms":1742502083874,
"events":["leg1_answer", "leg1_audio_connect", "leg2_audio_connect"]
}
The above webhook declares:
events:
leg1_answer - our system answered leg 1 (the inbound leg). This was because leg 2 has now been answered and the system wants to bridge the two legs together to connect the audio so that the caller can talk to the called party.leg1_audio_connect - leg 1 (the caller in this case) is having their audio connected to another legleg2_audio_connect - leg 2 (the called party in this case) is having their audio connected to another leg ... the caller. They can now hold a conversation.{
"uniqueID":"1742502077.9328368_13",
"seq":7,
"tstamp":1742502087,
"tstamp_ms":1742502087054,
"events":["leg2_end"],
"leg2_clearcause":16,
"leg2_disposition":"ANSWER"
}
The above webhook declares:
events - leg2_end the second leg of this call has been hung up; as this has happened before leg1_end, the called party hung up first.events includes leg2_end, the following fields are included:
leg2_clearcause - the clear cause of leg 2 when it ended Look up Q.850 cause codes for more information. In this instance, 16 means normal call clearing, ie no fault.leg2_disposition - a human readable status of the ended call leg.{
"uniqueID":"1742502077.9328368_13",
"seq":8,
"tstamp":1742502087,
"tstamp_ms":1742502087081,
"events":["leg1_end", "end"],
"leg1_clearcause":16,
"leg1_disposition":"ANSWER",
"leg1_disposition":"ANSWER"
}
The above webhook declares:
events
leg1_end - leg1 of the call has now ended. Although the caller may have hung up, it is most likely that leg 1 has been ended as a result of the called party (leg 2) hanging up and this hangup being passed through to the calling leg.end - an end event signifies the end of the call; this happens when there are no more active call legs.events includes leg1_end, the following fields are included:
leg1_clearcause - the clear cause of leg 2 when it ended.
leg1_disposition - a human readable status of the ended call leg.
events includes end, indicating the end of the call, the following field is included:
disposition - a human readable status of the call as a whole. Usually this is a duplicate of the disposition of the last outbound leg of a call.
These event types relate to the call as a whole and not to any specific leg.
These events are singular, ie for any given call each of these events can only happen once.
| Event Name | Singular | Description |
|---|---|---|
| start | Y | Start of the call. |
| end | Y | End of the call; all legs have ended. |
| callrec_ready | Y | The recording of the call (if enabled) is now available for download. This event will include the download URL |
Most of the reported events will refer to a specific call leg. These event names will start legX_ where X is the leg number. This can be seen in the above examples.
Some events may be repeated within the same call leg (eg legX_ivr_input) whereas other events are singular, ie they can only happen once for any given call leg.
| Event Name | Singular | Description |
|---|---|---|
| legX_start | Y | Signifies the start of this leg |
| legX_dial | N | Outbound legs only; the destination is being called |
| legX_progress | Y | Outbound legs only; we have received progress information (often in place of or as well as ringing) |
| legX_ringing | Y | Outbound legs only; we have received ringing indication; the remote end is ringing |
| legX_answer | Y | The leg has been answered |
| legX_audio_connect | Y | Audio from this leg has been bridged/connected to another leg so that the two parties can converse |
| legX_reject | Y | The call was rejected by a called party rejecting the call in a callee_verify menu |
| legX_callrec_start | N | Call recording has started for this leg |
| legX_callrec_stop | N | Call recording has stopped for this leg |
| legX_ivr_start | N | Inbound legs only; the caller has entered an IVR menu |
| legX_ivr_input | N | Inbound legs only; the caller has pressed a button on their phone keypad to select a menu option |
| legX_ivr_input_default | N | Inbound legs only; the system has selected the IVR menu's default option because the caller did't choose anything |
| legX_ivr_force_hangup | N | Inbound legs only; the system has hung up the call because the caller failed to choose a valid option after a configured amount of time or number of attempts |
| legX_ivr_maxreplays | N | Inbound legs only; an IVR has been replayed to the caller the maximum configured number of times |
| legX_end | Y | The call leg has ended |
| legX_telecaptcha_read_start | N | Telecaptcha calls; the system is waiting for the remote party to enter digits on their phone keypad |
| legX_telecaptcha_read_end | N | Telecaptcha calls; the system has finished reading digits from the remote party |
| legX_dtmf_rx | N | a DTMF signal is being received from this leg |
| legX_dtmf_tx | N | a DTMF signal is being sent to this leg |
These fields are general and don't relate to a specific leg.
The following fields will appear in every webhook (chksum will be included if your account has a secret salt defined).
| Field | Data Type | Description |
|---|---|---|
| uniqueID | string | a unique identifier for this call. Present in every webhook; all webhooks for the same call will have the same value in here. |
| tstamp | integer | unix timestamp for the event (number of seconds since the epoch, ie 1 January 1970 00:00:00) |
| tstamp_ms | integer | higher resolution unix timestamp for the event (number of milliseconds since the epoch) |
| events | array | array of event names pertinent to this webhook |
| seq | integer | sequence number within the call for this webhook. The first webhook for a call will have a seq value of 1, the next one a seq value of 2, etc. This allows you to not only re-order any webhooks arriving out of order, but also allows you to identify duplicates that may result as a result of network timeouts causing re-tries (if configured). |
| chksum | string | if a secret salt is configured on your account, then every webhook will contain this. It is the MD5 checksum of the uniqueID concatenated with the seq value and the secret salt. |
The following fields will appear in only some webhooks, depending on which events the webhook is reporting.
| Field | Data Type | Description |
|---|---|---|
| custID | integer | Sent with start events. Customer account number in which the call belongs. Unless you have sub-accounts, this will always contain your account number. |
| custIDpath | array | Sent with start events. Reseller path. Unless you have sub-accounts, this will just be an array containing your own account number. |
| ref | string | Sent with start events. Customer reference string, if set. |
| feature_flags | array | Array of feature flag keywords for any additional features used in the call, eg CALLREC, ROU.IVR, ROU.MIRROR |
| extra_params | object | Sent with end events. Contains additional info for some features. |
| callbackUID | string | Sent with start events for callback calls |
| defer_until | integer | Sent when a callback call is deferred by the agent. Contains a unix timestamp representing the time the next attempt will be made. |
| num_deferrals | integer | Sent when a callback call is deferred by the agent. Shows how many times this particular callback has been deferred by the agent so far. |
| max_deferrals | integer | Sent when a callback call is deferred by the agent. Shows the maximum number of deferrals allowed before the callback will be aborted. |
| service_number | string | Sent with start events for call types that have a service number (eg NTS, PBX calls). The service number in effect a billing identifier - the number being used to provide the service. |
These fields contain information about a specific call leg, and as such their names start legX_, where X is the leg number. This can be seen in the above examples.
| Field | Data Type | Description |
|---|---|---|
| legX_args | object | (object) Additional data about the leg, where applicable (eg a mailboxID, SIP credentials) |
| legX_cli | string | The calling number being presented on this leg. Withheld numbers not shown. |
| legX_dni | string | Inbound legs only; the called number. |
| legX_dest | string | Outbound legs only; the destination parameter (eg if going out over the telephone network, this will be the destination phone number). |
| legX_desttype | string | Outbound legs only; type of destination (eg number for calls going out to other phone numbers, sip, voicemail and other types). |
| legX_alias_to | string | For inbound legs where the called number is set up to alias its routing to another number we also host, the number being aliased will be in this field. |
| legX_mirror_to | string | For inbound legs where the called number is set up to mirror its routing to another number we also host, the number being mirrored will be in this field. |
| legX_clearcause | integer | Sent with legX_end events. The Q.850 clear cause indicating the leg status. |
| legX_sipcause | integer | Sent with legX_end events for SIP calls. The SIP clear cause indicating the leg status. |
| legX_disposition | string | Sent with legX_end events. A human readable keyword (eg ANSWER, CANCEL, BUSY) indicating the leg status. |
| legX_feature_flags | array | Array of feature flag keywords for any additional features used in this call leg, eg CALLREC, ROU.IVR, ROU.MIRROR |
| legX_dtmf_rx_dgts | string | Contains the DTMF character being received on this leg (digits 0 to 9, * or # and with some phones, also may be letters A to D) |
| legX_dtmf_tx_dgts | string | Contains the DTMF character being received sent out on this leg (digits 0 to 9, * or # and with some phones, also may be letters A to D) |
| legX_ivrID | integer | internal ID of ivr menu when a call leg enters a locally hosted menu |
| legX_ivr_input | string | Contains the character(s) that were entered whilst in a locally hosted IVR menu |
| legX_ivr_type | string | Indicates the IVR type the user has entered, eg start_of_call (normal menu), callee_verify |
| legX_direction | string | Indicates the direction of the leg. Will be ingress for inbound legs, and egress for outbound legs. |
| legX_transport | string | Indicates the transport type. Currently values will be pstn for legs going over the telephone network and sip for SIP VoIP legs |