Skip to main content

Sending SMS from the Browser

This guide is using Relay V4

This guide is available for Relay V3 and for Relay V4. You are currently viewing the guide for Relay V4. To switch to the older Relay V3 guide, please use the selection field below:

This guide will use SignalWire's Messaging API to create a simple web application that can send SMS through the browser.

What do I need?

Find the full code on Github here.

You will need the SignalWire Realtime SDK running on Node.js. It'll help if you are familiar with the Express framework.

Additionally, you will need a SignalWire account which you can create here. From your SignalWire Space, you need your SignalWire API credentials. If you need help finding these credentials, visit Navigating your SignalWire Space.

Trying it out

Run Natively

Navigate to this project in the SignalWire Guides GitHub Repo, and follow the instructions in README.md.

This example should not be used in a live environment

Exposing this web app to a live endpoint means anybody with the URL could send SMS requests through your SignalWire Space.

Code Walkthrough

The main code for this demo (index.js) is a very simple file server with a minimal backend with a single route (/sendSMS). The file server delivers index.html to the user's browser.

To perform API calls to the SignalWire servers, we need to send some authentication information: Project ID and the API token. This information is sensitive, so we take special precautions in storing them. We keep them in the .env file and add a rule on .gitignore to not push the .env file to GitHub. And while we're at it, we also store the phone number in the .env file, for ease of maintenance.

Server-side code

Set-up

The server-side code for this is very simple. First, we will import the required packages, set our environment variables, and create a client that will handle our SMS requests.

require("dotenv").config();
const { Messaging } = require("@signalwire/realtime-api");

const sendingPhoneNumber = process.env.PHONE_NUMBER;

const client = new Messaging.Client({
project: process.env.PROJECT_ID,
token: process.env.API_TOKEN,
});

Index Route

Next, we will write some code to serve the client-side code (index.html). When integrating this project, this may not be needed depending on how you're hosting the frontend.

app.use("/", express.static("html")); // serve the html folder

Create SMS Handler Route

Finally, for our server-side, we will create a route that actually handles the creation of our SMS requests to the client. We'll name it /sendSMS.

First, we get the destination phone number and the SMS body from the client. We need to make sure that the values are legitimate. In particular, we need to make sure the phone number is in the required E.164 format. To do so, we call the isE164PhoneNumber() function provided by the is-e164-phone-number package on NPM. You can, of course, choose to validate the numbers however you like, including regular expressions. You might also want to verify that the destination country code is supported by you.

We will try to send the message we retrieved from the client, and return a confirmation to the client. In this case, there is no validation if a message was delivered successfully, only that the request was created.

Alternatively, if our conditions aren't met, we just assume something went wrong and return an error message to the client.

While the rest of the parameters to client.send (body, to, from) are self-explanatory, the context parameter needs an introduction. It is used to segregate calls and messages (so you can, for example, subscribe to events from a group of phone numbers in the same context). For further information, please read First steps with Messaging.

app.post("/sendSMS", async (req, res) => {
let { phoneno, body } = req.body;
if (typeof body !== "string" || body === "") return res.send("Invalid body");
if (!isE164PhoneNumber(phoneno)) return res.send("Invalid Phone Number");

console.log("Sending message to phone number", phoneno);
try {
const status = await client.send({
context: "office",
from: sendingPhoneNumber, // The number you bought from SignalWire
to: phoneno,
body,
});

console.log(status);
return res.send("Your SMS was sent");
} catch (e) {
console.error(e);
return res.send("Error sending SMS");
}
});

Client-side Code

Our client-side code is just a simple HTML file index.html and its styling in index.css.

Most of this code is just the default/boilerplate HTML. The heart of our client boils down to the <body>.

First, we will create a new <form> with the action URL being our /sendSMS route. Note that we want to send the information as a POST request to /sendSMS route, which will be received by the app.post('/sendSMS', ...) function above.

There we add two input fields, one for the destination phone number and one for the text. A button submits the information to the server.

<!DOCTYPE html>
<html>
<head>
<title>SMS with SignalWire RealTime API</title>
<link rel="stylesheet" media="all" href="index.css" />
</head>
<body>
<div class="body">
<form method="POST" action="/sendSMS">
<h1>Send an SMS with SignalWire</h1>
<label>Phone Number</label>
<input type="input" placeholder="E.164 number like +18001234567" name="phoneno" />
<br />
<br />
Message:
<textarea name="body"></textarea>
<button>Send</button>
</form>
</div>
</body>
</html>
body {
margin: 0;
padding: 0;
}
.body {
width: 100vw;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
form {
width: 300px;
height: 300px;
}

label {
width: 100%;
}
input {
width: 100%;
}
textarea {
width: 100%;
max-width: 100%;
min-width: 100%;
max-height: 300px;
}

Wrap Up

This is a simple and flexible way to allow data to be passed from the client to your server which can then be validated before we create requests to the SignalWire API! While this guide focuses on SMS, this same principle can be used to implement a wide variety of features into your web app!

Required Resources:

Github Repo
RealTime SDK

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!