- language:python - language:nodejs - sdk:compatibility - product:messaging 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](/compatibility-api/sdks). Specifically, we will be working with the [Update Message API](/rest/compatibility-api/endpoints/update-message) and the [Delete Message API](/rest/compatibility-api/endpoints/delete-message). 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](/platform/dashboard/getting-started/navigating-your-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. python 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. python # Loop through phone numbers to send to for x in phone_number_list: message = client.messages.create( from_=+1xxxxxxxxxx, body=Were 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): - [SignalWire Rest Client](https://www.npmjs.com/package/@signalwire/compatibility-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](/platform/dashboard/getting-started/navigating-your-space) #### 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. javascript 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. javascript phoneNumberList.forEach((number) => { let messageSID; const sendMessage = client.messages .create({ from: +1##########, body: Were 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); }); }); :::caution 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. :::info 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](https://ngrok.com/). You can learn more about how to use ngrok **[HERE](/platform/basics/guides/technical-troubleshooting/how-to-test-webhooks-with-ngrok)**. ::: ### Python #### What do I need to run this code? This guide will use the [SignalWire Python SDK](/compatibility-api/sdks). Specifically we will be working with the [Update Message API](/rest/compatibility-api/endpoints/update-message) and the [Delete Message API](/rest/compatibility-api/endpoints/delete-message). Additionally this project will use [Flask](https://flask.palletsprojects.com/en/2.0.x/installation/), 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](/platform/dashboard/getting-started/navigating-your-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. python 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. python @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 isnt 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): - [Express](https://www.npmjs.com/package/express) - [SignalWire Rest Client](https://www.npmjs.com/package/@signalwire/compatibility-api) #### 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. javascript 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. javascript app.post(/RedactMessage, (req, res) => { let messageSID = req.body.MessageSid; let messageStatus = req.body.MessageStatus; // Check to make sure message isnt 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](https://signalwire.com/signup) Please feel free to reach out to us on our [Community Slack](https://signalwire.community/) or create a Support ticket if you need guidance!