code examples
code examples
Send SMS with Node.js and Vonage API: Complete Express Integration Guide 2025
Learn how to send SMS messages using Node.js, Express, and the Vonage SMS API. Step-by-step tutorial with code examples, error handling, authentication, and production deployment best practices.
Send SMS with Node.js and Vonage: A Developer Guide
Learn how to send SMS with Node.js using the Vonage SMS API and Express framework. This comprehensive tutorial walks you through building a production-ready REST API endpoint for programmatic text messaging, from initial setup to deployment, with complete code examples and best practices for authentication, error handling, and rate limiting.
By the end of this guide, you will have a functional Express API endpoint that accepts a recipient phone number and message content, then uses the Vonage Node SDK to send SMS messages globally.
If you're comparing SMS providers for your Node.js application, you may also want to explore sending SMS with Twilio and Node.js, Infobip SMS integration for Node.js, or Plivo Node.js SMS implementation to understand feature differences and pricing.
Key Technologies:
- Node.js: A JavaScript runtime environment for building server-side applications.
- Express.js: A minimal and flexible Node.js web application framework used to create our API endpoint.
- Vonage Node Server SDK (
@vonage/server-sdk): The official library for interacting with Vonage APIs from Node.js. - Vonage SMS API: The Vonage service used for sending and receiving SMS messages globally.
- dotenv: A module to load environment variables from a
.envfile intoprocess.env.
Prerequisites:
- Node.js and npm: Ensure Node.js (which includes npm) is installed on your system. You can download it from nodejs.org. Verify installation by running
node -vandnpm -vin your terminal. Note: The Vonage Node Server SDK requires Node.js v18 or higher for optimal compatibility with modern features likeasync/awaitand ES modules. - Vonage API Account: Sign up for a free Vonage API account at developer.vonage.com. New accounts receive free credit for testing.
- Vonage API Key and Secret: Find these on your Vonage API Dashboard after signing up.
- Vonage Phone Number or Alphanumeric Sender ID: You need a Vonage virtual number or have set up an Alphanumeric Sender ID to send messages from. You can purchase numbers in the dashboard under ""Numbers"" > ""Buy numbers"". Note: For trial accounts, you might be restricted to sending messages to verified numbers only initially.
- Text Editor/IDE: Such as VS Code, Sublime Text, or WebStorm.
- (Optional) Postman or curl: For testing the API endpoint we create.
System Architecture:
The system is straightforward:
- A client (e.g., Postman, curl, a frontend application) sends a POST request to our Node.js/Express API endpoint (
/send-sms). - The Express server receives the request, extracts the recipient number and message content.
- The server uses the Vonage Node SDK, configured with your API credentials, to call the Vonage SMS API.
- Vonage processes the request and delivers the SMS message to the recipient's phone via the carrier network.
- Vonage returns a response to our server, which then relays a success or error message back to the client.
[Client] ---- HTTP POST ----> [Node.js/Express API] ---- Vonage API Call ----> [Vonage Platform] ---- SMS ----> [Recipient Phone]
<---- HTTP Response --- <---- API Response ----
1. Setting up the Project
Let's initialize our Node.js project and install the necessary dependencies.
-
Create Project Directory: Open your terminal and create a new directory for your project, then navigate into it:
bashmkdir vonage-sms-sender cd vonage-sms-sender -
Initialize Node.js Project: Run
npm initto create apackage.jsonfile. You can accept the defaults by adding the-yflag:bashnpm init -yThis file tracks your project's metadata and dependencies.
-
Install Dependencies: We need Express for the web server, the Vonage SDK to interact with the API, and
dotenvto manage environment variables securely. Runningnpm installwill add these packages to yournode_modulesfolder and record the specific versions in yourpackage.json.bashnpm install express @vonage/server-sdk dotenv -
Create Project Files: Create the main files for our application:
bashtouch server.js vonageService.js .env .gitignoreserver.js: This will contain our Express application setup and API endpoint.vonageService.js: This module will encapsulate the logic for interacting with the Vonage SDK..env: This file will store our sensitive API credentials (API Key, API Secret, Vonage Number/Sender ID). Never commit this file to version control..gitignore: Specifies intentionally untracked files that Git should ignore.
-
Configure
.gitignore: Addnode_modulesand.envto your.gitignorefile to prevent committing dependencies and secrets:text# .gitignore node_modules/ .env *.log -
Set up
package.jsonStart Script: Openpackage.jsonand add astartscript underscriptsto easily run your server. Yourpackage.jsonwill look similar to this after runningnpm installand adding the start script (specific versions will vary):json{ ""name"": ""vonage-sms-sender"", ""version"": ""1.0.0"", ""description"": ""Node.js app to send SMS via Vonage"", ""main"": ""server.js"", ""scripts"": { ""start"": ""node server.js"", ""test"": ""echo \""Error: no test specified\"" && exit 1"" }, ""keywords"": [ ""vonage"", ""sms"", ""node"", ""express"" ], ""license"": ""ISC"", ""dependencies"": { ""@vonage/server-sdk"": ""^x.y.z"", ""dotenv"": ""^x.y.z"", ""express"": ""^x.y.z"" } }
2. Integrating with Vonage (Configuration)
Now, let's configure the application to use your Vonage account credentials securely.
-
Obtain Vonage Credentials:
- Navigate to your Vonage API Dashboard.
- Find your API key and API secret displayed prominently.
- Go to ""Numbers"" > ""Your numbers"" to find your Vonage virtual phone number, or ensure you have an Alphanumeric Sender ID configured if applicable (check regional restrictions).
-
Configure
.envFile: Open the.envfile and add your credentials. Replace the placeholder values with your actual Vonage details.dotenv# .env # Vonage API Credentials VONAGE_API_KEY=YOUR_API_KEY VONAGE_API_SECRET=YOUR_API_SECRET # Vonage Sender ID (Use your Vonage number or Alphanumeric Sender ID) # Ensure the number is in E.164 format if using a number (e.g., 14155552671) VONAGE_SENDER_ID=YOUR_VONAGE_NUMBER_OR_SENDER_ID # Server Port PORT=3000VONAGE_API_KEY: Your Vonage API Key.VONAGE_API_SECRET: Your Vonage API Secret.VONAGE_SENDER_ID: The 'from' number or ID for the SMS. This must be a valid Vonage number associated with your account or an approved Alphanumeric Sender ID. Use E.164 format (e.g.,14155552671) for phone numbers.PORT: The port number your Express server will listen on.
Security: The
.envfile keeps your secrets out of your codebase. Ensure it's listed in.gitignore. -
Whitelisting (Trial Accounts): If you are using a trial Vonage account, you might need to whitelist the phone numbers you intend to send SMS messages to.
- In the Vonage Dashboard, navigate to ""Sandbox & Tools"" > ""Test Numbers"".
- Add the recipient phone numbers you will use for testing and verify them following the instructions (usually via an SMS or voice call code).
- Failure to do this on a trial account will likely result in a ""Non-Whitelisted Destination"" error when sending.
3. Implementing Core Functionality (SMS Service)
Let's create the service logic to handle sending the SMS via the Vonage SDK.
-
Create
vonageService.js: OpenvonageService.jsand add the following code:javascript// vonageService.js const { Vonage } = require('@vonage/server-sdk'); // Initialize Vonage client from environment variables const vonage = new Vonage({ apiKey: process.env.VONAGE_API_KEY, apiSecret: process.env.VONAGE_API_SECRET }); /** * Sends an SMS message using the Vonage API. * @param {string} recipient - The recipient phone number in E.164 format (e.g., '14155552671'). * @param {string} messageText - The text content of the SMS message. * @returns {Promise<object>} A promise that resolves with the Vonage API response data on success. * @throws {Error} Throws an error if the message sending fails. */ async function sendSms(recipient, messageText) { const sender = process.env.VONAGE_SENDER_ID; if (!recipient || !messageText || !sender) { throw new Error('Missing recipient, message text, or sender ID.'); } console.log(`Attempting to send SMS from ${sender} to ${recipient}`); try { // Using vonage.sms.send for simpler SMS-only sending const responseData = await vonage.sms.send({ to: recipient, from: sender, text: messageText }); // Check response status from Vonage if (responseData.messages[0].status === '0') { console.log(`Message sent successfully to ${recipient}. Message UUID: ${responseData.messages[0]['message-id']}`); return responseData; // Resolve with the success response } else { const errorCode = responseData.messages[0].status; const errorText = responseData.messages[0]['error-text']; console.error(`Message failed with error code ${errorCode}: ${errorText}`); // Throw a specific error for easier handling upstream throw new Error(`Vonage API Error (${errorCode}): ${errorText}`); } } catch (error) { console.error('Error sending SMS via Vonage:', error); // Re-throw the error to be caught by the API route handler throw error; } } module.exports = { sendSms };Explanation:
- We import the
Vonageclass from the SDK. - We initialize the
vonageclient using the API Key and Secret loaded fromprocess.env(whichdotenvwill populate). - The
sendSmsfunction takes therecipientnumber andmessageTextas arguments. - It retrieves the
senderID from the environment variables. - Basic validation checks if required parameters are present.
- We use
vonage.sms.send(), which is a convenient method specifically for sending standard SMS. It takes an object withto,from, andtext. - The function uses
async/awaitfor cleaner asynchronous code. - It checks the
statusproperty in the Vonage response. A status of'0'indicates success. - If successful, it logs the message ID and returns the response data.
- If unsuccessful, it logs the error code and text provided by Vonage and throws an error.
- A
try...catchblock handles potential network errors or issues during the API call itself. - The function is exported for use in our server file.
- We import the
4. Building the API Layer (Express Server)
Now, let's set up the Express server and create the API endpoint to trigger the SMS sending.
-
Create
server.js: Openserver.jsand add the following code:javascript// server.js require('dotenv').config(); // Load environment variables from .env file const express = require('express'); const { sendSms } = require('./vonageService'); // Import the SMS sending function const app = express(); const port = process.env.PORT || 3000; // Use port from .env or default to 3000 // Middleware to parse JSON request bodies app.use(express.json()); // Middleware to parse URL-encoded request bodies app.use(express.urlencoded({ extended: true })); // --- API Endpoints --- // Health check endpoint app.get('/health', (req, res) => { res.status(200).json({ status: 'OK', timestamp: new Date().toISOString() }); }); // POST endpoint to send SMS app.post('/send-sms', async (req, res) => { const { to, message } = req.body; // Extract recipient and message from request body // --- Basic Input Validation --- if (!to || !message) { console.error('Validation Error: Missing ""to"" or ""message"" in request body'); return res.status(400).json({ success: false, message: 'Bad Request: Missing required fields ""to"" (recipient phone number) or ""message"".' }); } // Basic E.164 format check (starts with +, followed by digits) - adjust regex as needed for stricter validation const e164Regex = /^\+[1-9]\d{1,14}$/; if (!e164Regex.test(to)) { console.error(`Validation Error: Invalid phone number format for ""to"": ${to}`); return res.status(400).json({ success: false, message: 'Bad Request: Invalid recipient phone number format. Use E.164 format (e.g., +14155552671).' }); } try { console.log(`Received request to send SMS to: ${to}`); const result = await sendSms(to, message); // Call the Vonage service function // Successfully sent SMS res.status(200).json({ success: true, message: 'SMS sent successfully.', details: { to: result.messages[0].to, messageId: result.messages[0]['message-id'], status: result.messages[0].status, remainingBalance: result.messages[0]['remaining-balance'], // Useful info messagePrice: result.messages[0]['message-price'] // Useful info } }); } catch (error) { console.error(`Failed to send SMS to ${to}:`, error.message); // Determine appropriate status code based on error (simplified here) // In production, you might inspect error types for more specific responses const statusCode = error.message.includes('Vonage API Error') ? 502 : 500; // 502 Bad Gateway if Vonage error, 500 otherwise res.status(statusCode).json({ success: false, message: `Failed to send SMS. ${error.message}` // Include error message for client debugging }); } }); // --- Start Server --- app.listen(port, () => { console.log(`Server listening at http://localhost:${port}`); console.log(`Vonage Sender ID configured: ${process.env.VONAGE_SENDER_ID || 'NOT SET'}`); if (!process.env.VONAGE_API_KEY || !process.env.VONAGE_API_SECRET || !process.env.VONAGE_SENDER_ID) { console.warn('WARN: One or more Vonage environment variables (VONAGE_API_KEY, VONAGE_API_SECRET, VONAGE_SENDER_ID) are not set in .env'); } });Explanation:
require('dotenv').config();: This line must be at the very top to load the.envvariables before they are used anywhere else.- We import
expressand oursendSmsfunction. - An Express application instance (
app) is created. express.json()andexpress.urlencoded()middleware are used to parse incoming JSON and URL-encoded request bodies, respectively. This enables us to accessreq.body.- A simple
/healthGET endpoint is included as a best practice for monitoring. - The core
/send-smsPOST endpoint is defined:- It extracts the
to(recipient number) andmessagefrom the request body (req.body). - Input Validation: It checks if
toandmessageare present. If not, it sends a400 Bad Requestresponse. It also includes a basic regex check for E.164 format. - It calls the
sendSmsfunction within anasyncfunction, usingawaitto handle the promise. - A
try...catchblock handles potential errors during thesendSmscall (either network issues or errors reported by Vonage). - Success Response: If
sendSmsresolves successfully, it sends a200 OKresponse withsuccess: trueand relevant details from the Vonage response (like the message ID). - Error Response: If
sendSmsthrows an error, it logs the error and sends an appropriate error response (e.g.,500 Internal Server Erroror502 Bad Gatewayif it's a Vonage API issue) withsuccess: falseand the error message.
- It extracts the
app.listen()starts the server on the specified port. We add logs to confirm the server is running and which Sender ID is configured, plus a warning if essential Vonage variables are missing.
5. Error Handling and Logging
We've implemented basic error handling, but let's refine it.
- Consistent Error Strategy: Our current approach uses
try...catchin the API route and throws/catches errors from the service layer. Errors are logged to the console, and appropriate HTTP status codes (400, 500, 502) with JSON error messages are returned to the client. - Logging: We are using
console.logfor informational messages andconsole.errorfor errors. For production, consider using a more robust logging library like Winston or Pino which enable:- Different log levels (debug, info, warn, error).
- Structured logging (e.g., JSON format) for easier parsing by log analysis tools.
- Writing logs to files or external services.
- Retry Mechanisms: For transient network issues or specific Vonage rate-limit errors, implementing a retry strategy with exponential backoff could improve resilience. Libraries like
async-retrycan help implement this within thevonageService.jssendSmsfunction, wrapping thevonage.sms.sendcall. This is beyond the scope of this basic guide but important for production.
Example Testing Error Scenario:
Try sending a request without a to field to /send-sms. You should receive a 400 response. Try sending with invalid Vonage credentials in .env; you should receive a 502 or 500 response with an authentication error message.
6. Database Schema and Data Layer
This specific application does not require a database. It's a stateless API endpoint that processes requests immediately by calling an external service (Vonage).
If you were building a system to track sent messages, manage contacts, or queue messages, you would need a database (e.g., PostgreSQL, MongoDB) and a data access layer (possibly using an ORM like Prisma or Sequelize). This would involve defining schemas/models, setting up migrations, and writing functions to interact with the database.
7. Adding Security Features
Security is crucial, especially when dealing with APIs and credentials.
-
Input Validation and Sanitization:
- We added basic validation for the presence of
toandmessageand a format check forto. - For production, implement more robust validation using libraries like
joiorexpress-validator. - Sanitize message content if it's ever displayed elsewhere, though for sending SMS directly, Vonage handles encoding. Be mindful of character limits and potential injection if constructing messages dynamically from untrusted input.
- We added basic validation for the presence of
-
API Key Security:
- Never hardcode API keys/secrets. Use environment variables (
.envlocally, platform-specific configuration in deployment). - Ensure
.envis in.gitignore. - Rotate keys periodically if your platform supports it.
- Never hardcode API keys/secrets. Use environment variables (
-
Rate Limiting:
-
Protect your API from abuse and excessive cost by implementing rate limiting. Use middleware like
express-rate-limit. -
Example (add after
app.use(express.urlencoded...)):javascriptconst 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' }); app.use('/send-sms', limiter); // Apply to the send-sms route
-
-
HTTPS: Always deploy your application behind HTTPS to encrypt traffic between the client and your server. Hosting platforms usually handle this.
-
Common Vulnerabilities: While less relevant for this simple API, be aware of OWASP Top 10 vulnerabilities (like injection, broken authentication, etc.) when building more complex applications.
8. Handling Special Cases
- International Number Formatting: Always use the E.164 format for phone numbers (e.g.,
+14155552671,+447700900000). This ensures global compatibility. Our basic regex check enforces the starting+. - Character Limits & Encoding: Standard SMS messages have a 160-character limit (using GSM-7 encoding). Messages with characters outside this set (like emojis or many accented characters) use UCS-2 encoding, reducing the limit to 70 characters per SMS part. Longer messages are split into multiple parts (concatenated SMS). Vonage handles this splitting, but be aware it affects pricing (you pay per part). If sending emojis, ensure your sender ID supports unicode or the message might be garbled (Vonage usually handles this detection).
- Sender ID Restrictions: Alphanumeric Sender IDs are not supported in all countries (e.g., USA requires standard numbers). Using a Vonage number is generally more reliable globally. Check Vonage documentation for country-specific regulations.
- Delivery Reports (DLRs): This guide doesn't cover receiving DLRs, which confirm message delivery status to the handset. This requires setting up a separate webhook endpoint in your Vonage application settings and handling POST requests from Vonage.
9. Implementing Performance Optimizations
For this simple API, performance is largely dependent on the Vonage API response time.
- Bottlenecks: The main potential bottleneck is the external API call to Vonage.
- Caching: Caching is not applicable here as each request should trigger a unique SMS.
- Resource Usage: Node.js is generally efficient. Ensure you handle asynchronous operations correctly (using
async/await) to avoid blocking the event loop. - Load Testing: If expecting high volume, use tools like
k6orartilleryto test how many concurrent requests your server and the Vonage API can handle. Monitor Vonage rate limits. - Concurrency: Node.js handles concurrency well via its event loop. If sending bulk messages, consider queuing requests (e.g., using Redis or RabbitMQ) and processing them with worker processes rather than handling everything synchronously within the API request, to provide faster responses to the client.
10. Adding Monitoring, Observability, and Analytics
For production readiness:
- Health Checks: The
/healthendpoint provides a basic check. Monitoring services can poll this endpoint to verify the server is running. - Performance Metrics: Integrate Application Performance Monitoring (APM) tools (e.g., Datadog, New Relic, Dynatrace). These automatically instrument Express and Node.js to track request latency, error rates, throughput, and resource usage (CPU, memory).
- Error Tracking: Use services like Sentry or Bugsnag. They capture unhandled exceptions and provide detailed context (stack traces, request data) for faster debugging. Integrate their Node.js SDKs.
- Logging Aggregation: Send logs (preferably structured JSON) from your application (using Winston/Pino) to a centralized logging platform (e.g., Elasticsearch/Logstash/Kibana (ELK), Datadog Logs, Splunk). This enables searching, filtering, and creating dashboards based on log data (e.g., tracking SMS send failures by error code).
- Dashboards: Create dashboards in your monitoring/logging tools to visualize key metrics:
- API request rate and latency (overall and for
/send-sms). - API error rate (4xx and 5xx).
- Count of successful SMS sends vs. failures (based on logs or custom metrics).
- Vonage API error codes distribution (from logs).
- API request rate and latency (overall and for
- Alerting: Configure alerts in your monitoring system for critical issues:
- High API error rate (> X%).
- High API latency (> Y ms).
- Server unresponsive (health check failing).
- Specific Vonage error codes appearing frequently.
11. Troubleshooting and Caveats
Non-Whitelisted DestinationError: (Status Code15from Vonage) Occurs on trial accounts when sending to a number not added and verified in the ""Test Numbers"" section of the Vonage dashboard. Solution: Add and verify the recipient number.Invalid CredentialsError: (Status Code4or similar auth errors) Double-checkVONAGE_API_KEYandVONAGE_API_SECRETin your.envfile. Ensuredotenvis loaded correctly (require('dotenv').config();at the top ofserver.js). Make sure the.envfile is in the root directory where you runnode server.js.Invalid Sender Address (from)Error: (Status Code9or similar) EnsureVONAGE_SENDER_IDin.envis a valid Vonage number associated with your account (in E.164 format) or an approved Alphanumeric Sender ID allowed in the destination country.Invalid Message/ Encoding Issues: If sending special characters/emojis results in?or errors, ensure Vonage is correctly interpreting the content.vonage.sms.sendgenerally handles this well. Usingvonage.messages.sendmight require explicitly settingmessage_type: 'unicode'.- Rate Limiting by Vonage: If sending many messages quickly, you might hit Vonage's API rate limits (check their documentation for current limits). The API will return error responses (often status code
1). Implement delays or queuing if needed. - Missing
.envVariables: The startup log inserver.jsincludes a warning if key Vonage variables are missing. Ensure the.envfile exists and is correctly formatted. - Incorrect
toNumber Format: Ensure the recipient number passed in the request body is in E.164 format. The API includes a basic check. - Vonage Service Outages: Check the Vonage Status Page if you suspect issues beyond your application.
12. Deployment and CI/CD
- Environment Configuration: Do not deploy your
.envfile. Production environments (Heroku, AWS, Azure, Google Cloud, Render, etc.) provide mechanisms to set environment variables securely. ConfigureVONAGE_API_KEY,VONAGE_API_SECRET,VONAGE_SENDER_ID, andPORTin your chosen platform's settings. - Deployment Procedures:
- Platforms like Heroku/Render: Connect your Git repository. The platform typically detects
package.json, installs dependencies (npm install --production), and runs thestartscript (npm run start). Configure environment variables via their web UI or CLI. - Virtual Machines (EC2, etc.): Clone your repository, install Node.js/npm, run
npm install --production, set environment variables (e.g., using systemd unit files or shell profiles), and use a process manager likepm2to run your app (pm2 start server.js). Ensure firewalls allow traffic on your chosenPORT. - Serverless (AWS Lambda, etc.): Requires refactoring. Your Express app needs to be adapted to the platform's handler function signature (e.g., using frameworks like Serverless Framework or AWS SAM). Environment variables are set via function configuration.
- Platforms like Heroku/Render: Connect your Git repository. The platform typically detects
- CI/CD Pipeline:
- Use tools like GitHub Actions, GitLab CI, or Jenkins.
- Steps:
- Checkout Code: Get the latest code from your repository.
- Setup Node.js: Specify the Node.js version.
- Install Dependencies: Run
npm ci(usually preferred overnpm installin CI for deterministic builds). - (Optional) Linting/Testing: Run code linters (
eslint) and automated tests (jest,mocha). - (Optional) Build Step: If using TypeScript or a build process, run it here.
- Deploy: Push the code/build artifacts to your hosting platform using its CLI or deployment mechanisms (e.g.,
heroku deploy,eb deploy,serverless deploy). Securely inject secrets/environment variables during this step.
- Rollback Procedures: Familiarize yourself with your hosting platform's rollback mechanism (e.g., Heroku releases, AWS CodeDeploy rollbacks) to quickly revert to a previous working version if a deployment fails.
13. Verification and Testing
-
Start the Server:
bashnpm startYou should see the log message ""Server listening at http://localhost:3000"".
-
Manual Verification (using
curl): Open a new terminal window. Replace+1xxxxxxxxxxwith a verified test number (if using a trial account) or any valid number (if using a paid account) in E.164 format. ReplaceYOUR_VONAGE_NUMBER_OR_SENDER_IDwith the value you set.bashcurl -X POST http://localhost:3000/send-sms \ -H ""Content-Type: application/json"" \ -d '{ ""to"": ""+1xxxxxxxxxx"", ""message"": ""Hello from Node.js and Vonage!"" }' -
Expected Success Output (Terminal running
curl):json{ ""success"": true, ""message"": ""SMS sent successfully."", ""details"": { ""to"": ""1xxxxxxxxxx"", ""messageId"": ""xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"", ""status"": ""0"", ""remainingBalance"": ""x.xxxx"", ""messagePrice"": ""x.xxxx"" } } -
Expected Success Output (Terminal running
server.js):Server listening at http://localhost:3000 Vonage Sender ID configured: YOUR_VONAGE_NUMBER_OR_SENDER_ID Received request to send SMS to: +1xxxxxxxxxx Attempting to send SMS from YOUR_VONAGE_NUMBER_OR_SENDER_ID to +1xxxxxxxxxx Message sent successfully to +1xxxxxxxxxx. Message UUID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx -
Check Your Phone: You should receive the SMS message on the recipient device.
-
Test Failure Cases:
- Send without
to:curl -X POST http://localhost:3000/send-sms -H ""Content-Type: application/json"" -d '{""message"": ""test""}'(Expect 400) - Send without
message:curl -X POST http://localhost:3000/send-sms -H ""Content-Type: application/json"" -d '{""to"": ""+1xxxxxxxxxx""}'(Expect 400) - Send with invalid
toformat:curl -X POST http://localhost:3000/send-sms -H ""Content-Type: application/json"" -d '{""to"": ""12345"", ""message"": ""test""}'(Expect 400) - Temporarily put incorrect credentials in
.envand restart the server. Try sending again (Expect 500/502).
- Send without
-
(Optional) Automated Testing:
- Unit Tests: Use frameworks like Jest or Mocha/Chai to test the
vonageService.jslogic. You would mock the@vonage/server-sdkto avoid making real API calls during tests, verifying thatvonage.sms.sendis called with the correct parameters based on input. - Integration Tests: Test the
/send-smsendpoint using libraries likesupertest. This makes actual HTTP requests to your running Express app (usually in a test environment), asserting the responses. You might still mock the Vonage call or have a dedicated test Vonage account.
- Unit Tests: Use frameworks like Jest or Mocha/Chai to test the
Verification Checklist:
- Project setup correctly (
npm installsuccessful). .envfile created with correctVONAGE_API_KEY,VONAGE_API_SECRET,VONAGE_SENDER_ID..envis listed in.gitignore.- Recipient number(s) whitelisted if using a trial Vonage account.
- Server starts without errors (
npm start). /healthendpoint returns 200 OK.- Sending a valid request to
/send-smsusingcurlreturns a 200 OK response withsuccess: true. - The SMS message is received on the target phone number.
- Sending invalid requests (missing fields, bad format) returns appropriate 400 errors.
- Simulating API key errors results in 5xx errors.
This guide provides a solid foundation for sending SMS messages using Node.js and Vonage. Remember to consult the official Vonage Node SDK documentation and Vonage SMS API documentation.
Frequently Asked Questions
How do I send SMS with Node.js using Vonage?
To send SMS with Node.js using Vonage, install the @vonage/server-sdk package, configure your API credentials in a .env file, initialize the Vonage client with new Vonage({ apiKey, apiSecret }), and call vonage.sms.send({ to, from, text }) with the recipient number, your Vonage number, and message text. The SDK returns a Promise that resolves with delivery status.
What Node.js version is required for Vonage SMS API?
The Vonage Node Server SDK requires Node.js v18 or higher for optimal compatibility with modern features like async/await and ES modules. While older versions may work, v18+ ensures full support for all SDK features and security updates.
How much does it cost to send SMS with Vonage?
Vonage SMS pricing varies by destination country. New accounts receive free credit for testing. You can check real-time pricing in your Vonage Dashboard under "Pricing" or view the message-price field in API responses. Trial accounts have daily limits and require recipient number whitelisting.
How do I handle Vonage SMS API errors in Node.js?
Vonage SMS API returns status codes in responses: status '0' indicates success, while non-zero codes indicate errors. Common errors include status 15 (Non-Whitelisted Destination on trial accounts), status 4 (Invalid Credentials), and status 1 (Throttled/Rate Limited). Implement try...catch blocks and check the status and error-text fields in responses.
What is E.164 phone number format for Vonage SMS?
E.164 is the international telephone numbering format required by Vonage: a + symbol followed by country code and subscriber number, with no spaces or special characters (e.g., +14155552671 for US numbers, +447700900000 for UK). Use the regex /^\+[1-9]\d{1,14}$/ to validate E.164 format.
Can I send SMS from localhost with Vonage?
Yes, you can send SMS from localhost using Vonage. The Vonage API only requires outbound HTTPS connections, so your local Node.js application can make API calls without exposing ports or using webhooks. However, receiving delivery receipts (DLRs) requires a publicly accessible webhook URL.
How do I secure Vonage API credentials in Node.js?
Store Vonage API credentials in environment variables using the dotenv package. Create a .env file with VONAGE_API_KEY and VONAGE_API_SECRET, add .env to .gitignore, and load variables with require('dotenv').config() before initializing the Vonage client. Never hardcode credentials or commit them to version control.
What is the rate limit for Vonage SMS API?
Vonage SMS API has a default rate limit of 30 requests per second per API key. Exceeding this limit returns status code 1 (Throttled). For higher throughput, contact Vonage support. US 10DLC numbers have additional per-minute limits based on campaign type. Implement rate limiting middleware like express-rate-limit to protect your API.
How do I send SMS to international numbers with Vonage Node.js?
To send international SMS, ensure the recipient number is in E.164 format with the correct country code (e.g., +61 for Australia, +81 for Japan). Some countries have regulatory requirements like sender ID registration. Check Vonage's country-specific documentation and verify your account has international messaging enabled.
Why am I getting "Non-Whitelisted Destination" error from Vonage?
The "Non-Whitelisted Destination" error (status code 15) occurs on Vonage trial accounts when sending to numbers not verified in your dashboard. Navigate to "Sandbox & Tools" > "Test Numbers", add the recipient number, and verify it via SMS or voice call. Upgrade to a paid account to remove this restriction.
Frequently Asked Questions
How to send SMS messages with Node.js?
Use the Vonage SMS API with the Vonage Node Server SDK and Express.js. Create an Express API endpoint that takes the recipient's number and message, then uses the SDK to send the SMS through Vonage's API.
What is the Vonage Node Server SDK?
It's the official library (`@vonage/server-sdk`) for interacting with Vonage APIs from your Node.js application. This SDK simplifies making API calls to Vonage's services, including the SMS API.
Why does Vonage require an API key and secret?
The API key and secret authenticate your application with Vonage's platform. These credentials verify your identity and authorize access to your Vonage account features and services.
When should I whitelist recipient numbers with Vonage?
Whitelisting is necessary for Vonage trial accounts. Add the recipient numbers you'll be testing with to the "Test Numbers" section of your Vonage dashboard to avoid "Non-Whitelisted Destination" errors.
How to set up Vonage API credentials in Node.js?
Store your API key, secret, and sender ID in a `.env` file. Use the `dotenv` package to load these variables into `process.env` within your application. Never commit `.env` to version control.
What is the role of Express.js in sending SMS with Vonage?
Express.js creates the API endpoint that receives requests to send messages. It handles routing, middleware, and communication with both the client making the request and the Vonage API.
How to handle errors when sending SMS via Vonage?
Use `try...catch` blocks to handle errors from the Vonage API call. Check the Vonage response status and log errors appropriately. Provide informative error responses to the client.
How do I handle international phone numbers when sending SMS?
Always use the E.164 format (e.g., +14155552671). This standardized format ensures Vonage routes messages internationally without issue.
How to check the status of sent SMS messages?
The Vonage API returns a status code in its response. A '0' status means success. For delivery confirmation, you need to implement Vonage Delivery Receipts (DLRs) using webhooks.
What are some Vonage SMS limitations to be aware of?
SMS messages have character limits: 160 for GSM-7 encoding and 70 for UCS-2 (used for special characters). Longer messages are split, increasing costs. Alphanumeric sender IDs have country restrictions.
How to troubleshoot the 'Non-Whitelisted Destination' error?
This error (code 15) is specific to Vonage trial accounts. Ensure the recipient number is added and verified in the 'Test Numbers' section of the Vonage dashboard.
How to handle Vonage API rate limits in my application?
Monitor Vonage's API documentation for rate limits. If you anticipate high message volume, implement rate limiting in your Express app using middleware like `express-rate-limit` and consider using a message queue.
What is E.164 format and why does Vonage require it?
E.164 is an international standard for phone numbers. It includes a '+' and country code (e.g., +1 for USA). Using E.164 ensures correct routing of your SMS globally.
Can I use emojis in my SMS messages via Vonage?
Yes, but be aware that emojis typically require UCS-2 encoding, reducing the character limit per SMS segment to 70. Vonage handles encoding, but ensure your sender ID supports Unicode.