Call Data Webhooks
Schema
A Call Data Webhook is a registered endpoint where CDRs should be sent once billed by the system.
Prior to July 6, 2026, this would ONLY send SMS and MMS CDRs.
Bulk Dip Tasks can be configured to send their generated CDRs with a enable_cdr_export flag.
LRN, CNAM and MRL can similarly be enabled with the same flag: enable_cdr_export on the request.
Type Object
| Name | Type | Description |
|---|---|---|
auth_identity |
String | Desc. auth_identity |
auth_method |
Enum(NONE, BASIC, BEARER):String |
Desc. auth_method |
auth_name |
String | Desc. auth_name |
auth_secret |
String | Desc. auth_secret |
custom_headers |
Array:SubObject | Desc. custom_headers |
custom_query_params |
Array:SubObject | Desc. custom_query_params |
data |
String | Desc. data |
id |
String(format:ulid) | Desc. id |
inserted_at |
String(format:date-time) | An ISO8601 formatted timestamp |
name |
String(1..255) | Desc. name |
notes |
String(0..65535) | Desc. notes |
protocol |
Enum(NONE, HTTP, SFTP):String |
Desc. protocol |
updated_at |
String(format:date-time) | An ISO8601 formatted timestamp |
Desc. auth_identity
Acts a the username in an authorization pair, only applicable if the auth method is BASIC.
Desc. auth_method
Depending on the protocol, this will affect the authorization behaviour.
NONE- no authorization is provided if not required, otherwise placeholder values will be usedBASIC- theauth_identityacts as the username while theauth_secretacts as the password- With
HTTP- anAuthorization: Basic <BASE64-VALUE>header will be set - With
SFTP- the session will be authenticated using theauth_identityandauth_secret BEARER- theauth_identityis ignored and only theauth_secretis used verbatim- With
HTTP- anAuthorization: Bearer <VALUE>header will be set - with
SFTP- the username will be a placeholder value and the password will be set
Desc. auth_name
Reserved for other protocols that may require additional auth information.
Desc. auth_secret
Acts as the password in an authorization pair, if using BEARER, it will be the verbatim token.
SubObject
Sub-Schema
Type Object
| Name | Type | Description |
|---|---|---|
key |
String | |
value |
String |
Desc. custom_headers
A list of custom header values that should be sent on the HTTP request.
Headers are currently unused if the protocol is not HTTP.
SubObject
Sub-Schema
Type Object
| Name | Type | Description |
|---|---|---|
key |
String | |
value |
String |
Desc. custom_query_params
A list of custom query parameters that should be sent on the HTTP request.
These are currently unused if the protocol is not HTTP.
Desc. data
Depending on the protocol, this will contain the url or address of the endpoint.
For HTTP, it will be an http url, as for SFTP, it will be the hostname and optionally the port.
HTTP- (e.g. "http://example.com/path/to/upload")SFTP- (e.g. "sftp://sftp.example.com/path/to/upload")
Desc. id
Another format for UUID, used primarily for tasks, requests and messages.
Desc. name
A display name for the call data webhook, used purely for identifying it.
Desc. notes
Any notes or details about the call data webhook.
Desc. protocol
The transport protocol which should be used to send
NONE- Effectively a no-op.HTTP- Send CDRs over HTTP.SFTP- Upload CDRs over SFTP.
Example
{
"auth_identity": "string",
"auth_method": "NONE",
"auth_name": "string",
"auth_secret": "string",
"custom_headers": [
{
"key": "x-my-header",
"value": "Anything"
}
],
"custom_query_params": [
{
"key": "x-my-header",
"value": "Anything"
}
],
"data": "string",
"id": "01EH2Y28M6KXG14QMPM3HSP1Y0",
"inserted_at": "2021-08-13T04:08:44.762841Z",
"name": "CDR Webhook us-east",
"notes": "string",
"protocol": "NONE",
"updated_at": "2021-08-13T04:08:44.762841Z"
}
Summary
CallDataWebhooks are an experimental feature for delivering your CallData or CDR records in realtime to a specified endpoint.
At the moment only SMS and MMS CDRs are supported.
API
Create Call Data Webhook
POST /api/v1/call_data_webhooks HTTP/1.1
Create a new CDR Webhook.
You are limited to one cdr webhook record per-account.
Request application/json
POST /api/v1/call_data_webhooks HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 482
{
"data": {
"auth_identity": "string",
"auth_method": "NONE",
"auth_name": "string",
"auth_secret": "string",
"custom_headers": [
{
"key": "x-my-header",
"value": "Anything"
}
],
"custom_query_params": [
{
"key": "x-my-header",
"value": "Anything"
}
],
"data": "string",
"name": "CDR Webhook us-east",
"notes": "string",
"protocol": "NONE"
},
"type": "call_data_webhook"
}
Response 201
application/json
HTTP/1.1 201
Content-Type: application/json
Content-Length: 621
{
"data": {
"auth_identity": "string",
"auth_method": "NONE",
"auth_name": "string",
"auth_secret": "string",
"custom_headers": [
{
"key": "x-my-header",
"value": "Anything"
}
],
"custom_query_params": [
{
"key": "x-my-header",
"value": "Anything"
}
],
"data": "string",
"id": "01EH2Y28M6KXG14QMPM3HSP1Y0",
"inserted_at": "2021-08-13T04:08:44.762841Z",
"name": "CDR Webhook us-east",
"notes": "string",
"protocol": "NONE",
"updated_at": "2021-08-13T04:08:44.762841Z"
},
"type": "call_data_webhook"
}
Response 403
application/json
HTTP/1.1 403
Content-Type: application/json
Content-Length: 312
{
"errors": [
{
"code": "access_denied.no_scope",
"detail": "No scope available to user role",
"params": {
"action": "index",
"level": "guest",
"resource": "resource"
},
"sub_code": "none",
"title": "Access Denied, no scope available"
}
]
}
Response 422
application/json
HTTP/1.1 422
Content-Type: application/json
Content-Length: 241
{
"errors": [
{
"code": "invalid_parameter",
"detail": "The specified resource could not be found",
"source": {
"pointer": "/data/type"
},
"sub_code": "none",
"title": "Not Found"
}
]
}
Update Call Data Webhook
POST /api/v1/call_data_webhooks HTTP/1.1
Create a new CDR Webhook.
You are limited to one cdr webhook record per-account.
Request application/json
POST /api/v1/call_data_webhooks HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 482
{
"data": {
"auth_identity": "string",
"auth_method": "NONE",
"auth_name": "string",
"auth_secret": "string",
"custom_headers": [
{
"key": "x-my-header",
"value": "Anything"
}
],
"custom_query_params": [
{
"key": "x-my-header",
"value": "Anything"
}
],
"data": "string",
"name": "CDR Webhook us-east",
"notes": "string",
"protocol": "NONE"
},
"type": "call_data_webhook"
}
Response 201
application/json
HTTP/1.1 201
Content-Type: application/json
Content-Length: 621
{
"data": {
"auth_identity": "string",
"auth_method": "NONE",
"auth_name": "string",
"auth_secret": "string",
"custom_headers": [
{
"key": "x-my-header",
"value": "Anything"
}
],
"custom_query_params": [
{
"key": "x-my-header",
"value": "Anything"
}
],
"data": "string",
"id": "01EH2Y28M6KXG14QMPM3HSP1Y0",
"inserted_at": "2021-08-13T04:08:44.762841Z",
"name": "CDR Webhook us-east",
"notes": "string",
"protocol": "NONE",
"updated_at": "2021-08-13T04:08:44.762841Z"
},
"type": "call_data_webhook"
}
Response 403
application/json
HTTP/1.1 403
Content-Type: application/json
Content-Length: 312
{
"errors": [
{
"code": "access_denied.no_scope",
"detail": "No scope available to user role",
"params": {
"action": "index",
"level": "guest",
"resource": "resource"
},
"sub_code": "none",
"title": "Access Denied, no scope available"
}
]
}
Response 422
application/json
HTTP/1.1 422
Content-Type: application/json
Content-Length: 241
{
"errors": [
{
"code": "invalid_parameter",
"detail": "The specified resource could not be found",
"source": {
"pointer": "/data/type"
},
"sub_code": "none",
"title": "Not Found"
}
]
}
Delete Call Data Webhook
POST /api/v1/call_data_webhooks HTTP/1.1
Create a new CDR Webhook.
You are limited to one cdr webhook record per-account.
Request application/json
POST /api/v1/call_data_webhooks HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 482
{
"data": {
"auth_identity": "string",
"auth_method": "NONE",
"auth_name": "string",
"auth_secret": "string",
"custom_headers": [
{
"key": "x-my-header",
"value": "Anything"
}
],
"custom_query_params": [
{
"key": "x-my-header",
"value": "Anything"
}
],
"data": "string",
"name": "CDR Webhook us-east",
"notes": "string",
"protocol": "NONE"
},
"type": "call_data_webhook"
}
Response 201
application/json
HTTP/1.1 201
Content-Type: application/json
Content-Length: 621
{
"data": {
"auth_identity": "string",
"auth_method": "NONE",
"auth_name": "string",
"auth_secret": "string",
"custom_headers": [
{
"key": "x-my-header",
"value": "Anything"
}
],
"custom_query_params": [
{
"key": "x-my-header",
"value": "Anything"
}
],
"data": "string",
"id": "01EH2Y28M6KXG14QMPM3HSP1Y0",
"inserted_at": "2021-08-13T04:08:44.762841Z",
"name": "CDR Webhook us-east",
"notes": "string",
"protocol": "NONE",
"updated_at": "2021-08-13T04:08:44.762841Z"
},
"type": "call_data_webhook"
}
Response 403
application/json
HTTP/1.1 403
Content-Type: application/json
Content-Length: 312
{
"errors": [
{
"code": "access_denied.no_scope",
"detail": "No scope available to user role",
"params": {
"action": "index",
"level": "guest",
"resource": "resource"
},
"sub_code": "none",
"title": "Access Denied, no scope available"
}
]
}
Response 422
application/json
HTTP/1.1 422
Content-Type: application/json
Content-Length: 241
{
"errors": [
{
"code": "invalid_parameter",
"detail": "The specified resource could not be found",
"source": {
"pointer": "/data/type"
},
"sub_code": "none",
"title": "Not Found"
}
]
}
List Call Data Webhooks
POST /api/v1/call_data_webhooks HTTP/1.1
Create a new CDR Webhook.
You are limited to one cdr webhook record per-account.
Request application/json
POST /api/v1/call_data_webhooks HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 482
{
"data": {
"auth_identity": "string",
"auth_method": "NONE",
"auth_name": "string",
"auth_secret": "string",
"custom_headers": [
{
"key": "x-my-header",
"value": "Anything"
}
],
"custom_query_params": [
{
"key": "x-my-header",
"value": "Anything"
}
],
"data": "string",
"name": "CDR Webhook us-east",
"notes": "string",
"protocol": "NONE"
},
"type": "call_data_webhook"
}
Response 201
application/json
HTTP/1.1 201
Content-Type: application/json
Content-Length: 621
{
"data": {
"auth_identity": "string",
"auth_method": "NONE",
"auth_name": "string",
"auth_secret": "string",
"custom_headers": [
{
"key": "x-my-header",
"value": "Anything"
}
],
"custom_query_params": [
{
"key": "x-my-header",
"value": "Anything"
}
],
"data": "string",
"id": "01EH2Y28M6KXG14QMPM3HSP1Y0",
"inserted_at": "2021-08-13T04:08:44.762841Z",
"name": "CDR Webhook us-east",
"notes": "string",
"protocol": "NONE",
"updated_at": "2021-08-13T04:08:44.762841Z"
},
"type": "call_data_webhook"
}
Response 403
application/json
HTTP/1.1 403
Content-Type: application/json
Content-Length: 312
{
"errors": [
{
"code": "access_denied.no_scope",
"detail": "No scope available to user role",
"params": {
"action": "index",
"level": "guest",
"resource": "resource"
},
"sub_code": "none",
"title": "Access Denied, no scope available"
}
]
}
Response 422
application/json
HTTP/1.1 422
Content-Type: application/json
Content-Length: 241
{
"errors": [
{
"code": "invalid_parameter",
"detail": "The specified resource could not be found",
"source": {
"pointer": "/data/type"
},
"sub_code": "none",
"title": "Not Found"
}
]
}
Get Call Data Webhook
POST /api/v1/call_data_webhooks HTTP/1.1
Create a new CDR Webhook.
You are limited to one cdr webhook record per-account.
Request application/json
POST /api/v1/call_data_webhooks HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 482
{
"data": {
"auth_identity": "string",
"auth_method": "NONE",
"auth_name": "string",
"auth_secret": "string",
"custom_headers": [
{
"key": "x-my-header",
"value": "Anything"
}
],
"custom_query_params": [
{
"key": "x-my-header",
"value": "Anything"
}
],
"data": "string",
"name": "CDR Webhook us-east",
"notes": "string",
"protocol": "NONE"
},
"type": "call_data_webhook"
}
Response 201
application/json
HTTP/1.1 201
Content-Type: application/json
Content-Length: 621
{
"data": {
"auth_identity": "string",
"auth_method": "NONE",
"auth_name": "string",
"auth_secret": "string",
"custom_headers": [
{
"key": "x-my-header",
"value": "Anything"
}
],
"custom_query_params": [
{
"key": "x-my-header",
"value": "Anything"
}
],
"data": "string",
"id": "01EH2Y28M6KXG14QMPM3HSP1Y0",
"inserted_at": "2021-08-13T04:08:44.762841Z",
"name": "CDR Webhook us-east",
"notes": "string",
"protocol": "NONE",
"updated_at": "2021-08-13T04:08:44.762841Z"
},
"type": "call_data_webhook"
}
Response 403
application/json
HTTP/1.1 403
Content-Type: application/json
Content-Length: 312
{
"errors": [
{
"code": "access_denied.no_scope",
"detail": "No scope available to user role",
"params": {
"action": "index",
"level": "guest",
"resource": "resource"
},
"sub_code": "none",
"title": "Access Denied, no scope available"
}
]
}
Response 422
application/json
HTTP/1.1 422
Content-Type: application/json
Content-Length: 241
{
"errors": [
{
"code": "invalid_parameter",
"detail": "The specified resource could not be found",
"source": {
"pointer": "/data/type"
},
"sub_code": "none",
"title": "Not Found"
}
]
}
Webhook
As this feature is a delivery configuration, it will forward or upload the respective CDR to the configured endpoint.
In both the HTTP and SFTP protocols, a standard CDR response is sent or uploaded.
The choice to use the same CDR format is to simplify implementation, as the structure should be familiar.
HTTP
Request
POST http://example.com/configured/path HTTP/1.1
Content-Type: application/json
A single call data record
Type Object
| Name | Type | Description |
|---|---|---|
fees |
Array:CDRFee | |
host_number |
String | Desc. host_number |
id |
String(format:ulid) | Desc. id |
inserted_at |
String(format:date-time) | An ISO8601 formatted timestamp |
item_count |
Integer | Desc. item_count |
item_id |
String | Desc. item_id |
remote_number |
String | Desc. remote_number |
sell_rate |
String(format:decimal) | Desc. sell_rate |
status |
Enum:String | Main status of the CDR |
subtype |
Enum:String | Desc. subtype |
surcharges |
Array:CDRSurcharge | |
total |
String(format:decimal) | Desc. total |
type |
Enum:String | Desc. type |
updated_at |
String(format:date-time) | An ISO8601 formatted timestamp |
Desc. host_number
Depending on the CDR type, this can be an actual phone number or some other value
Desc. id
Another format for UUID, used primarily for tasks, requests and messages.
Desc. item_count
How many items does this CDR actually represent
Desc. item_id
Depending on the CDR type, this will be the id of another record
Desc. remote_number
Depending on the CDR type, this can be an actual phone number or some other value
Desc. sell_rate
The base rate (no fees or surcharges), already includes the count
Enum Values status
Allowed values
UNKNOWNOKMISSERRORREFUNDNO_ANSWERBUSYCANCELLEDCHANNEL_UNAVAILABLECONGESTIONTEMP_FAILURE
Enum Values subtype
Allowed values
NONELRNLRNEMESSAGING_CARRIER_LOOKUPCNAMTTSOUTBOUNDINBOUNDTERMINATIONSIP_IAXDID_RCFDID_VOIPCALLBACKDIDCHARGEPREPAYMENTTAXPAYMENTADJUSTMENTDID_REGISTRYDID_REGISTRY_NRCDID_REGISTRY_A_MRCDEDICATED_ESPIDDEDICATED_ESPID_NRCDEDICATED_ESPID_A_MRCDID_TIERDID_TIER_NRCDID_TIER_A_MRCCSP_BRANDCSP_BRAND_A_MRCCSP_BRAND_VETTINGCSP_CAMPAIGNCSP_CAMPAIGN_MRCCSP_CAMPAIGN_A_MRC
Desc. subtype
Further refines the CDR type, depending on what the
Desc. total
The total amount charged (sell_rate+fees+surcharges)
Enum Values type
Allowed values
APIMMSSMSVOICEBALANCEMISC
Desc. type
The main category that the CDR belongs to.
Example
{
"fees": [
{
"cost": "0.000100",
"name": "extra_cheese"
}
],
"host_number": "12003004000",
"id": "01EH2Y28M6KXG14QMPM3HSP1Y0",
"inserted_at": "2021-08-13T04:08:44.762841Z",
"item_count": 1,
"item_id": "01FCYT490ZK2NYF0BFYRFFAJZ8",
"remote_number": "12003004001",
"sell_rate": "0.000900",
"status": "UNKNOWN",
"subtype": "NONE",
"surcharges": [
{
"cost": "0.000100",
"name": "ACME Corp"
}
],
"total": "0.000900",
"type": "API",
"updated_at": "2021-08-13T04:08:44.762841Z"
}
Response
Any 2xx status is accepted, but it's recommended to send a 204 status back once received.
Any other status will trigger a redelivery of the event.
HTTP/1.1 204 No Content
SFTP
There is no real example for SFTP, however a file in the form cdr-ID.json will be uploaded at the path, where ID is replaced with the ID of the CDR.
The format is the same as the HTTP Request CDR format.