Frequently Asked Questions
Use the @vonage/server-sdk
and the messages.send()
method with your API credentials, application ID, private key, Vonage virtual number, and the recipient's number. The sender's number must be your Vonage virtual number linked to the application. This method handles the API call and provides a message UUID for tracking.
The Vonage Messages API is a unified API for sending and receiving messages across multiple channels like SMS, MMS, and WhatsApp. This tutorial focuses on using it for two-way SMS communication, enabling features such as notifications, customer support, and reminders.
Vonage uses webhooks to deliver incoming SMS messages to your application in real-time. When a message is sent to your Vonage virtual number, Vonage sends an HTTP POST request to your specified webhook URL containing the message details. Your server needs to listen on this URL.
The Vonage Application ID and private key are essential for authenticating with the Messages API, specifically when sending SMS messages or configuring webhooks. They ensure secure communication between your app and the Vonage platform.
Yes, by using ngrok, you can create a secure tunnel to your local development server, providing a public URL that Vonage can use to deliver webhooks. Make sure to update the inbound webhook URL in your Vonage application settings.
Create a POST route (e.g., '/webhooks/inbound') in your Express app. Vonage will send JSON data to this endpoint. Your code should parse this JSON, process the message details, and immediately respond with a 200 OK status. Any time-consuming operations should occur after acknowledging the webhook.
The .env
file stores environment variables, such as API keys, secrets, and configuration settings, keeping them separate from your code. The dotenv
package loads these variables into process.env
.
Vonage retries webhooks if it doesn't receive a quick 200 OK. Implement idempotent logic or use the messageId
to track processed messages, preventing duplicate actions if the webhook is delivered multiple times. Store the messageId
in your database.
Implement input validation and sanitization, verify webhook signatures, and use rate limiting to protect against abuse. Ensure HTTPS is used for webhooks, and never expose your API secrets or private keys in version control.
In the Vonage dashboard, navigate to your application settings. Under 'Link virtual numbers', find your purchased number and click 'Link'. This directs incoming messages to the application's webhooks.
The Vonage Messages API sends a JSON payload containing the sender's number (msisdn
), recipient number (to
), message content (text
), message ID (messageId
), timestamp (message-timestamp
), and other metadata. Ensure your 'Default SMS Setting' is set to Messages API in the Vonage dashboard.
Check your ngrok tunnel is active, verify the webhook URL in the Vonage dashboard matches your server route, confirm the HTTP method is POST, and ensure your server responds with 200 OK quickly. Check for firewall issues and correct credentials in your .env
file.
Build Two-Way SMS Messaging with Vonage, Node.js & Express
Build a production-ready Node.js SMS application with Express to handle two-way messaging using the Vonage Messages API. Send and receive SMS programmatically through webhooks, enabling customer communication without requiring app installation.
This complete guide covers Vonage Node.js integration, project setup, webhook configuration with ngrok, security best practices, error handling, and production deployment. You'll create a functional SMS messaging system that sends messages via API calls and receives inbound messages through Express webhooks.
Project Overview and Goals
Create a Node.js application that can:
Problem Solved: Interact with users via SMS – a direct and widely accessible communication method without requiring users to install a separate app.
Technologies Used:
@vonage/server-sdk
: Official Vonage Node.js SDK for interacting with the Vonage APIs. Current version: v3.24.1.dotenv
: Module to load environment variables from a.env
file intoprocess.env
.System Architecture:
The diagram shows a User's Phone communicating bi-directionally with the Vonage Platform via SMS. The Vonage Platform sends incoming messages to Your Node.js App via a Receive SMS Webhook (HTTP POST). Your Node.js App sends outgoing messages via a Send SMS API Call to the Vonage Platform.
Expected Outcome: A running Node.js application that sends SMS messages and logs incoming SMS messages received on a configured Vonage number.
Prerequisites:
1. Set Up Your Node.js SMS Project
Initialize your Node.js project and install the necessary dependencies.
1. Create Project Directory: Open your terminal and create a new directory for your project_ then navigate into it.
2. Initialize Node.js Project: Initialize the project using npm. This creates a
package.json
file.The
-y
flag accepts the default settings.3. Install Dependencies: Install Express for the web server_ the Vonage SDK_ and
dotenv
for managing environment variables.4. Install Development Dependencies (Optional but Recommended): Install
nodemon
to automatically restart the server upon file changes_ speeding up development.5. Configure
package.json
Scripts: Add scripts to yourpackage.json
for easily starting the server:6. Create Project Structure: Organize your code for better maintainability.
Create the
src
directory:7. Create
.gitignore
: Prevent committing sensitive information and unnecessary files. Create a.gitignore
file in the project root:8. Set Up Environment Variables (
.env
): Create a.env
file in the project root. Populate this with credentials obtained from Vonage in the next steps.Using
.env
keeps sensitive credentials out of your source code, making it more secure and easier to manage different configurations for development, staging, and production. Thedotenv
package loads these variables intoprocess.env
when the application starts.2. Configure Vonage Messages API Credentials
Configure your Vonage account and obtain the necessary credentials before writing code.
1. Obtain API Key and Secret:
.env
file forVONAGE_API_KEY
andVONAGE_API_SECRET
.2. Create a Vonage Application:
Vonage Applications act as containers for your communication configurations (like webhook URLs) and use a private/public key pair for authenticating certain API calls (like sending messages via the Messages API).
private.key
file downloads immediately. Save this file in the root of your project directory. Ensure the path inVONAGE_APPLICATION_PRIVATE_KEY_PATH
in your.env
file matches (./private.key
).http://example.com/webhooks/inbound
andhttp://example.com/webhooks/status
. Update these later when you set up ngrok and your server..env
file forVONAGE_APPLICATION_ID
.3. Link Your Vonage Number:
14155550100
) and paste it into your.env
file forVONAGE_NUMBER
.4. Set Default SMS API:
Vonage has two APIs for SMS: the older SMS API and the newer Messages API. Their webhook formats differ. Since you're using the Messages API SDK (
@vonage/server-sdk
) for sending, configure your account to send inbound webhooks using the Messages API format for consistency.5. Fill Remaining
.env
Variables:PORT
to3000
(or another port if you prefer).TO_NUMBER
to your personal mobile phone number (including country code, e.g.,12015550101
) for testing sending messages.Your
.env
file should now contain your specific credentials.3. Send SMS Messages with Vonage Node.js SDK
Create the script to send an outbound SMS message using the Vonage Messages API.
File:
src/send-sms.js
Explanation:
require('dotenv').config();
: Loads the variables from your.env
file intoprocess.env
.Vonage
client instance. Crucially, for the Messages API, authentication relies on theapplicationId
andprivateKey
. WhileapiKey
andapiSecret
aren't strictly required for this specific send call, including them is good practice as other SDK features might use them.vonage.messages.send()
: This is the core function from the SDK for sending messages via the Messages API.new SMS(...)
: We create an SMS message object specifying the text content, recipient (to
), and sender (from
). The sender must be your Vonage virtual number linked to the Application ID.async/await
andtry...catch
: We use modern JavaScript asynchronous patterns to handle the API call and implement basic error handling. A successful response includes amessageUuid
, which is useful for tracking.catch
block logs errors. In a production system, you'd integrate this with a proper logging framework (like Winston or Pino) and potentially an error tracking service (like Sentry).To Test Sending: Run the script from your terminal:
You should see output indicating success and receive an SMS on the phone number specified in
TO_NUMBER
. Check your terminal for any error messages if it fails.4. Receive Inbound SMS with Express Webhooks
Set up the Express server to listen for incoming SMS messages delivered by Vonage webhooks.
File:
src/server.js
Explanation:
express.json
,express.urlencoded
): Essential for parsing the incoming request body from Vonage, which is typically JSON./webhooks/inbound
Endpoint (POST): This is the route Vonage will call when an SMS arrives at your linked number.msisdn
for sender,to
for recipient,text
,messageId
,message-timestamp
). We use destructuring with renaming ('message-timestamp': timestamp
) to assign the timestamp value to a variable namedtimestamp
. Adjust these fields if using the older SMS API format.res.status(200).end()
: Vonage requires a quick200 OK
response to know the webhook was received successfully. Send this response before doing any lengthy processing (like database writes or external API calls) to avoid timeouts and retries from Vonage./webhooks/status
Endpoint (POST): Optional but recommended. Vonage sends delivery receipts (DLRs) and other status updates about outbound messages to this URL if configured./health
Endpoint (GET): A simple endpoint often used by monitoring systems to check if the application is running.app.listen
: Starts the Express server on the configured port.5. Expose Local Server with ngrok for Webhook Testing
Vonage needs a publicly accessible URL to send webhooks. During development,
ngrok
creates a secure tunnel to your local machine.Important: The ngrok free tier has limitations:
For production or longer development sessions, consider ngrok paid plans starting at $8/month for stable URLs and unlimited session duration.
1. Start Your Local Server: If it's not already running, start your Express server:
Using
nodemon
automatically restarts on changes. You should see "Server listening on port 3000...".2. Start ngrok: Open another terminal window/tab (leave the server running) and run:
Replace
3000
if you used a different port.3. Get ngrok URL: ngrok will display output similar to this:
https://<random-string>.ngrok.io
URL. This is your public URL. Note: Free tier URLs are temporary and change every 2 hours or when you restart ngrok.http://127.0.0.1:4040
) is a useful dashboard to inspect webhook requests ngrok receives.4. Update Vonage Application Webhooks:
https://<random-string>.ngrok.io
URL and append/webhooks/inbound
. Example:https://a1b2c3d4e5.ngrok.io/webhooks/inbound
https://<random-string>.ngrok.io
URL and append/webhooks/status
. Example:https://a1b2c3d4e5.ngrok.io/webhooks/status
POST
.6. Test Your Two-Way SMS Application
Now, let's test the complete two-way flow.
1. Ensure Services are Running:
npm run dev
) is running in one terminal.ngrok http 3000
is running in another terminal.2. Test Inbound SMS:
VONAGE_NUMBER
).http://127.0.0.1:4040
) to inspect the raw HTTP request received from Vonage.3. Test Outbound SMS (Again):
TO_NUMBER
phone./webhooks/status
endpoint.7. Implement Security for Production SMS Webhooks
While this guide covers basics, production applications require robust security.
express-validator
orjoi
to validate the structure and content ofreq.body
before processing. Sanitize any data before storing it in a database or displaying it to prevent XSS attacks.Authorization
header from the incoming webhook requestpayload_hash
(SHA-256 hash of the webhook payload) matches the computed hashexpress-rate-limit
can restrict the number of requests from a single IP address or based on other criteria..env
files or private keys to version control (.gitignore
helps). Use secure methods provided by your deployment platform (e.g., environment variable settings in Heroku, AWS Secrets Manager, etc.) to manage secrets in production.8. Handle Errors and Implement Logging
Production systems need better error handling and logging than simple
console.log
.winston
orpino
for structured logging (e.g., JSON format). This makes logs easier to parse, filter, and analyze in log aggregation tools (like Datadog, Splunk, ELK stack). Include request IDs to trace requests across services.200 OK
quickly. Your application logic must be idempotent (safe to run multiple times with the same input) or have mechanisms to detect and handle duplicate webhook deliveries (e.g., by checking themessageId
against recently processed messages in your database).sendSms
) to fail. Implement a retry strategy with exponential backoff for transient network errors when sending messages. Libraries likeaxios-retry
(if using axios directly) or custom logic can handle this.9. Design Your SMS Database Schema
For any real application, you'll want to store message history.
Conceptual Schema (
messages
table):id
(Primary Key, e.g., UUID or Auto-incrementing Integer)vonage_message_uuid
(VARCHAR, Unique) - Store themessageId
ormessageUuid
from Vonage. Crucial for tracking and preventing duplicates.direction
(ENUM('inbound', 'outbound')) - Track message flow.sender
(VARCHAR) - Phone number of the sender.recipient
(VARCHAR) - Phone number of the recipient.body
(TEXT) - The message content.status
(VARCHAR, e.g., 'submitted', 'delivered', 'failed', 'received') - Track message status (updated via status webhook for outbound).vonage_timestamp
(TIMESTAMP WITH TIME ZONE) - Timestamp from Vonage webhook (message-timestamp
).created_at
(TIMESTAMP WITH TIME ZONE) - When the record was created in your system.updated_at
(TIMESTAMP WITH TIME ZONE) - When the record was last updated.Implementation:
vonage_message_uuid
).10. Deploy Your SMS Application to Production
Deploying your Node.js application involves several steps.
General Steps:
VONAGE_*
credentials,PORT
, and database connection strings to the production environment. Do not deploy your.env
file.npm install --production
on the server to install only necessary dependencies.pm2
to run your Node.js application (node src/server.js
).pm2
handles restarts, clustering (for multi-core utilization), and log management. Example:pm2 start src/server.js --name vonage-sms-app
.https://your-app-domain.com/webhooks/inbound
).CI/CD Pipeline:
eslint
,prettier
).jest
,mocha
).11. Troubleshoot Common Vonage SMS Issues
/webhooks/inbound
,/webhooks/status
) and the method isPOST
.200 OK
Response: If your server doesn't respond quickly with200 OK
to webhooks, Vonage will retry, causing duplicate processing. Ensureres.status(200).end()
is called promptly.private.key
. Ensure the key file has the correct read permissions for your Node.js process.Messages API
vsSMS API
Mismatch: Ensure your Vonage account default setting matches the webhook format your code expects (we used Messages API). If you see unexpected webhook body formats, check this setting. The key timestamp field ismessage-timestamp
in the Messages API webhook.12. Access Complete Code Repository
A repository containing the complete code for this guide can be found here:
https://github.com/sent-dev/vonage-node-express-sms-guide
Frequently Asked Questions About Vonage SMS Integration
How do I send SMS with Vonage Messages API?
Use the
@vonage/server-sdk
package with your Application ID and private key. Initialize the Vonage client, create an SMS object with recipient, sender, and message text, then callvonage.messages.send()
. The API returns a message UUID for tracking.What's the difference between Vonage Messages API and SMS API?
The Messages API is Vonage's newer unified API supporting SMS, MMS, WhatsApp, and other channels with consistent webhook formats. The older SMS API only handles SMS. Use Messages API for new projects – it offers better integration and future-proofs your application for multi-channel messaging.
How do I secure Vonage webhooks in production?
Implement JWT signature verification using the Authorization header sent by Vonage. Decode the JWT with your signing secret and verify the payload_hash (SHA-256 hash). Add rate limiting with
express-rate-limit
, validate all input with libraries likejoi
, and always use HTTPS for webhook URLs.Why do I need ngrok for local Vonage webhook development?
Vonage webhooks require a publicly accessible HTTPS URL to deliver inbound messages. ngrok creates a secure tunnel from the internet to your local development server. The free tier provides 2-hour sessions with random URLs – sufficient for development but requiring webhook URL updates when restarting.
How much does it cost to send SMS with Vonage?
Vonage SMS pricing varies by destination country and message type. Costs typically range from $0.0035 to $0.10 per message depending on the recipient's location. Check the Vonage pricing page for current rates. Multi-part or Unicode messages may incur additional charges.
Can I use Vonage to send SMS internationally?
Yes, Vonage supports international SMS to 200+ countries. You'll need to purchase a virtual number appropriate for your sending region and ensure your account has sufficient credits. Some countries have specific sender ID requirements or restrictions – consult Vonage documentation for country-specific regulations.
How do I handle duplicate webhook deliveries from Vonage?
Vonage retries webhooks if it doesn't receive a 200 OK response quickly. Make your webhook processing idempotent by checking the
messageId
against recently processed messages in your database before taking action. Always send the 200 OK response immediately, then process the message asynchronously.What Node.js version should I use with Vonage SDK?
Use Node.js v22 LTS (recommended for 2025) or v20 LTS minimum. The
@vonage/server-sdk
v3.24.1 supports these LTS versions and provides the most stable experience with long-term support until 2027.Next Steps for Your Vonage SMS Application
Now that you understand Vonage two-way SMS messaging, you can:
For advanced features, explore the official Vonage Messages API documentation and join the Vonage Community Slack for support.
This guide provides a solid foundation for building two-way SMS interactions using Node.js, Express, and Vonage. Layer in robust security, error handling, logging, and testing as you move towards production deployment. Consult the official Vonage Messages API documentation for more advanced features and details).