Skip to main content

Redacting Messages for HIPAA Compliance

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

Redacting Messages Immediately after Sending

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. You will also need your SignalWire API credentials. You can get them 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.

Step by Step Code Walkthrough

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

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()

Node.js

What do I need to run this code?

We will need the following libraries (click their names to get instructions on how to install them):

You will also need your SignalWire API credentials. You can get them 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

If you save this code snippet in a file called redactingAfterSending.js, for example, you then need to run:
node redactingAfterSending.js in the terminal.

Step by Step Code Walkthrough

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.

const { RestClient } = require('@signalwire/compatibility-api');

// TODO: Update with your own credentials
const spaceURL = 'YOURSPACENAME.signalwire.com'
const projectID = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXX"
const authToken = 'PTxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'

const client = RestClient(
projectID,
authToken,
{ signalwireSpaceUrl: spaceURL });

const phoneNumberList = [
'+1##########',
'+1##########'
];
Send Message, Sleep, Redact Message

Here we will create a for loop using your phoneNumberList to create an outbound SMS request with the SignalWire API. Once the request is sent, the program will sleep for 10 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 Delete the message lines in the snippet below we can send a final request to delete the message instead.

phoneNumberList.forEach((number) => {
let messageSID;

const sendMessage = client.messages
.create({
from: '+1##########',
body: "We're going to redact this for HIPAA",
to: number
})
.then(message => {
messageSID = message.sid;
});

sendMessage.then(() => {
setTimeout(() => {
// Redact the message body
client.messages(messageSID)
.update({
body: ''
})
.then(console.log("Message Redacted"));

// Delete the message
// client.messages(messageSID)
// .delete()
// .then(console.log("Message Redacted"));
}, 10000);
});
});
Redacting Messages With the Above 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, you have the option of uncommenting the lines to delete the message instead of just redacting the text.

Tunneling to your local machine

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.

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 get them by logging into your SignalWire space and navigating to the API tab. For more information on navigating your SignalWire space check here

Step by Step Code Walkthrough

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)

Node.js

What do I need to run this code?

We will need the following libraries (click their names to get instructions on how to install them):

Step by Step Code Walkthrough

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 Express module to run a server. Finally, we will create a SignalWire Client using our credentials.

const { RestClient } = require('@signalwire/compatibility-api');
const express = require("express");

var app = express();
app.use(express.urlencoded());

app.listen(3000, () => {
console.log("Server running on port 3000");
});

// TODO: Update with your own credentials
const spaceURL = 'YOURSPACENAME.signalwire.com'
const projectID = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXX"
const authToken = 'PTxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'

const client = RestClient(
projectID,
authToken,
{ signalwireSpaceUrl: spaceURL });
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.post("/RedactMessage", (req, res) => {
let messageSID = req.body.MessageSid;
let messageStatus = req.body.MessageStatus;

// Check to make sure message isn't still in progress
if (messageStatus != "sending" & messageStatus != "queued") {
// Redact the message body
client.messages(messageSID)
.update({
body: ''
})
.then(console.log("Message Redacted"))
.then(res.sendStatus(200));

// Uncomment this line and comment the above one if instead you want to FULLY delete the message, erasing all message history
// Delete the message
// client.messages(messageSID)
// .delete()
// .then(console.log("Message Redacted"))
// .then(res.sendStatus(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.

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!