
How to Send and Receive SMS Messages with Node.js and Google Cloud Run
Tiempo de lectura: 9 minutos
Back in 2019, I organised a series of events featuring a “Cloud Run Club” at Finsbury Square Garden and Victoria in London, followed by a Google Cloud Run workshop. Today, there will be no running, but you'll learn how to build and deploy an SMS application using Node.js, Express, and the Vonage Messages API on Google Cloud Run.
Unfortunately, while running, I can't scale to zero, but Google Cloud Run lets you deploy containerized applications that scale automatically. You only pay for what you use. It's great for building webhooks and APIs since you don't need to manage servers. Your app scales to zero when there's no traffic.
Outline and Prerequisites
Node.js v18 or later installed
Google Cloud CLI installed and configured
A Google Cloud account with billing enabled
A basic understanding of JavaScript and Node.js.
Project Structure
You can find the complete code on GitHub. The project tree looks as follows.
blog-messages_api-cloud_run-sms/
├── index.js, contains our JavaScript
├── package.json, for our dependencies
├── .env.example, you can copy and create a .env from it to add your environment variables
├── .gitignore, for any files or folders not to be committed
└── private.key Create a Vonage Application
I'll show you how to create a new Vonage application from the dashboard in the steps below. Alternatively, you can use the CLI to create an application.
Para crear una aplicación, vaya a la sección Crear una aplicación en el panel de Vonage y define un nombre para tu aplicación.
Si tiene intención de utilizar una API que utilice Webhooks, necesitará una clave privada. Haga clic en "Generar clave pública y privada"; la descarga debería iniciarse automáticamente. Guárdela de forma segura; esta clave no puede volver a descargarse si se pierde. Seguirá la convención de nomenclatura private_<id de su aplicación>.key. Esta clave puede utilizarse ahora para autenticar llamadas a la API. Nota: La clave no funcionará hasta que se guarde la aplicación.
Elija las funciones que necesite (por ejemplo, Voice, Messages, RTC, etc.) y proporcione los webhooks necesarios (por ejemplo, URL de eventos, URL de respuestas o URL de mensajes entrantes). Estos se describirán en el tutorial.
Para guardar e implementar, haz clic en "Generar nueva aplicación" para finalizar la configuración. Tu aplicación ahora está lista para usar con las API de Vonage.
Messages API Capability and Configure Webhooks
Toggle the Messages option under capabilities. We will use the Messages API v1.
Set placeholder URLs for now. We'll update these after deployment:
Inbound URL: https://example.com/webhooks/inbound
Status URL: https://example.com/webhooks/status
Save your application and note down your Application ID.
Messages Capability
Para comprar un número de teléfono virtual, vaya a su panel API y siga los pasos que se indican a continuación.
Purchase a phone number
Vaya a su Panel API
Vaya a CONSTRUIR Y GESTIONAR > Numbers > Comprar Numbers.
Elija los atributos necesarios y haga clic en Buscar
Pulse el botón Comprar junto al número que desee y valide su compra
Para confirmar que ha adquirido el número virtual, vaya al menú de navegación de la izquierda, en CONSTRUIR Y GESTIONAR, haga clic en Numbers y, a continuación, en Sus Numbers.
Link a Virtual Phone Number to the Application
Once we've selected our number, it’s time to link it to our Vonage application. Go to Your Numbers and click the pencil icon next to your number. Select your application under "Messages". At [00:01:19], you can see how to purchase and link a virtual number.
Set Messages API as Default
Go to Settings and scroll down to "SMS Settings". Make sure "Messages API" is selected as the default API for SMS, then click "Save changes".
SMS SettingsVonage has two APIs for sending SMS: the SMS API and the Messages API. This tutorial uses the Messages API. If you don't switch this setting, your webhooks will receive a different payload format, and the code won't work correctly.
Initialize the Project
Create a directory for your application and change into it. Run npm init -y to initialize your project.
mkdir blog-messages_api-cloud_run-sms
cd blog-messages_api-cloud_run-sms
npm init -y Install Dependencies
We are going to use the following dependencies in our project: express, @vonage/server-sdk, @vonage/jwt. You can install them by running the following command from your terminal or command prompt.
npm install express @vonage/server-sdk @vonage/jwt Server Setup
Create the index.js file and initialize your server with the required packages. Configure a Vonage client using environment variables that are read from the .env file to be created from the .env.example file.
const express = require('express');
const path = require('path');
const { Vonage } = require('@vonage/server-sdk');
const { verifySignature } = require('@vonage/jwt');
const app = express();
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
// Initialize Vonage client
const vonage = new Vonage({
applicationId: process.env.VONAGE_APPLICATION_ID,
privateKey: path.join(__dirname, 'private.key')
});
const FROM_NUMBER = process.env.VONAGE_NUMBER;We use path.join(__dirname, 'private.key') to get the absolute path to the key file, so that it works both locally and when deployed to Cloud Run.
Add the Home Page
Add the form content and styling that the user must complete to send SMS messages. The user has to enter their phone number and a message, then click the submit button to send the SMS.
app.get('/', (req, res) => {
res.send(`
<!DOCTYPE html>
<html>
<head>
<title>Vonage SMS on Cloud Run</title>
<style>
body { font-family: Arial, sans-serif; max-width: 600px; margin: 50px auto; padding: 20px; }
h1 { color: #7b00ff; }
form { display: flex; flex-direction: column; gap: 15px; }
input, textarea { padding: 10px; font-size: 16px; }
button { padding: 12px; background: #7b00ff; color: white; border: none; cursor: pointer; }
</style>
</head>
<body>
<h1> Send SMS with Vonage </h1>
<form action="/send" method="POST">
<label>Phone Number (e.g. 444155551234)</label>
<input type="tel" name="to" required>
<label>Message</label>
<textarea name="text" rows="4" required></textarea>
<button type="submit">Send SMS</button>
</form>
</body>
</html>
`);
}); Add the Send Endpoint
Add the endpoint that sends the SMS using the Vonage Messages API. The vonage.messages.send() method accepts an object with channel set to 'sms' and message_type set to 'text'. The response includes a message_uuid you can use to track the message.
app.post('/send', async (req, res) => {
const { to, text } = req.body;
try {
const response = await vonage.messages.send({
message_type: 'text',
to: to,
from: FROM_NUMBER,
channel: 'sms',
text: text
});
console.log('SMS sent:', response.message_uuid);
res.sendSMS sent! Message ID: ${response.message_uuid});
} catch (error) {
console.error('Error sending SMS:', error);
res.status(500).sendFailed to send SMS: ${error.message});
}
}); Add Webhook Endpoints
When someone sends an SMS to your Vonage virtual number you previously purchased, the SMS message arrives at Vonage, Vonage sends a POST request to your Google Cloud Run /webhooks/inbound endpoint, and finally, your app processes the message and responds with 200 OK, if everything works well. Add the webhook endpoints that use this verification, as shown below. The status webhook (/webhooks/status) receives delivery receipts. You'll know whether your message was delivered or failed.
app.post('/webhooks/inbound', (req, res) => {
verifyJWT(req);
console.log('Inbound SMS received:');
console.log('From:', req.body.from);
console.log('Text:', req.body.text);
res.status(200).send('OK');
});
app.post('/webhooks/status', (req, res) => {
verifyJWT(req);
console.log('Status update:', req.body.status);
res.status(200).send('OK');
});Agrega una función de verificación JWT para verificar si la solicitud entrante (por ejemplo, mensaje o llamada) proviene de Vonage.
La variable VONAGE_API_SIGNATURE_SECRET es el secreto utilizado para firmar la solicitud correspondiente al secreto de firma asociado a la clave API incluida en las reivindicaciones JWT. Puede identificar su secreto de firma en los Configuración del panel de control.
Puede obtener más información sobre verificar la solicitud.
const verifyJWT = (req) => {
// Verify if the incoming request came from Vonage
const jwtToken = req.headers.authorization.split(" ")[1];
if(!verifySignature(jwtToken, process.env.VONAGE_API_SIGNATURE_SECRET)) {
console.error("Signature does not match");
throw new Error("Not a Vonage API request");
}
console.log("JWT verified");
}Asegúrese de instalar la dependencia @vonage/jwt.
npm install @vonage/jwt Start the Server
Cloud Run sets the PORT environment variable automatically, so we use that if available. Add the code to start the server:
const PORT = process.env.PORT || 8080;
app.listen(PORT, () => {
console.logServer running on port ${PORT});
}); Limited Local Testing
You can run the app locally to check that it starts without errors, but you won't be able to send SMS messages yet. The Vonage Messages API needs to reach your webhook URLs to verify requests and send status updates. That's why we're deploying to Cloud Run first.
If you want to verify the app runs, run the JavaScript file.
node index.jsOpen http://localhost:3000 to see the form. The app should start without errors, but sending messages will fail until we deploy and configure the webhooks.
Deploy to Google Cloud Run
Now that the app works locally, let's deploy it to Google Cloud Run, so it's accessible on the internet and can receive webhooks from Vonage.
Set Up Google Cloud
If you don't have a Google Cloud account yet, create one as required in the prerequisites.
Install the Google Cloud CLI
Download and install the Google Cloud CLI for your operating system. In the next subsection, I’ll show how to do it on macOS, but you can refer to the link above for other OSes. I wanted to show the steps I’ve done myself because I ran into some errors, and share some tips that might help.
On macOS
# Download the archive (Apple Silicon)
curl -O https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-cli-darwin-arm.tar.gz
# Extract it
tar -xzf google-cloud-cli-darwin-arm.tar.gz
# Run the install script
./google-cloud-sdk/install.shIn case there’s a Python version error: the gcloud CLI requires Python 3.10 or higher. If you see a TypeError about unsupported operand type(s) for |, your Python is too old. Install a newer version with Homebrew as shown below (or any other way you prefer) and point gcloud to it:
brew install python@3.12
export CLOUDSDK_PYTHON=$(brew --prefix python@3.12)/bin/python3.12
./google-cloud-sdk/install.shThe install script will ask if you want to add gcloud to your PATH. Choose yes. Then restart your command prompt/ terminal or run:
source ~/.zshrcNow initialize gcloud:
gcloud initThis will open a browser window to log in to your Google account and select or create a new Google Cloud project.
Create a Google Cloud Project
If you don't have a project yet, create one. The Project IDs must be globally unique, so you can add some random characters.
gcloud projects create vonage-sms-yourname --name="Vonage Messages API Demo"
gcloud config set project vonage-sms-yournameYou can also create a project from the Google Cloud Console.
Enable a Google Cloud Billing Account
Cloud Run requires billing to be enabled. Go to the Billing page and link a billing account to your project.
Enable Required Google Cloud APIs
Enable the Cloud Build and Cloud Run APIs:
gcloud services enable cloudbuild.googleapis.com run.googleapis.com Deploy to Google Cloud Run
For production applications, consider using Google Secret Manager to store sensitive values. For this tutorial, we'll pass environment variables directly.
Make sure your “private.key” file is in the project directory. It gets bundled with your source code during deployment.
Deploy:
gcloud run deploy vonage-sms \
--source . \
--region us-central1 \
--allow-unauthenticated \
--set-env-vars "VONAGE_APPLICATION_ID=your_app_id" \
--set-env-vars "VONAGE_NUMBER=444155551234" \
--set-env-vars "VONAGE_API_SIGNATURE_SECRET=your_signature_secret"First deploy: you'll see a prompt about creating an Artifact Registry repository named cloud-run-source-deploy to store your container images. Type y to continue.
The first deployment takes a couple of minutes. When it's done, you'll see a URL like https://vonage-sms-abc123-uc.a.run.app.
Update Vonage Webhooks
Now that you have your Cloud Run URL, go back to your Vonage Application and update the webhook URLs:
Inbound URL: https://your-cloud-run-url/webhooks/inbound
Status URL: https://your-cloud-run-url/webhooks/status
Don't forget to click Save changes at the bottom right of the page.
Test It Out
It’s time to test everything we’ve been setting up and see things running!
Send an SMS
Open your Cloud Run URL in a browser (the URL you got after deployment, like https://vonage-sms-abc123-uc.a.run.app). You should see the SMS form we built. Enter your phone number and a message, then press send. If everything is configured correctly, you'll receive the SMS on your phone within a few seconds. You can check country-specific features and restrictions.
Receive an SMS
Now test the other direction. Send an SMS from your phone to the Vonage number you purchased and linked to the application you created. This triggers the inbound webhook we set up. You can check the logs in two places:
From the Command Line
gcloud run logs read vonage-sms --region us-central1 From the Vonage Dashboard
Go to your Vonage Application, click on your application, and check the logs section to see message activity and any webhook errors. You should see your inbound message logged with the sender's number and text.
Conclusion
You've built and deployed an SMS application on Google Cloud Run using the Vonage Messages API. The app can send messages through a web form and receive incoming messages through webhooks.
¿Tienes alguna pregunta o algo que compartir? Únete a la conversación en Slack de la comunidad de Vonagey mantente actualizado con el Boletín para desarrolladoressíguenos en X (antes Twitter)suscríbete a nuestro canal de YouTube para ver tutoriales en video, y sigue la página de página para desarrolladores de Vonage en LinkedInun espacio para que los desarrolladores aprendan y se conecten con la comunidad. Mantente conectado, comparte tu progreso y entérate de las últimas noticias, consejos y eventos para desarrolladores.