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.env
file 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-sms
endpoint 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.
# Terminal mkdir vonage-sms-sender cd vonage-sms-sender
-
Initialize Node.js Project: Initialize the project using npm. The
-y
flag accepts default settings.# Terminal npm init -y
This creates a
package.json
file. -
Install Dependencies: Install Express, the Vonage Server SDK, and
dotenv
.# Terminal npm install express @vonage/server-sdk dotenv
express
: 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.
# 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.env
file) and unnecessary files (likenode_modules
) from being committed to version control (e.g., Git). Open.gitignore
and add the following:# .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:
vonage-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).// 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.env
variables defined in your.env
file 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.
// 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/await
provides 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 thesendSms
function, initialize Express and add middleware to parse JSON request bodies.// 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-sms
Endpoint: Create a POST route handler that takes the recipient number and message from the request body and uses oursendSms
function.// 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 beasync
because itawait
s thesendSms
function. - 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...catch
here 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.
// 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
'ssend
function, thefrom
field 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
.env
file you created earlier and add your Vonage credentials and the desired port for your server. Never commit this file to Git.# .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_PLUS
with the actual values from your dashboard. Use the number without the leading+
if that's what the SDK expects for thefrom
field. - 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:
sendSms
function 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...catch
block catches errors fromsendSms
or 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.log
andconsole.error
are 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
sendSms
function using libraries likeasync-retry
. - Caution: Be careful not to retry on non-recoverable errors (like invalid credentials
401
or 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-sms
endpoint (checking forto
andmessage
, basic phone format). - Use a robust library like
google-libphonenumber
(via its Node.js port) for comprehensive phone number validation and formatting. - Sanitize the
message
content 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
.env
and.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:
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
to
field. Thefrom
number 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
Vonage
instances per request. - Asynchronous Operations: Node.js and
async/await
handle 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-sms
endpoint and identify potential bottlenecks in your server or rate limits hit on the Vonage side.- Example (
ab
): Create a filepost_payload.json
with content like{ "to": "+1...", "message": "Test" }
. Then run:ab -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.
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-client
or 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_KEY
orVONAGE_API_SECRET
. Double-check values in.env
against the Vonage dashboard. Ensure.env
is 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
from
number (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
from
number 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()
. Ensureto
is 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.env
file 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.env
file 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-sdk
or 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
.env
file. 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. (
nodemon
is generally for development only). - Modify
package.json
scripts:// 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.,
main
branch). - 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
.env
file is populated with correct credentials. - Start the server:
# Terminal node index.js
- You should see output similar to:
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
+1xxxxxxxxxx
with your whitelisted test phone number (in E.164 format). - Replace
"Hello from Node.js and Vonage!"
with your desired text.
# 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
):{ "success": true, "message": "SMS sent successfully.", "messageId": "SOME_MESSAGE_ID_FROM_VONAGE" }
- Expected Success Logs (Terminal running
node index.js
):Server 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):
curl -X POST http://localhost:3000/send-sms -H "Content-Type: application/json" -d '{"to": "+1xxxxxxxxxx"}'
{"success":false,"message":"Missing required fields: `to` and `message`."}
- Invalid Number Format:
Expected Response (HTTP 400):
curl -X POST http://localhost:3000/send-sms -H "Content-Type: application/json" -d '{"to": "invalid-number", "message": "test"}'
{"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.js
terminal (likely related to "Non-Whitelisted Destination" or similar, depending on the exact Vonage API response) and receive an HTTP 500 response from your API:{"success":false,"message":"Failed to send SMS due to an internal server error."}
- Missing fields: