code examples
code examples
Send SMS with Node.js, Express, and Vonage: A Developer Guide
A comprehensive guide on building a Node.js/Express application to send SMS messages using the Vonage API, covering setup, implementation, security, and deployment.
This guide provides a comprehensive walkthrough for building a Node.js application using the Express framework to send SMS messages via the Vonage API. We'll cover everything from project setup to deployment considerations, ensuring you have a robust foundation for integrating SMS capabilities into your applications.
By the end of this tutorial, you'll have a functional Express API endpoint capable of accepting a phone number and message, then using Vonage to deliver that message as an SMS. We prioritize clear steps, best practices, and production readiness.
Project Overview and Goals
What We're Building:
A simple RESTful API built with Node.js and Express. This API will expose a single endpoint (/send-sms) that accepts a POST request containing a recipient phone number and a message body. Upon receiving a valid request, the API will use the Vonage Node.js SDK to send the specified message to the recipient via SMS.
Problem Solved:
This project provides a foundational microservice or API component for applications needing to send transactional or notification SMS messages – for example, sending order confirmations, appointment reminders, or one-time passwords (though Vonage offers dedicated Verify APIs for OTPs).
Technologies Used:
- Node.js: A JavaScript runtime environment enabling server-side execution. Chosen for its vast ecosystem (npm), asynchronous nature suitable for I/O operations (like API calls), and popularity.
- Express: A minimal and flexible Node.js web application framework. Chosen for its simplicity, widespread adoption, and ease of setting up RESTful APIs.
- Vonage API: A communications platform-as-a-service (CPaaS) providing APIs for SMS, voice, video, and more. Chosen for its reliable SMS delivery and developer-friendly SDKs.
@vonage/server-sdk: The official Vonage Node.js SDK, simplifying interactions with the Vonage API.dotenv: A zero-dependency module that loads environment variables from a.envfile intoprocess.env. Chosen for secure management of API credentials outside of source code.
System Architecture:
+-------------+ +---------------------+ +-----------------+ +--------------+
| Client |------>| Express API Server |------>| Vonage API |------>| Mobile Phone |
| (e.g. curl,| | (Node.js /send-sms)| | (SMS Gateway) | | (Recipient) |
| Postman) | +---------------------+ +-----------------+ +--------------+
+-------------+ |
| Uses SDK with API Key/Secret
v
+------------------------+
| @vonage/server-sdk |
+------------------------+Expected Outcome & Prerequisites:
- Outcome: A running Node.js Express server with a
/send-smsendpoint that successfully sends an SMS via Vonage when called with valid parameters. - Prerequisites:
- Node.js and npm (or yarn) installed. (Download Node.js)
- A Vonage API account. (Sign up for free)
- A Vonage virtual phone number capable of sending SMS.
- Your Vonage API Key and API Secret.
- A text editor or IDE (e.g., VS Code).
- A tool for making HTTP requests (e.g.,
curl, Postman). - A personal phone number verified in your Vonage account to receive test messages (required for free trial accounts).
1. Setting up the Project
Let's initialize our Node.js project and install the necessary dependencies. These steps are generally the same across macOS, Linux, and Windows (using WSL or Git Bash).
-
Create Project Directory: Open your terminal or command prompt and create a new directory for your project, then navigate into it.
bash# Terminal mkdir vonage-sms-sender cd vonage-sms-sender -
Initialize Node.js Project: Initialize the project using npm. The
-yflag accepts default settings.bash# Terminal npm init -yThis creates a
package.jsonfile. -
Install Dependencies: Install Express, the Vonage Server SDK, and
dotenv.bash# Terminal npm install express @vonage/server-sdk dotenvexpress: The web framework.@vonage/server-sdk: The Vonage library.dotenv: For loading environment variables.
-
Create Project Files: Create the main application file and a file for environment variables.
bash# Terminal (Linux/macOS) touch index.js .env .gitignore # Terminal (Windows Command Prompt) type nul > index.js type nul > .env type nul > .gitignore # Terminal (Windows PowerShell) New-Item index.js -ItemType File New-Item .env -ItemType File New-Item .gitignore -ItemType File -
Configure
.gitignore: It's crucial to prevent sensitive information (like your.envfile) and unnecessary files (likenode_modules) from being committed to version control (e.g., Git). Open.gitignoreand add the following:text# .gitignore # Dependencies node_modules/ # Environment variables .env # Logs *.log npm-debug.log* yarn-debug.log* yarn-error.log* # Optional diagnostic data report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json # Optional editor directories and files .vscode/* !.vscode/settings.json !.vscode/tasks.json !.vscode/launch.json !.vscode/extensions.json .idea *.suo *.ntvs* *.njsproj *.sln *.sw?- Why
.gitignore? This file tells Git which files or directories to ignore, preventing accidental exposure of secrets and keeping your repository clean.
- Why
-
Project Structure: Your project directory should now look like this:
textvonage-sms-sender/ ├── .env ├── .gitignore ├── index.js ├── node_modules/ ├── package.json └── package-lock.json
2. Implementing Core Functionality (Vonage SDK)
Now, let's write the code to interact with the Vonage API using the SDK. We'll place this logic within our main index.js file for simplicity in this guide.
-
Initialize Vonage SDK: Open
index.js. At the top, require the necessary modules and initialize the Vonage SDK using credentials loaded from environment variables (which we'll define soon).javascript// index.js require('dotenv').config(); // Load environment variables from .env file const express = require('express'); const { Vonage } = require('@vonage/server-sdk'); // --- Vonage Client Initialization --- // Ensure you have VONAGE_API_KEY and VONAGE_API_SECRET in your .env file const vonage = new Vonage({ apiKey: process.env.VONAGE_API_KEY, apiSecret: process.env.VONAGE_API_SECRET }); // --- End Vonage Client Initialization --- // Express app setup will go here later...- Why
require('dotenv').config()first? This line must execute before accessingprocess.envvariables defined in your.envfile to ensure they are loaded. - Why SDK Initialization here? We initialize the Vonage client once when the application starts, rather than on every request, for efficiency. It uses the API Key and Secret for authentication.
- Why
-
Create SMS Sending Function: Let's encapsulate the SMS sending logic in an asynchronous function. This makes the code reusable and easier to manage.
javascript// index.js (continue below Vonage initialization) // --- SMS Sending Function --- async function sendSms(recipient, messageText) { const fromNumber = process.env.VONAGE_VIRTUAL_NUMBER; // Your Vonage virtual number if (!fromNumber) { throw new Error('VONAGE_VIRTUAL_NUMBER is not set in the environment variables.'); } try { const responseData = await vonage.sms.send({ to: recipient, from: fromNumber, text: messageText }); console.log('Vonage API Response:', JSON.stringify(responseData, null, 2)); // Check Vonage response for success if (responseData.messages[0]['status'] === '0') { console.log(`Message sent successfully to ${recipient}. Message ID: ${responseData.messages[0]['message-id']}`); return { success: true, messageId: responseData.messages[0]['message-id'] }; } else { const errorCode = responseData.messages[0]['status']; const errorText = responseData.messages[0]['error-text']; console.error(`Message failed with error code ${errorCode}: ${errorText}`); throw new Error(`Failed to send SMS: ${errorText} (Code: ${errorCode})`); } } catch (error) { console.error('Error sending SMS via Vonage:', error); // Re-throw the error to be caught by the API endpoint handler throw error; } } // --- End SMS Sending Function --- // Express app setup will go here...- Why
async/await? The Vonage SDK methods for network requests (like sending SMS) are asynchronous.async/awaitprovides a cleaner way to handle promises compared to.then().catch(). - Why
try...catch? Network requests can fail for various reasons (invalid credentials, network issues, Vonage errors). This block handles potential errors gracefully. - Why check
responseData.messages[0]['status'] === '0'? According to Vonage SMS API documentation, a status code of '0' indicates success for that specific message attempt. Other codes indicate errors, detailed inerror-text. - Why
throw error? In case of failure, we throw the error so the calling code (our API endpoint) knows something went wrong and can respond appropriately to the client.
- Why
3. Building the API Layer (Express)
Now, let's set up the Express server and create the /send-sms endpoint.
-
Initialize Express App: In
index.js, after thesendSmsfunction, initialize Express and add middleware to parse JSON request bodies.javascript// index.js (continue below sendSms function) // --- Express App Setup --- const app = express(); const PORT = process.env.PORT || 3000; // Use port from .env or default to 3000 // Middleware to parse JSON bodies app.use(express.json()); // Middleware to parse URL-encoded bodies (optional, but good practice) app.use(express.urlencoded({ extended: true })); // --- End Express App Setup --- // API Endpoint definition will go here... // Start server will go here...- Why
express.json()? This middleware is essential for parsing incoming requests withContent-Type: application/json. It makes the JSON payload available onreq.body.
- Why
-
Define the
/send-smsEndpoint: Create a POST route handler that takes the recipient number and message from the request body and uses oursendSmsfunction.javascript// index.js (continue below Express App Setup) // --- API Endpoint: /send-sms --- app.post('/send-sms', async (req, res) => { // Basic Input Validation const { to, message } = req.body; if (!to || !message) { return res.status(400).json({ success: false, message: 'Missing required fields: `to` and `message`.' }); } // Simple validation for phone number format (basic check) // For production, use a dedicated library like google-libphonenumber if (!/^\+?[1-9]\d{1,14}$/.test(to)) { return res.status(400).json({ success: false, message: 'Invalid phone number format. Use E.164 format (e.g., +14155552671).' }); } console.log(`Received request to send SMS to: ${to}, Message: "${message}"`); try { const result = await sendSms(to, message); console.log('SMS send attempt successful via API endpoint.'); res.status(200).json({ success: true, message: 'SMS sent successfully.', messageId: result.messageId }); } catch (error) { console.error('API Endpoint Error: Failed to send SMS.', error.message); // Send a generic server error response // Avoid exposing detailed internal error messages to the client res.status(500).json({ success: false, message: 'Failed to send SMS due to an internal server error.' }); } }); // --- End API Endpoint --- // Start server will go here...- Why
async (req, res)? The route handler needs to beasyncbecause itawaits thesendSmsfunction. - Why input validation? Never trust client input. Basic checks prevent errors and potential abuse. We check for presence and a very basic E.164 format.
- Why
try...catchhere too? This catches errors thrown bysendSms(including Vonage API errors or network issues) and allows us to send a standardized error response (HTTP 500) to the client.
- Why
-
Start the Server: Finally, add the code to start the Express server listening on the configured port.
javascript// index.js (at the very end) // --- Start Server --- app.listen(PORT, () => { console.log(`Server running on http://localhost:${PORT}`); // Log the current date/time when the server starts console.log(`Server started at: ${new Date()}`); }); // --- End Start Server ---
4. Integrating with Vonage (Credentials)
Securely managing your Vonage API credentials is vital.
-
Obtain Vonage Credentials:
- Log in to your Vonage API Dashboard.
- On the main dashboard page, you should see your API Key and API Secret. Copy these values.
- Navigate to ""Numbers"" > ""Your numbers"" in the left-hand menu.
- If you don't have a number, buy one suitable for sending SMS in your target region. Copy the virtual number (usually in E.164 format, e.g.,
14155550100). For the@vonage/server-sdk'ssendfunction, thefromfield usually doesn't require the+. Check the SDK documentation if unsure. - Trial Account Note: If you're on a free trial, navigate to the Vonage Dashboard settings or account overview section. Find the area for ""Test Numbers"" or ""Whitelisted Numbers"". You must add any recipient phone numbers here first before you can send SMS to them. You'll typically need to verify ownership via an SMS or call.
-
Configure Environment Variables: Open the
.envfile you created earlier and add your Vonage credentials and the desired port for your server. Never commit this file to Git.dotenv# .env - DO NOT COMMIT THIS FILE TO VERSION CONTROL # Vonage Credentials VONAGE_API_KEY=YOUR_VONAGE_API_KEY VONAGE_API_SECRET=YOUR_VONAGE_API_SECRET VONAGE_VIRTUAL_NUMBER=YOUR_VONAGE_VIRTUAL_NUMBER_NO_PLUS # Server Configuration PORT=3000- Replace
YOUR_VONAGE_API_KEY,YOUR_VONAGE_API_SECRET, andYOUR_VONAGE_VIRTUAL_NUMBER_NO_PLUSwith the actual values from your dashboard. Use the number without the leading+if that's what the SDK expects for thefromfield. - Why
.env? Keeps secrets out of your code repository, making it safer to share code and easier to manage configurations across different environments (development, staging, production).
- Replace
5. Error Handling and Logging
We've already implemented basic try...catch blocks and console.log/console.error. Let's refine this.
- Consistent Error Strategy: Our current strategy is:
sendSmsfunction catches specific Vonage errors, logs them internally, and throws a new error with a user-friendly message (or the Vonage error message).- The API endpoint
try...catchblock catches errors fromsendSmsor other processing steps. - The API endpoint logs the error internally (
console.error) and returns a generic HTTP 500 error to the client to avoid leaking implementation details. - For validation errors (missing fields, bad format), we return specific HTTP 400 errors.
- Logging:
console.logandconsole.errorare suitable for development.- Production Logging: For production, consider more robust logging libraries like Winston or Pino. These enable:
- Different log levels (debug, info, warn, error).
- Structured logging (e.g., JSON format), making logs easier to parse by machines.
- Sending logs to files, databases, or external logging services (like Datadog, Logstash, Papertrail).
- Example Log Points:
- Log incoming request details (path, method, sanitized body).
- Log outgoing requests to Vonage (recipient, message ID on success).
- Log errors with stack traces and context (e.g., request ID).
- Retry Mechanisms:
- The Vonage API itself handles some level of retries for SMS delivery.
- If your API call to Vonage fails due to a transient network issue (e.g., temporary connection error, non-4xx/non-5xx error if distinguishable), you could implement a simple retry logic within the
sendSmsfunction using libraries likeasync-retry. - Caution: Be careful not to retry on non-recoverable errors (like invalid credentials
401or invalid number400) or you might waste resources or get rate-limited. Don't retry sending the same message if Vonage returns a success status ('0') but the message isn't received – that's a delivery issue Vonage needs to handle. For basic sending, relying on Vonage's delivery mechanism is usually sufficient.
6. Database Schema and Data Layer
This specific project focuses solely on sending an SMS via an API call and does not require a database.
If you were building a system that needed to:
- Track sent messages.
- Queue messages for later sending.
- Store user preferences for notifications.
- Manage contacts.
You would then introduce a database (e.g., PostgreSQL, MongoDB) and a data layer (using an ORM like Prisma or Sequelize, or native drivers) to manage persistence. This is beyond the scope of this basic guide.
7. Security Features
Security is paramount, especially when handling API keys and potentially user data.
- Input Validation & Sanitization:
- We implemented basic validation in the
/send-smsendpoint (checking fortoandmessage, basic phone format). - Use a robust library like
google-libphonenumber(via its Node.js port) for comprehensive phone number validation and formatting. - Sanitize the
messagecontent if it's ever displayed elsewhere (e.g., in an admin dashboard) to prevent Cross-Site Scripting (XSS). Libraries likeDOMPurify(if rendering in HTML) or basic character escaping might be needed depending on context. For direct SMS sending, sanitization of the content is less critical unless Vonage flags specific patterns.
- We implemented basic validation in the
- API Key Security:
- Handled via
.envand.gitignore. Ensure your server environment variables are securely managed in production. - Never embed API keys or secrets directly in client-side code (JavaScript running in a browser). Your backend API acts as the secure intermediary.
- Handled via
- Rate Limiting:
- Protect your API endpoint from abuse and brute-force attacks. Use middleware like
express-rate-limit. - Example:
javascript
const rateLimit = require('express-rate-limit'); const limiter = rateLimit({ windowMs: 15 * 60 * 1000, // 15 minutes max: 100, // Limit each IP to 100 requests per windowMs message: 'Too many requests from this IP, please try again after 15 minutes' }); // Apply to the specific endpoint or globally app.use('/send-sms', limiter);
- Protect your API endpoint from abuse and brute-force attacks. Use middleware like
- HTTPS:
- Always use HTTPS in production to encrypt data in transit. Deploy behind a reverse proxy (like Nginx or Caddy) or use hosting platforms (like Heroku, Vercel, AWS Elastic Beanstalk) that handle TLS/SSL termination.
- Common Vulnerabilities: Protect against OWASP Top 10 vulnerabilities (e.g., Injection, Broken Authentication) through secure coding practices, framework features, and dependency updates.
8. Handling Special Cases
Real-world scenarios often involve edge cases.
- International Phone Numbers:
- Always expect and ideally store phone numbers in E.164 format (
+followed by country code and number, e.g.,+447700900000,+14155552671). Our basic validation encourages this. - Vonage generally requires E.164 format for the
tofield. Thefromnumber should be your Vonage virtual number.
- Always expect and ideally store phone numbers in E.164 format (
- SMS Character Limits & Encoding:
- Standard SMS messages using the GSM-7 character set are limited to 160 characters.
- Using characters outside GSM-7 (like many emojis or non-Latin characters) switches the encoding to UCS-2, reducing the limit to 70 characters per SMS segment.
- Long messages are automatically split into multiple segments by carriers (concatenated SMS), potentially costing more. Be mindful of message length. You might want to add validation or truncation logic based on expected character set and length.
- Vonage Trial Account Limitations:
- As mentioned, trial accounts can only send SMS to phone numbers verified and whitelisted in the Vonage dashboard. Ensure your recipient number is added if testing on a trial account. Error messages like ""Non-Whitelisted Destination"" indicate this issue.
- Delivery Status:
- This guide focuses on sending. To track delivery, you need to configure Delivery Receipts (DLRs). This involves setting up another webhook endpoint in your application where Vonage can POST status updates (e.g.,
delivered,failed,expired). This requires using the Messages API or setting up DLR webhooks for the SMS API in the Vonage dashboard.
- This guide focuses on sending. To track delivery, you need to configure Delivery Receipts (DLRs). This involves setting up another webhook endpoint in your application where Vonage can POST status updates (e.g.,
9. Performance Optimizations
For this simple service, performance bottlenecks are unlikely, but consider these general points:
- SDK Initialization: We correctly initialize the Vonage SDK once on startup. Avoid creating new
Vonageinstances per request. - Asynchronous Operations: Node.js and
async/awaithandle the I/O-bound nature of calling the Vonage API efficiently without blocking the main thread. - Resource Usage: Monitor Node.js process memory and CPU usage under load.
- Load Testing: Use tools like
k6,artillery, orApacheBench(ab) to simulate traffic to your/send-smsendpoint and identify potential bottlenecks in your server or rate limits hit on the Vonage side.- Example (
ab): Create a filepost_payload.jsonwith content like{ "to": "+1...", "message": "Test" }. Then run:bashab -n 100 -c 10 -p post_payload.json -T application/json http://localhost:3000/send-sms
- Example (
- Caching: Caching is not directly applicable to the act of sending a unique SMS but could be used if you were fetching contact details or templates before sending.
10. Monitoring, Observability, and Analytics
For production systems, knowing what's happening is crucial.
- Health Checks: Implement a simple health check endpoint.
Monitoring systems can ping this endpoint to verify the service is running.javascript
app.get('/health', (req, res) => { res.status(200).json({ status: 'UP', timestamp: new Date().toISOString() }); }); - Performance Metrics: Track key metrics:
- Request latency (average, p95, p99) for
/send-sms. - Request rate (requests per second/minute).
- Error rate (percentage of 5xx or 4xx responses).
- Node.js process metrics (CPU, memory, event loop lag).
- Use tools like Prometheus with
prom-clientor integrated Application Performance Monitoring (APM) solutions (Datadog, New Relic, Dynatrace).
- Request latency (average, p95, p99) for
- Error Tracking: Integrate services like Sentry or Bugsnag to capture, aggregate, and alert on application errors in real-time, providing much more context than simple console logs.
- Logging & Dashboards: Send structured logs (as mentioned in Section 5) to a centralized logging platform (ELK stack, Loki, Splunk, Datadog Logs). Create dashboards to visualize key metrics and log trends, helping you spot issues quickly.
11. Troubleshooting and Caveats
Common issues developers encounter:
- Error: 401 Unauthorized:
- Cause: Incorrect
VONAGE_API_KEYorVONAGE_API_SECRET. Double-check values in.envagainst the Vonage dashboard. Ensure.envis being loaded correctly (require('dotenv').config();is called early). - Solution: Verify credentials and restart the server.
- Cause: Incorrect
- Error: Non-Whitelisted Destination / Illegal Sender Address - rejected:
- Cause (Trial Account): Trying to send SMS to a number not added to the "Test Numbers" / "Whitelisted Numbers" list in your Vonage dashboard.
- Cause (Paid Account): The
fromnumber (VONAGE_VIRTUAL_NUMBER) might be incorrect, not SMS-capable, or not provisioned correctly in your account. Or, country-specific restrictions might apply. - Solution: Verify the recipient number is whitelisted (trial) or check the
fromnumber configuration and capabilities in the dashboard. Check Vonage documentation for country-specific sending rules.
- Error: Invalid Parameters / Missing Parameters:
- Cause: The request payload to Vonage is malformed (e.g., missing
to,from, ortext), or the phone number format is invalid. - Solution: Check the data being passed to
vonage.sms.send(). Ensuretois in E.164 format. Log the exact payload being sent for debugging.
- Cause: The request payload to Vonage is malformed (e.g., missing
- Environment Variables Not Loading:
- Cause:
require('dotenv').config()is called too late, the.envfile is in the wrong directory, or it has syntax errors. - Solution: Ensure
dotenv.config()is the first or among the first lines inindex.js. Verify the.envfile location and syntax. Addconsole.log(process.env.VONAGE_API_KEY)afterdotenv.config()to test loading during startup (remove this log for production).
- Cause:
- SDK Version Issues:
- Cause: Outdated or incompatible versions of
@vonage/server-sdkor Node.js. Sometimes type definition issues arise. - Solution: Ensure you are using a recent, stable version of the SDK compatible with your Node.js version. Check the SDK's documentation or issue tracker for compatibility notes or known issues related to specific Node.js or TypeScript versions. Run
npm update @vonage/server-sdk.
- Cause: Outdated or incompatible versions of
- SMS Not Received (but API says success):
- Cause: Carrier filtering, incorrect recipient number (but valid format), device issues (airplane mode, blocked number), country regulations.
- Solution: Double-check the recipient number. Test sending to a different number/carrier. Check Vonage's status page for incidents. Implement Delivery Receipts (DLRs) for detailed delivery status.
12. Deployment and CI/CD
Moving your application to a live environment.
- Deployment Environments: Choose a hosting platform:
- PaaS (Platform-as-a-Service): Heroku, Vercel (for serverless functions), Google App Engine, AWS Elastic Beanstalk. Often simpler for Node.js apps.
- IaaS (Infrastructure-as-a-Service): AWS EC2, Google Compute Engine, DigitalOcean Droplets. Require more manual server setup (Node.js installation, process management, reverse proxy).
- Containers: Dockerizing your application and deploying to Kubernetes, AWS ECS, Google Cloud Run.
- Environment Configuration:
- Crucially: Do not deploy your
.envfile. Production hosting platforms provide mechanisms to securely set environment variables (e.g., Heroku Config Vars, AWS Systems Manager Parameter Store, Docker secrets). ConfigureVONAGE_API_KEY,VONAGE_API_SECRET,VONAGE_VIRTUAL_NUMBER, andPORT(or let the platform assign it viaprocess.env.PORT) in your chosen platform's interface.
- Crucially: Do not deploy your
- Running in Production:
- Use a process manager like PM2 to keep your Node.js application running, manage restarts on crashes, and handle clustering for better performance. (
nodemonis generally for development only). - Modify
package.jsonscripts:json// package.json ""scripts"": { ""start"": ""node index.js"", // Production start command ""dev"": ""nodemon index.js"" // Development command (requires npm install --save-dev nodemon) } - Your deployment platform will typically run
npm start.
- Use a process manager like PM2 to keep your Node.js application running, manage restarts on crashes, and handle clustering for better performance. (
- CI/CD (Continuous Integration / Continuous Deployment):
- Automate testing and deployment using platforms like GitHub Actions, GitLab CI/CD, Jenkins, CircleCI.
- Basic Pipeline:
- Push code to Git repository (e.g.,
mainbranch). - CI server triggers.
- Install dependencies (
npm ci- usespackage-lock.json). - Run linters/formatters (
eslint,prettier). - Run automated tests (Unit, Integration).
- Build application (if needed, e.g., TypeScript compilation).
- Deploy to staging/production environment (e.g.,
heroku deploy,docker push,eb deploy).
- Push code to Git repository (e.g.,
- Rollback Procedures: Ensure your deployment strategy includes a way to quickly revert to a previous stable version if a deployment introduces critical bugs. Platforms often have built-in rollback features.
13. Verification and Testing
Ensuring your application works correctly.
-
Run the Application:
- Make sure your
.envfile is populated with correct credentials. - Start the server:
bash
# Terminal node index.js - You should see output similar to:
log
Server running on http://localhost:3000 Server started at: [Current Date and Time]
- Make sure your
-
Manual Verification (using
curl):- Open a new terminal window.
- Replace
+1xxxxxxxxxxwith your whitelisted test phone number (in E.164 format). - Replace
"Hello from Node.js and Vonage!"with your desired text.
bash# Terminal (replace number and message) curl -X POST http://localhost:3000/send-sms \ -H "Content-Type: application/json" \ -d '{ "to": "+1xxxxxxxxxx", "message": "Hello from Node.js and Vonage!" }'- Expected Success Response (Terminal running
curl):json{ "success": true, "message": "SMS sent successfully.", "messageId": "SOME_MESSAGE_ID_FROM_VONAGE" } - Expected Success Logs (Terminal running
node index.js):logServer running on http://localhost:3000 Server started at: [Current Date and Time] Received request to send SMS to: +1xxxxxxxxxx, Message: "Hello from Node.js and Vonage!" Vonage API Response: { ... detailed response from Vonage ... } Message sent successfully to +1xxxxxxxxxx. Message ID: SOME_MESSAGE_ID_FROM_VONAGE SMS send attempt successful via API endpoint. - Expected Outcome: You should receive the SMS on your test phone.
-
Manual Verification (Error Cases):
- Missing fields:
Expected Response (HTTP 400):bash
curl -X POST http://localhost:3000/send-sms -H "Content-Type: application/json" -d '{"to": "+1xxxxxxxxxx"}'json{"success":false,"message":"Missing required fields: `to` and `message`."} - Invalid Number Format:
Expected Response (HTTP 400):bash
curl -X POST http://localhost:3000/send-sms -H "Content-Type: application/json" -d '{"to": "invalid-number", "message": "test"}'json{"success":false,"message":"Invalid phone number format. Use E.164 format (e.g., +14155552671)."} - Non-Whitelisted Number (Trial Account): Attempt sending to a number not on your Vonage trial whitelist. You should observe an error logged in the
node index.jsterminal (likely related to "Non-Whitelisted Destination" or similar, depending on the exact Vonage API response) and receive an HTTP 500 response from your API:json{"success":false,"message":"Failed to send SMS due to an internal server error."}
- Missing fields:
Frequently Asked Questions
How to send SMS with Node.js and Express
Use the Vonage API and the @vonage/server-sdk package with your Express application. Create a POST endpoint and use the Vonage SDK to send SMS messages. Be sure to set up the proper environment variables, and don't forget to test thoroughly before deploying to production.
What is Vonage API used for in Node.js
The Vonage API is a communications platform that provides features such as sending SMS messages, making voice calls, and video interactions. The Vonage Node.js SDK simplifies the integration of these communication channels within your Node applications.
Why use dotenv for Vonage credentials
The dotenv package helps in managing sensitive data like API keys by loading them from a .env file. This ensures that your credentials are not hardcoded into your application and keeps them separate from your codebase.
How to install Vonage server SDK
The Vonage Server SDK can be easily installed using npm or yarn. Navigate to your project directory in your terminal and run the command 'npm install @vonage/server-sdk'. This will download and install the necessary files into your project's node_modules directory.
How to set up .gitignore for Node.js project
Create a .gitignore file in the root directory of your project. List the files and folders you want Git to ignore. Don't forget to include node_modules, .env, and any log or diagnostic files.
What is the purpose of package.json
The package.json file contains metadata about your Node.js project, including its name, dependencies, scripts, and version. It is essential for managing project dependencies and running various scripts within your project's lifecycle.
How to initialize Vonage client in Node.js
Initialize the Vonage client by requiring the Vonage package and passing in your API key and secret. These credentials should be stored as environment variables. Do not hardcode credentials directly into your application logic.
How to handle Vonage API error responses
Implement try-catch blocks around your API calls to handle errors gracefully. Check the status code in the response data, log the error, and return a user-friendly message to the client in case of failures.
How to validate phone number format in Node.js
Use a regular expression for basic phone number validation or leverage the google-libphonenumber library for comprehensive formatting and validation checks. Never trust user input.
Why use express.json() middleware
The express.json() middleware parses incoming JSON payloads from requests and makes them available in the req.body object. This is necessary when your API endpoint expects to receive data in JSON format.
How to structure Node.js Express API routes
Create functions to act as request handlers for different HTTP methods (GET, POST, PUT, DELETE) and specify the route paths. Structure your route handling logic to be modular and readable for better organization.
When to use a database with Vonage SMS API
A database may not be necessary for basic SMS sending functionality. Consider implementing persistent storage if you need to track messages, queue messages, or store user data such as preferences or contacts.
How to secure Vonage API credentials in production
Always store your Vonage API credentials as environment variables on your server or within the secure configuration options provided by your hosting platform. Never hardcode them directly into your source code.
What is the SMS character limit with Vonage
Standard GSM-7 encoded SMS messages have a 160-character limit. Messages exceeding this limit may be segmented, or if using UCS-2 encoding (for emojis and other special characters), the limit is 70 characters.
How to troubleshoot Vonage 401 unauthorized error
A 401 Unauthorized error usually indicates incorrect Vonage API credentials. Double-check your API key and secret in your .env file and server environment variables, ensuring dotenv is correctly configured.