Get access to free VOIP training. Sign up below.

Broadworks XSI-Event webhooks

I started looking into webhooks for xsi-events updates. With Django, building a very basic hook took only a short amount of time!

First off, why would you use xsi-events? Xsi-events are used for notifcations of real-time events. This will allow you to monitor things like calls in queue, users on DND, and anything else found in the Receptionist or Call Center thin clients.

XSP servers have a test page built into them. You can find the URL in the XSI-events user guide from

You can use the test page to trigger a subscription to an event. You can send the data as JSON or XML. You can also build something very easily with curl :

curl -u '' -H "Content-Type: text/xml" -d @test.xml -X POST https://xsp.local/com.broadsoft.xsi-events/v2.0/enterprise/TEST/group/TEST-GROUP -v


This will require an Enterprise administrator credentials in the curl request.

Once you trigger this, the XSP will respond with POST request to the uri found in the XML file.

Now you need a way to handle this.

In your file, you can build a very simple handler. Notice the csrf_exempt decorator. As the POST request will not send a csrf token, you will need a method to by pass this.

from django.core.context_processors import csrf
import as ct

def xsiEvents(request):
        if request.method == 'POST':
                data = ct.xml_xsi_ccqueue(request.body)
                return HttpResponse()
        if request.method  == 'GET' :
                return HttpResponse()

As you can see, when the request method is POST, Django will call another method for processing. I built a model where all updates matching certain criteria are stored. Yeah.. this could be better, however this is all in dev mode right now.

class callcenter_queue(models.Model):
        userId = models.CharField(max_length=100)
        externalApplicationId  = models.CharField(max_length=100)
        httpContact = models.URLField(max_length=100)
        targetId = models.CharField(max_length=100)
        eventData = models.CharField(max_length=100)
        callhalf = models.CharField(max_length=100)
        extTrackingId = models.CharField(max_length=100)
        addTime = models.CharField(max_length=50)
        acdName = models.CharField(max_length=100)

In the handler, I first parse the XSML. I turn turn various tags, text and attributes into dictionary keys and values.

I then update or delete the table (model) if the ‘eventData’ key matches certain criteria.

import xml.etree.ElementTree as ET
def xml_xsi_ccqueue(data):
        root = ET.fromstring(data)
        response = {}
        for child in root:
                if child.tag == '{}eventData' :
                        response[child.tag.replace('{}', '') ] = str(child.attrib)
                        response[child.tag.replace('{}', '') ] = child.text
                for sub in child:
                        response[sub.tag.replace('{}', '') ] = sub.text
                        for meta in sub:
                                response[meta.tag.replace('{}', '') ] = meta.text

        # Query for a extTrackingID that mathces the xsi-event POST
        if response['eventData'] == '{'{}type': 'xsi:ACDCallAddedEvent'}':
               f.write('found eventData')
               xsi_update = callcenter_queue(
                        userId =  response['userId'],
                        externalApplicationId =  response['externalApplicationId'],
                        httpContact=  response['uri'],
                        targetId =  response['targetId'],
                        eventData =  response['eventData'],
                        callhalf =  response['callId'],
                        extTrackingId =  response['extTrackingId'],
                        addTime =  response['addTime'],
                        acdName =  response['acdName']
               return response
        #if the call is answered, delete the event from the database
        if  'ACDCallAnsweredByAgentEvent' in response['eventData'] :
                try :
                        f.write('read to remove')
                        f.write( str(response['extTrackingId']))
                        xsi_update  = callcenter_queue.objects.get(extTrackingId = response['extTrackingId'] )

        #if the caller bails out remove the call from queue
        if  'ACDCallAbandonedEvent' in response['eventData'] :
                try :
                        xsi_update  = callcenter_queue.objects.get(extTrackingId = response['extTrackingId'] )

Now this is a very basic example of building a webhook for xsi-events. There’s a lot of code that I can clean up here, however it does function in a lab/dev environment.




UPDATE 10/21/2014


Here is a sample of the XML I use for this call:

<?xml version=”1.0″ encoding=”UTF-8″? >
<Subscription xmlns=””  >
<targetIdType>https://xsp.local/com.broadsoft.xsi-events/v2.0/enterprise/$ENTERPRISE_NAME/group/$GROUP_NAME</targetIdType >
<event>Call Center Monitoring</event >
<uri>http://myserver.local/webhooks</uri >
<applicationId>CUSTOM_APP_1.0</applicationId >

4 thoughts on “Broadworks XSI-Event webhooks

  1. Can you provide the the sample XML file? Thanks.

    I am trying to perform the same request on my sandbox account, however, I am encountering the following response content:

    ‘ndoGet is not supporteddoGet is not supported1108’

  2. Hi, In my case the event subscriptions are not working. When we put a subscription request, we get back a success response with a subscription id but that subscription is not found when searched back in the system. Also the http url never gets called by the subscription proving they haven’t been activated.
    Please help. Has it got something to do with the users access rights. What access rights are needed for getting subscription for target type user .

Comments are closed.