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.envfile 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.jsonfile.The
-yflag accepts the default settings.3. Install Dependencies: Install Express for the web server_ the Vonage SDK_ and
dotenvfor managing environment variables.4. Install Development Dependencies (Optional but Recommended): Install
nodemonto automatically restart the server upon file changes_ speeding up development.5. Configure
package.jsonScripts: Add scripts to yourpackage.jsonfor easily starting the server:6. Create Project Structure: Organize your code for better maintainability.
Create the
srcdirectory:7. Create
.gitignore: Prevent committing sensitive information and unnecessary files. Create a.gitignorefile in the project root:8. Set Up Environment Variables (
.env): Create a.envfile in the project root. Populate this with credentials obtained from Vonage in the next steps.Using
.envkeeps sensitive credentials out of your source code, making it more secure and easier to manage different configurations for development, staging, and production. Thedotenvpackage loads these variables intoprocess.envwhen 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:
.envfile forVONAGE_API_KEYandVONAGE_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.keyfile downloads immediately. Save this file in the root of your project directory. Ensure the path inVONAGE_APPLICATION_PRIVATE_KEY_PATHin your.envfile matches (./private.key).http://example.com/webhooks/inboundandhttp://example.com/webhooks/status. Update these later when you set up ngrok and your server..envfile forVONAGE_APPLICATION_ID.3. Link Your Vonage Number:
14155550100) and paste it into your.envfile 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
.envVariables:PORTto3000(or another port if you prefer).TO_NUMBERto your personal mobile phone number (including country code, e.g.,12015550101) for testing sending messages.Your
.envfile 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.jsExplanation:
require('dotenv').config();: Loads the variables from your.envfile intoprocess.env.Vonageclient instance. Crucially, for the Messages API, authentication relies on theapplicationIdandprivateKey. WhileapiKeyandapiSecretaren'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/awaitandtry...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.catchblock 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.jsExplanation:
express.json,express.urlencoded): Essential for parsing the incoming request body from Vonage, which is typically JSON./webhooks/inboundEndpoint (POST): This is the route Vonage will call when an SMS arrives at your linked number.msisdnfor sender,tofor 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 OKresponse 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/statusEndpoint (POST): Optional but recommended. Vonage sends delivery receipts (DLRs) and other status updates about outbound messages to this URL if configured./healthEndpoint (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,
ngrokcreates 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
nodemonautomatically 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
3000if you used a different port.3. Get ngrok URL: ngrok will display output similar to this:
https://<random-string>.ngrok.ioURL. 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.ioURL and append/webhooks/inbound. Example:https://a1b2c3d4e5.ngrok.io/webhooks/inboundhttps://<random-string>.ngrok.ioURL and append/webhooks/status. Example:https://a1b2c3d4e5.ngrok.io/webhooks/statusPOST.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 3000is 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_NUMBERphone./webhooks/statusendpoint.7. Implement Security for Production SMS Webhooks
While this guide covers basics, production applications require robust security.
express-validatororjoito validate the structure and content ofreq.bodybefore processing. Sanitize any data before storing it in a database or displaying it to prevent XSS attacks.Authorizationheader from the incoming webhook requestpayload_hash(SHA-256 hash of the webhook payload) matches the computed hashexpress-rate-limitcan restrict the number of requests from a single IP address or based on other criteria..envfiles or private keys to version control (.gitignorehelps). 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.winstonorpinofor 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 OKquickly. 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 themessageIdagainst 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 (
messagestable):id(Primary Key, e.g., UUID or Auto-incrementing Integer)vonage_message_uuid(VARCHAR, Unique) - Store themessageIdormessageUuidfrom 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.envfile.npm install --productionon the server to install only necessary dependencies.pm2to run your Node.js application (node src/server.js).pm2handles 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 OKResponse: If your server doesn't respond quickly with200 OKto 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 APIvsSMS APIMismatch: 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-timestampin 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-sdkpackage 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
messageIdagainst 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-sdkv3.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.