Skip to main content

📌 Status Callbacks

You can learn more about voice status callbacks, all of the possible parameters you can use, and how to set them up in our status callback mega guide!

You can read the guide below, or use our recipe to quickly copy the code!

🦉 Open Recipe: Voice Status Callbacks

Configuring the Code

Below is an example of a simple call status tracker that will log every status change event ('initiated' to 'ringing', 'ringing' to 'answered', etc) to the console along with the CallSID, CallStatus, Timestamp, and Direction. If a call has reached an end-stage state, i.e. completed, canceled, no-answer, or busy, it will be added to our table of call records. This table will exclude failed calls and in-progress calls so as to not have duplicate records.

If a call fails, it will be added to a separate table containing failed calls along with relevant data to investigate later. If at any point the number of failed calls in the table reaches 100, the table will be downloaded to CSV and an SMS alert will be sent out to notify whoever would be in charge of dealing with the failures. After the CSV has been downloaded and the alert has been sent, we will clear the failed calls array so it can begin appending new failed calls again.

After every call is appended to either of the tables, the tables will reprint so that it's easy to see the updated list of completed and failed calls.

from flask import Flask, request
import logging
import pandas as pd
from import Client as signalwire_client

app = Flask(__name__)

# create empty arrays to store our call records - one for failed only and one to handle all other end stage statuses (not queued, not ringing, not answered, etc)
failedCallArray = []
allCallArray = []

# authenticate the SignalWire client
client = signalwire_client("ProjectID",

@app.route("/CallStatus", methods=['POST'])
def incoming_calls():
# grab incoming parameters posted to webhook and assign them variables
call_sid = request.values.get('CallSid', None)
call_status = request.values.get('CallStatus', None)
event_timestamp = request.values.get('Timestamp', None)
recording_url = request.values.get('RecordingUrl', None)
call_direction = request.values.get('Direction', None)
to_number = request.values.get('To', None)
from_number = request.values.get('From', None)

# log some basic information to print to console for EVERY status change'SID: {}, Status: {}, Timestamp: {}, Direction: {}'.format(call_sid, call_status, event_timestamp, call_direction))

# create a separate array for all end stage statuse updates and add them to our call log table, display updated table
if (call_status != 'ringing' and call_status != 'initiated' and call_status != 'answered' and call_status != 'in-progress' and call_status != 'queued' and call_status != 'failed'):
allCallArray.append([call_sid, call_status, event_timestamp, call_direction, to_number, from_number, recording_url])
adf = pd.DataFrame(allCallArray, columns=('Call SID', 'Call Status', 'Event Timestamp', 'Call Direction', 'To Number', 'From Number',
'Recording URL (if present)'))
print("All Calls")

# if call status is failed, log call record to call failure table and display table
if (call_status == "failed"):
failedCallArray.append([call_sid, call_status, event_timestamp, call_direction, to_number, from_number, recording_url])
df = pd.DataFrame(failedCallArray, columns=('Call SID', 'Call Status', 'Event Timestamp', 'Call Direction', 'To Number', 'From Number', 'Recording URL (if present)'))
print("Failed Calls")

# if the number of failed calls is over 100
if len(failedCallArray) > 100:
# download call logs with necessary data to CSV and send an sms alert of the failures
df.to_csv('failedCallReport.csv', index=False, encoding='utf-8')
m = client.messages.create(
body='Call Failure Alert! You have received 100 call failures. '
'A CSV of the failures has been downloaded and the failure database will now reset.',
print("CSV of Failed Calls Downloaded & Message Alert Sent")

# clear array to start adding fresh logs again
while len(failedCallArray) > 0:

# Return 200 OK
return ('', 200)

if __name__ == "__main__":

Running the application

You will need the Flask framework and the SignalWire Python SDK downloaded.

To run the application, execute export then run flask run.