code examples
code examples
How to Send SMS with Vonage API in Node.js: Complete Express Tutorial
Learn how to send SMS with Vonage API using Node.js and Express. Step-by-step tutorial with @vonage/server-sdk 3.24.1, delivery receipts, error handling, and production deployment guide.
How to Send SMS Messages with Vonage API in Node.js Express
Learn how to send SMS messages with Vonage SMS API using Node.js and Express. This complete guide walks you through building a production-ready SMS application with @vonage/server-sdk 3.24.1, covering secure API credential management, error handling, delivery receipt tracking, and testing best practices.
You'll create a functional Express SMS server with a REST API endpoint that accepts a recipient phone number and message text, then delivers SMS messages reliably using the Vonage API. This Node.js SMS integration works for notifications, alerts, appointment reminders, or two-factor authentication (though Vonage's Verify API is purpose-built for 2FA workflows).
This tutorial uses Vonage's official Node.js SDK (@vonage/server-sdk) with comprehensive error handling for delivery receipts (DLRs) and message status tracking.
Current Versions (as of 2024–2025):
- Node.js: v22 LTS (Active LTS until October 2025)
- Express.js: 5.1.0 (requires Node.js 18 or higher)
- @vonage/server-sdk: 3.24.1
Project Overview: Building a Vonage SMS API Integration
What You'll Build:
A Node.js Express server with a single API endpoint (POST /send-sms). This endpoint receives a destination phone number and text message body, then uses the Vonage Node.js SDK to send SMS messages programmatically.
Problem Solved:
Integrate SMS sending capabilities into Node.js applications quickly and reliably using Vonage's enterprise-grade communication platform.
Technologies Used:
| Technology | Purpose | Version |
|---|---|---|
| Node.js | JavaScript runtime for server-side applications | v22 LTS |
| Express.js | Minimal web framework for creating the API endpoint | 5.1.0 |
| Vonage SMS API | Communication Platform as a Service (CPaaS) for sending SMS | Latest |
| @vonage/server-sdk | Official Vonage Node.js SDK | 3.24.1 |
| dotenv | Loads environment variables from .env into process.env, keeping credentials secure | Latest |
System Architecture:
- A client (e.g., Postman, curl, another application) sends a
POSTrequest to the/send-smsendpoint. - Express parses the request body to extract the recipient number and message text.
- The server uses the Vonage Node.js SDK (configured with your API credentials) to send a request to the Vonage SMS API.
- Vonage processes the request and sends the SMS message to the recipient's phone number.
- Vonage returns a response to your server, which sends a response back to the client.
sequenceDiagram
participant Client
participant Express
participant Vonage API
participant Recipient
Client->>Express: POST /send-sms
Express->>Vonage API: vonage.sms.send()
Vonage API->>Recipient: SMS delivery
Vonage API-->>Express: Response (status, message-id)
Express-->>Client: JSON responsePrerequisites: What You Need to Send SMS with Vonage
Prerequisites:
- Node.js and npm: Install from nodejs.org
- Vonage API Account: Sign up at Vonage API Dashboard – new accounts receive free testing credit
- Vonage API Key and Secret: Find these on your Vonage API Dashboard main page
- Vonage Phone Number: Rent a virtual number from Vonage. Go to
Numbers>Buy numbersin the Vonage Dashboard. Ensure the number supports SMS in your target region - Verified Test Phone Number (for trial accounts): Trial accounts can only send SMS to verified numbers. Add and verify numbers in the Sandbox / Test Numbers page
- Text Editor or IDE: VS Code, Sublime Text, or WebStorm
- Basic terminal/command line knowledge
Step 1: Set Up Your Vonage Node.js SMS Project
Initialize your Node.js project and install the necessary dependencies.
-
Create a Project Directory:
bashmkdir vonage-sms-guide cd vonage-sms-guide -
Initialize the Node.js Project: Create a
package.jsonfile. The-yflag accepts default settings.bashnpm init -y -
Install Dependencies: Install
express,@vonage/server-sdk, anddotenv.bashnpm install express @vonage/server-sdk dotenv -
Create Core Files:
bash# On macOS/Linux touch index.js .env .gitignore # On Windows (Command Prompt) type nul > index.js type nul > .env type nul > .gitignore # On Windows (PowerShell) New-Item index.js -ItemType File New-Item .env -ItemType File New-Item .gitignore -ItemType File -
Configure Environment Variables (
.env): Open.envand add your Vonage API credentials and rented number.VONAGE_API_KEY: Your API key from the Vonage DashboardVONAGE_API_SECRET: Your API secret from the Vonage DashboardVONAGE_FROM_NUMBER: Your virtual phone number in E.164 format without spaces (e.g.,14155550100)PORT: The port your Express server listens on (e.g.,3000)
plaintext# .env VONAGE_API_KEY=YOUR_VONAGE_API_KEY VONAGE_API_SECRET=YOUR_VONAGE_API_SECRET VONAGE_FROM_NUMBER=YOUR_VONAGE_VIRTUAL_NUMBER PORT=3000Important: Replace placeholder values with your actual credentials.
-
Configure Git Ignore (
.gitignore): Prevent committing sensitive environment variables andnode_modules.plaintext# .gitignore node_modules .env
Your project structure:
vonage-sms-guide/
├── index.js
├── package.json
├── .env
└── .gitignore
Step 2: Implement Vonage SMS API with Node.js and Express
Write the code for your Express server in index.js.
-
Require Dependencies and Load Environment Variables:
javascript// index.js const express = require('express'); const { Vonage } = require('@vonage/server-sdk'); require('dotenv').config(); // Check if essential environment variables are set if (!process.env.VONAGE_API_KEY || !process.env.VONAGE_API_SECRET || !process.env.VONAGE_FROM_NUMBER) { console.error('Error: Missing Vonage API credentials or FROM number in .env file.'); process.exit(1); }Why
dotenv.config()first? It must run before accessingprocess.envvariables from.env. The code checks that critical variables load successfully. -
Initialize Express App and Vonage Client: Create Express and Vonage SDK instances using environment variables.
javascript// index.js (continued) const app = express(); const port = process.env.PORT || 3000; const vonage = new Vonage({ apiKey: process.env.VONAGE_API_KEY, apiSecret: process.env.VONAGE_API_SECRET }); -
Add Middleware: Configure Express to parse JSON request bodies.
javascript// index.js (continued) app.use(express.json()); app.use(express.urlencoded({ extended: true })); -
Create the SMS Sending Endpoint (
/send-sms): Define aPOSTroute to handle SMS sending requests.javascript// index.js (continued) app.post('/send-sms', async (req, res) => { // Basic input validation const { to, text } = req.body; if (!to || !text) { return res.status(400).json({ success: false, message: 'Missing `to` or `text` parameter in request body.' }); } const from = process.env.VONAGE_FROM_NUMBER; try { const resp = await vonage.sms.send({ to, from, text }); console.log('Message sent successfully:', resp); // Status '0' indicates successful submission to the Vonage network, not delivery to the handset. // DLR statuses include: DELIVRD (delivered), UNDELIV (undelivered), EXPIRED, FAILED, REJECTD, DELETED, UNKNOWN. if (resp.messages && resp.messages.length > 0 && resp.messages[0].status === '0') { res.status(200).json({ success: true, message: 'SMS submitted successfully.', messageId: resp.messages[0]['message-id'] }); } else { console.error('Vonage API reported an issue:', resp); const errorText = (resp.messages && resp.messages.length > 0) ? resp.messages[0]['error-text'] : 'Unknown Vonage API error'; res.status(500).json({ success: false, message: `Failed to send SMS. Vonage error: ${errorText}`, details: resp }); } } catch (error) { console.error('Error sending SMS:', error); res.status(500).json({ success: false, message: 'Internal server error while sending SMS.', error: error.message }); } });Key Points:
- Define an
asyncfunction to useawaitfor the asynchronousvonage.sms.sendcall. - Basic validation checks if
toandtextare present in the request body. - Retrieve the
fromnumber from environment variables. vonage.sms.send({ to, from, text })makes the API call.- A
try...catchblock handles potential network errors or issues within the SDK call. - Inspect the
respobject from Vonage. Astatusof'0'indicates successful submission to the network. Non-zero statuses indicate errors (e.g., invalid number, insufficient funds). Return the Vonagemessage-idon success. - Send appropriate JSON responses (success or error) back to the client with relevant status codes (200, 400, 500).
- Define an
-
Start the Server: Make the Express application listen for incoming requests on the configured port.
javascript// index.js (continued) app.listen(port, () => { console.log(`Server listening at http://localhost:${port}`); console.log(`SMS sending endpoint available at POST http://localhost:${port}/send-sms`); });
Your index.js file is now complete.
Step 3: Test Your Vonage SMS Integration
Run the server and test the SMS sending functionality.
-
Run the Server: Open your terminal in the project directory and run:
bashnode index.jsYou should see output indicating the server is running:
Server listening at http://localhost:3000 SMS sending endpoint available at POST http://localhost:3000/send-sms -
Test with
curlor Postman: Usecurl(command-line) or Postman (GUI) to send aPOSTrequest to your endpoint.Using
curl: ReplaceYOUR_RECIPIENT_NUMBERwith the phone number you want to send the SMS to (use a verified number for trial accounts). Format the number including the country code (e.g.,14155550123).bashcurl -X POST http://localhost:3000/send-sms \ -H 'Content-Type: application/json' \ -d '{ "to": "YOUR_RECIPIENT_NUMBER", "text": "Hello from your Vonage Node.js App!" }'Using Postman:
-
Create a new request.
-
Set the method to
POST. -
Enter the URL:
http://localhost:3000/send-sms. -
Go to the
Bodytab, selectraw, and chooseJSONfrom the dropdown. -
Enter the JSON payload:
json{ "to": "YOUR_RECIPIENT_NUMBER", "text": "Hello from your Vonage Node.js App!" } -
Click
Send.
-
-
Check the Response:
-
Successful Submission: You should receive a JSON response with a
200 OKstatus:json{ "success": true, "message": "SMS submitted successfully.", "messageId": "some-message-id-from-vonage" }Check the recipient phone – the SMS should arrive shortly. You should also see confirmation logs in the terminal where
node index.jsis running. -
Error Response: If something goes wrong (e.g., invalid credentials, incorrect 'to' number format, trial account restrictions), you'll get an error response with a non-200 status code:
json// Example: Missing parameter { "success": false, "message": "Missing `to` or `text` parameter in request body." }json// Example: Vonage API error (e.g., non-whitelisted number) { "success": false, "message": "Failed to send SMS. Vonage error: Non White-listed Destination - rejected", "details": { /* ... full Vonage response ... */ } }json// Example: Internal server error { "success": false, "message": "Internal server error while sending SMS.", "error": "Some specific error message" }Check the terminal logs for more detailed error information.
-
Step 4: Handle Vonage SMS API Errors and Delivery Receipts
Your current implementation includes basic try...catch blocks and logs errors to the console. For production systems, implement:
- Structured Logging: Use libraries like
WinstonorPinofor structured logging (e.g., JSON format), which makes logs easier to parse and analyze, especially when sending them to log aggregation services (like Datadog, Splunk, ELK stack). - Centralized Logging: Configure your logger to send logs to a centralized platform instead of just
console.log. - More Granular Error Handling: Check specific Vonage error codes (returned in the
error-textor status fields) to provide more informative feedback or trigger specific actions (e.g., retry logic for temporary network issues, alerts for authentication failures). Common error codes include:- Error Code 15 (Rejection Code 10 for SMPP): "Illegal Sender" – occurs when sending SMS to the US or Canada without a US pre-approved long number, toll-free, 10DLC, or short code associated with your Vonage account.
- Error Code 99: "General Error" – indicates a request was processed but failed due to various factors; check DLR details for specifics.
- Non-zero status codes: Any status code other than '0' in the initial response indicates submission failure.
- Delivery Receipts (DLRs): Sending the message successfully (status '0') only means Vonage accepted it for submission. To confirm delivery to the handset, set up a webhook endpoint to receive DLRs from Vonage. DLRs provide statuses like DELIVRD (delivered), UNDELIV (undelivered), EXPIRED, FAILED, REJECTD, DELETED, or UNKNOWN. Refer to the Vonage SMS API documentation and DLR Status documentation for complete error code listings.
Step 5: Secure Your Vonage API Credentials
- API Key Security: Never commit your
.envfile or hardcode API keys/secrets directly in your source code. Use environment variables and ensure.envis in your.gitignore. In production environments, use your hosting provider's mechanism for managing secrets (e.g., AWS Secrets Manager, Heroku Config Vars, Kubernetes Secrets). - Input Validation: Your current validation is minimal. In a real application, perform more robust validation on the
tophone number (e.g., check format using a library likelibphonenumber-jsversion 1.11+ with metadata synced to September 2025, ~145 KB max metadata) and sanitize thetextinput to prevent potential injection attacks if the text is ever displayed elsewhere. - Rate Limiting: Protect your endpoint from abuse by implementing rate limiting (e.g., using
express-rate-limit). This prevents users from sending excessive numbers of messages rapidly. - Authentication/Authorization: The current endpoint is open. In a real application, protect this endpoint, ensuring only authorized users or services can trigger SMS sending. This might involve API keys, JWT tokens, or session-based authentication added as middleware to the Express route.
Step 6: Troubleshoot Common Vonage SMS API Issues
| Issue | Solution |
|---|---|
| Non-Whitelisted Destination Error | Add and verify recipient numbers in your Vonage Sandbox / Test Numbers page. Upgrade your account (add payment details) to send to any number. |
| Invalid Credentials | Double-check that VONAGE_API_KEY and VONAGE_API_SECRET in your .env file are correct and have no extra spaces. |
Incorrect FROM Number | Ensure VONAGE_FROM_NUMBER is a valid number you rented from Vonage in the correct format (e.g., 14155550100). |
| Insufficient Funds | Check your balance in the dashboard. If your Vonage account runs out of credit, sending will fail. |
| Carrier Filtering | Mobile carriers might filter messages, especially if they appear spammy. Ensure your content is appropriate and consider using Alphanumeric Sender IDs (where supported) or Short Codes for higher volume/better deliverability. |
| SDK/API Changes | While @vonage/server-sdk is stable, always refer to the official Vonage documentation for the latest methods and response structures. |
| SMS API vs. Messages API | This guide uses the simpler Vonage SMS API flow via vonage.sms.send(). For multi-channel messaging (WhatsApp, Facebook Messenger, MMS) or advanced features, explore the Vonage Messages API with vonage.messages.send(). |
Step 7: Deploy Your Vonage Node.js SMS Application
Deploy this application on a server or platform (like Heroku, Render, AWS EC2, Google Cloud Run, etc.). Key steps include:
- Environment Variables: Set
VONAGE_API_KEY,VONAGE_API_SECRET, andVONAGE_FROM_NUMBERas environment variables on your chosen hosting platform. Do not upload the.envfile. - Dependencies: Ensure
npm installruns in the deployment environment to install dependencies. - Starting the App: Configure the platform to run your application using
node index.js. - Port: Ensure your application listens on the port assigned by the hosting environment (often provided via a
PORTenvironment variable, which your code already handles).
A Procfile for platforms like Heroku:
web: node index.jsComplete Vonage SMS Code Example
The complete code for this guide includes index.js, package.json, .gitignore, and a .env.example file.
Frequently Asked Questions About Vonage SMS with Node.js
How do I send SMS with Vonage in Node.js?
Install @vonage/server-sdk (version 3.24.1 for 2025) and create a Vonage client with your API key and secret. Use vonage.sms.send({ to, from, text }) to send messages. You need a Vonage account, API credentials, and a rented virtual number. The complete setup requires Express for the REST endpoint, dotenv for credential management, and proper error handling for production use.
What does Vonage status code 0 mean?
Status code '0' indicates successful submission to the Vonage network, not delivery to the recipient's handset. To confirm actual delivery, implement webhook endpoints to receive Delivery Receipts (DLRs) from Vonage. DLR statuses include: DELIVRD (delivered), UNDELIV (undelivered), EXPIRED, FAILED, REJECTD, DELETED, and UNKNOWN.
What is Vonage Error Code 15?
Error Code 15 (Rejection Code 10 for SMPP) means "Illegal Sender" – this occurs when sending SMS to the US or Canada without a US pre-approved long number, toll-free, 10DLC, or short code associated with your Vonage account. To resolve this, obtain the appropriate number type for US/Canada SMS delivery through your Vonage Dashboard.
What is Vonage Error Code 99?
Error Code 99 indicates a "General Error" – meaning the request was processed but failed due to various factors. Check the Delivery Receipt (DLR) details for specifics about why the message failed. This error requires examining the error-text field in the response and consulting the Vonage SMS API error documentation for detailed troubleshooting.
What version of @vonage/server-sdk should I use in 2025?
Use @vonage/server-sdk version 3.24.1 (latest as of early 2025) with Node.js v22 LTS and Express 5.1.0. Install with npm install @vonage/server-sdk@3.24.1. This version provides stable SMS API functionality with improved error handling. Always check npm for the latest version.
How do I handle the "Non-Whitelisted Destination" error?
This is the most common error for Vonage trial accounts. Trial accounts can only send SMS to verified numbers. Add and verify recipient numbers in your Vonage Sandbox / Test Numbers page. To send to any number, upgrade your account by adding payment details in the Vonage Dashboard.
What are Delivery Receipts (DLRs) in Vonage SMS?
Delivery Receipts (DLRs) are webhook notifications from Vonage confirming whether your SMS was delivered to the recipient's handset. DLRs provide statuses like DELIVRD (delivered), UNDELIV (undelivered), EXPIRED, FAILED, REJECTD, DELETED, or UNKNOWN. Implement a webhook endpoint to receive DLRs for reliable message tracking. See the DLR Status documentation.
Should I use Vonage SMS API or Messages API?
For simple SMS sending with Node.js Express, use the SMS API via vonage.sms.send() with API Key/Secret authentication (covered in this guide). For multi-channel messaging (WhatsApp, Facebook Messenger, MMS) or advanced features, use the Vonage Messages API with vonage.messages.send(), which requires Application ID and Private Key authentication.
How do I validate phone numbers before sending SMS with Vonage?
Use libphonenumber-js version 1.11+ (with metadata synced to September 2025, ~145 KB max metadata) to validate phone number format before calling the Vonage API. Install with npm install libphonenumber-js and parse numbers to E.164 format. This prevents API errors from invalid phone numbers and improves delivery rates.
Can I send SMS from a Vonage trial account?
Yes, but with restrictions. Trial accounts receive free testing credit but can only send SMS to verified numbers added in the Sandbox / Test Numbers page. Upgrade your account (add payment details) to send SMS to any number. Trial accounts are perfect for development and testing before production deployment.
Next Steps: Enhancing Your Vonage SMS Integration
You've successfully built a Node.js application capable of sending SMS messages using Express and the Vonage API.
From here, you could:
- Implement webhook endpoints to receive incoming SMS messages or delivery receipts.
- Integrate this functionality into a larger application.
- Add more robust error handling, logging, and monitoring.
- Build a frontend interface to interact with the API.
- Explore the Vonage Messages API for multi-channel communication.
Frequently Asked Questions
How to send SMS with Node.js and Express?
Use the Vonage API and Express.js framework within your Node.js application. This involves setting up a POST route in Express to handle requests, and then utilizing the Vonage Node.js SDK to send messages via their SMS API. The server receives the recipient's number and message text, then uses Vonage to deliver the SMS.
What is the Vonage API used for in Node.js?
The Vonage API, a Communication Platform as a Service (CPaaS), enables sending SMS messages programmatically. In Node.js, you interact with it using the Vonage Node.js Server SDK, which simplifies sending SMS messages, managing two-factor authentication, and other communication tasks. The article provides a tutorial on its usage for sending SMS.
Why use dotenv in a Node.js SMS project?
Dotenv is a crucial module for storing sensitive information such as API keys and secrets as environment variables within a `.env` file. It's instrumental in keeping these credentials secure and outside your main codebase, protecting them from accidental exposure through version control systems like Git.
When should I use Vonage Verify API instead of SMS?
While you can use the Vonage SMS API for two-factor authentication (2FA), Vonage's Verify API is often better suited for this specific purpose. It provides more advanced 2FA features and simplifies the process, streamlining security implementations.
How to set up Vonage API credentials in Node.js?
Store your Vonage `API_KEY`, `API_SECRET`, virtual `FROM_NUMBER`, and `PORT` within a `.env` file. Then, use `dotenv.config()` in your `index.js` file to load these variables into your Node.js environment so your application can use them to authenticate with Vonage and send messages.
What Node.js packages are required for sending SMS with Vonage?
You'll need `express` for creating the API endpoint, `@vonage/server-sdk` to interact with the Vonage APIs, and `dotenv` to manage your Vonage API credentials securely as environment variables.
How to create an SMS API endpoint with Express?
Define a `POST` route handler in your Express app, typically at `/send-sms`. This endpoint receives the recipient's number (`to`) and the message body (`text`) as parameters in the request. Inside the handler, use the Vonage SDK to send the message using the provided parameters.
Why does Vonage SMS API sometimes return status 0 even if delivery fails?
A '0' status from the Vonage SMS API usually indicates successful message *submission* to the network, not final delivery to the recipient. To get confirmed delivery status, you need to implement delivery receipts (DLRs) using webhooks. These provide real-time updates on the message status as it progresses.
Can I send SMS to any number with a Vonage trial account?
No, trial accounts have restrictions. You can only send SMS to numbers you've specifically verified in the Vonage dashboard's Sandbox / Test Numbers page. To lift this restriction, you must upgrade to a paid Vonage account.
What is the purpose of the Vonage FROM_NUMBER?
The `VONAGE_FROM_NUMBER` is your designated Vonage Virtual Number, which acts as the sender ID for your outgoing SMS messages. This number is what recipients will see as the source of the SMS.
How to handle errors when sending SMS messages with Vonage API?
The example code uses basic `try...catch` blocks. For production, use libraries like Winston or Pino for structured logs and send them to centralized logging services. Implement more detailed error handling by checking Vonage error codes (like 'Non White-listed Destination') returned in the API response and take appropriate actions (e.g., retries or alerts).
How to test my Vonage SMS integration locally?
Once your Express server is running, use tools like `curl` or Postman to send `POST` requests to the `/send-sms` endpoint. The request body should be JSON formatted with the recipient's number (`to`) and message (`text`). Ensure your trial account numbers are whitelisted in the Vonage dashboard.
What are important security considerations when using the Vonage SMS API?
Never expose your API keys directly in your code. Always use environment variables (`.env` file) and make sure this file is included in your `.gitignore`. In production, manage secrets securely using your platform's specific mechanisms. Also implement input validation to prevent potential injection vulnerabilities and use rate limiting to protect against abuse.