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, read our guide to Navigating your SignalWire Space.
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);
});
});
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.
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, read our guide to Navigating your SignalWire Space.
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, create a SignalWire account and Space
Please feel free to reach out to us on our Community Slack or create a Support ticket if you need guidance!