Redacting Messages for HIPAA Compliance - Python

Overview

This guide will show you two ways to approach redacting sensitive information from your outbound messages using the SignalWire API and Python.

What do I need to run this code?

This guide will use the SignalWire Python SDK. Specifically we will be working with the Update Message API and the Delete Message API. Additionally this project will use Flask, and of course you will need your SignalWire API credentials. You can do this by logging into your SignalWire space and navigating to the API tab. For more information on navigating your SignalWire space check here

How to Run Application

Build and run Natively

To run the application, execute export FLASK_APP=app.py then run flask run.

You may need to use an SSH tunnel for testing this code if running on your local machine. – we recommend ngrok. You can learn more about how to use ngrok here.

Step by Step Code Walkthrough

This guide will focus on the app.py file which will contain the full implementation of the code.

Redacting Messages Immediately after Sending

Set Up SignalWire Client and Additional Variables

First we will import our Client from the SignalWire rest API and import time. Next we will create a client using our SignalWire credentials. Finally we will create a list which will store our to numbers.

from signalwire.rest import Client as signalwire_client
import time

# instantiate signalwire client 
client = signalwire_client("ProjectID", "AuthToken", signalwire_space_url = 'YourSpace.signalwire.com')

# store list of numbers to send to in an array, or replace this with a lookup to your database
phone_number_list = ['+12xxxxxxxxx', '+13xxxxxxxxx']

Send Message, Sleep, Redact Message

Here we will create a for loop using your phone_number_list to create an outbound sms request with the SignalWire API. Once the request is sent, the program will sleep for 60 seconds, and then use the SignalWire API to create an update request. The update body will be empty, effectively redacting our message while keeping the record of the message in tact.

Alternatively, by uncommenting the final line in the snippet below we can send a final request to delete the message.

# Loop through phone numbers to send to
for x in phone_number_list:
    message = client.messages.create(
                                from_='+1xxxxxxxxxx',
                                body="We're going to redact this for HIPAA",
                               to=x
                                )

    # sleep for a period of time to account for while the message sending is in progress
    time.sleep(60)

    # use this to update the message body but keep the message record
    messages = client.messages(message.sid).update(body='')
    print("Message Redacted")

    # uncomment this line and comment the above one if instead you want to FULLY delete the message, erasing all message history
    #client.messages(message.sid).delete()

🚧

This solution is simple but not scalable.

The next section will present an alternative solution that accomplishes the same goal without relying on delays after sending.

Redacting Messages with Status Callbacks

The following example is an SMS status callback application that checks for messages with a MessageStatus that does not indicate the message is still in progress.

If the message is not in progress, we will redact the message body. As with the previous example, uncommenting the two lines above our return statement will send a request to completely delete the message history.

Set Up SignalWire Client and Additional Variables

Similar to our first example, we will import our Client from the SignalWire rest API. However we will also import the Flask and request modules from flask and create a variable for our flask app. Finally we will create a SignalWire client using our credentials.

from flask import Flask, request
from signalwire.rest import Client as signalwire_client

app = Flask(__name__)
client = signalwire_client("ProjectID","AuthToken",signalwire_space_url='YOUR_SPACE.signalwire.com')

Setting up our Webhook

First we will create a route for our webhook to listen in on. In our case we will listen for a POST request on the /RedactMessage route. Next we will get and store the incoming message sid and status parameters. Finally we will check the message status and ensure the message is not sending or queued. Once we identify the message is beyond those points, we can redact or delete it.

@app.route("/RedactMessage", methods=['POST'])
def incoming_sms():
    # store incoming request parameters in variables 
    message_sid = request.values.get('MessageSid', None)
    message_status = request.values.get('MessageStatus', None)

    # check to make sure message isn't still in progress 
    if (message_status != "sending" and message_status != "queued"):
        # use this to update the message body but keep the message record
        message = client.messages(message_sid).update(body='')
        print("Message Redacted")

        # uncomment this line and comment the above one if instead you want to FULLY delete the message, erasing all message history
        # client.messages(message_sid).delete()
        # print("Message Deleted")
    return ('', 200)

Wrap up

If you work in an industry that passes personal data, medical data, or financial data, it is crucial that you are able to remove personally-identifying information from records. This guide will assist you in quickly building up an app to ensure your outgoing messages are redacted in a swift and reliable manner,

Required Resources

SignalWire Python SDK
Flask

Sign Up Here

If you would like to test this example out, you can create a SignalWire account and space here

Please feel free to reach out to us on our Community Slack or create a Support ticket if you need guidance!


Did this page help you?