Send SMS with Node.js, Express, and Vonage: A Production-Ready Guide
This guide provides a complete walkthrough for building a Node.js application using the Express framework to send SMS messages via the Vonage Messages API. We will cover everything from project setup and Vonage configuration to implementing the core sending logic, handling errors, and preparing for production deployment.
By the end of this tutorial, you will have a functional Express API endpoint capable of accepting requests and sending SMS messages programmatically. This guide assumes minimal prior knowledge of Vonage but expects familiarity with Node.js, npm (or yarn), and basic API concepts.
Project Overview and Goals
What We're Building:
A simple yet robust Node.js Express server with a single API endpoint (/send-sms
) that accepts a recipient phone number and a message text, then uses the Vonage Messages API to send the SMS.
Problem Solved: This application provides a programmatic way to send SMS messages, enabling automated notifications, alerts, two-factor authentication codes, or other communication workflows directly from your backend systems.
Technologies Used:
- Node.js: A JavaScript runtime environment for executing server-side code.
- Express.js: A minimal and flexible Node.js web application framework used to create the API endpoint.
- Vonage Messages API: A powerful Vonage API for sending messages across various channels (SMS, MMS, WhatsApp, etc.). We will use its Node.js SDK.
dotenv
: A utility to load environment variables from a.env
file intoprocess.env
.
System Architecture:
The flow is straightforward:
- An HTTP client (like
curl
, Postman, or another application) sends a POST request to the/send-sms
endpoint of our Express server. - The Express server validates the request body (recipient number and message).
- The server calls the Vonage Node.js SDK, authenticating using a Vonage Application ID and Private Key.
- The Vonage SDK communicates with the Vonage Messages API.
- The Vonage platform sends the SMS message to the recipient's phone via the carrier network.
- The Vonage API returns a response to our server, which relays success or failure information back to the original client.
[Client] --(HTTP POST)--> [Express App (/send-sms)] --(SDK Call)--> [Vonage API] --(SMS)--> [Recipient Phone]
Expected Outcome:
A running Node.js application serving an API endpoint (http://localhost:3000/send-sms
) that successfully sends an SMS message when provided with a valid recipient number and text via a POST request.
Prerequisites:
- Node.js and npm (or yarn): Installed on your development machine. (Download Node.js)
- Vonage API Account: Required to get API credentials and a virtual number. (Sign up for Vonage)
- Vonage Virtual Phone Number: You need a Vonage number capable of sending SMS messages. You can acquire one through the Vonage Dashboard.
- Basic Terminal/Command Line Knowledge: For running commands.
1. Setting up the Project
Let's create the project structure and install the necessary dependencies.
-
Create Project Directory: Open your terminal or command prompt and run:
mkdir vonage-sms-guide cd vonage-sms-guide
-
Initialize Node.js Project: This creates a
package.json
file to manage dependencies and project metadata.npm init -y
-
Install Dependencies: We need Express for the server, the Vonage Server SDK to interact with the API, and
dotenv
for managing environment variables.npm install express @vonage/server-sdk dotenv
-
Enable ES Modules: Modern Node.js often uses ES Modules (
import
/export
syntax). Open yourpackage.json
file and add the following line:// package.json { ""name"": ""vonage-sms-guide"", ""version"": ""1.0.0"", ""description"": """", ""main"": ""src/index.js"", // Optional: Specify entry point ""scripts"": { ""start"": ""node src/index.js"", // Script to run the app ""test"": ""echo \""Error: no test specified\"" && exit 1"" }, ""keywords"": [], ""author"": """", ""license"": ""ISC"", ""dependencies"": { ""@vonage/server-sdk"": ""^3.14.1"", ""dotenv"": ""^16.4.5"", ""express"": ""^4.19.2"" }, ""type"": ""module"" // <-- Add this line }
Why
type: ""module""
? This tells Node.js to treat.js
files as ES Modules_ enabling the use ofimport
andexport
syntax_ which is cleaner and widely adopted. -
Create Project Structure: Organize the code for better maintainability.
mkdir src touch src/index.js touch src/vonageService.js touch .env touch .gitignore
src/index.js
: The main entry point for our Express application.src/vonageService.js
: A module dedicated to interacting with the Vonage SDK..env
: Stores sensitive credentials like API keys (will not be committed to version control)..gitignore
: Specifies files and directories that Git should ignore.
-
Configure
.gitignore
: Prevent committing sensitive information and unnecessary files. Add the following to your.gitignore
file:# .gitignore # Dependencies node_modules/ # Environment variables .env # Logs logs *.log npm-debug.log* yarn-debug.log* yarn-error.log* lerna-debug.log* # OS generated files .DS_Store Thumbs.db
Why ignore
.env
andnode_modules
?.env
contains secrets that should never be stored in version control.node_modules
contains installed dependencies which can be reinstalled usingnpm install
and would unnecessarily bloat the repository.
2. Configuring Vonage
Before writing code_ we need to set up our Vonage account and application correctly.
-
Sign Up/Log In: Ensure you have a Vonage API account.
-
Create a Vonage Application: Vonage Applications act as containers for your communication configurations and authentication details.
- Navigate to Applications in the Vonage API Dashboard.
- Click Create a new application.
- Give your application a meaningful name (e.g._ ""Node SMS Guide App"").
- Click Generate public and private key. This will automatically download a
private.key
file. Save this file securely – we will place it in our project root directory later. The public key remains with Vonage. - Scroll down to Capabilities.
- Enable the Messages capability. You will see fields for
Inbound URL
andStatus URL
. For sending SMS only_ these aren't strictly required_ but Vonage requires them to be filled if the capability is enabled. You can enter placeholder URLs likehttps://example.com/webhooks/inbound
andhttps://example.com/webhooks/status
. If you plan to receive SMS or delivery receipts later_ you'll need functional webhook URLs here (often managed with tools like ngrok during development). - Scroll down to Link your numbers (or similar section).
- Find the Vonage virtual number you want to send SMS from and click Link. If you don't have one_ you'll need to acquire one first via the Numbers > Buy numbers section.
- Click Generate application.
- You will be taken to the application details page. Note down the Application ID. It will be a UUID string.
- Note: The Vonage Dashboard UI may change over time. Refer to the official Vonage documentation for creating applications and managing capabilities if the steps differ slightly.
-
Place Private Key: Copy the
private.key
file you downloaded into the root directory of your project (vonage-sms-guide/private.key
). -
Set Messages API as Default (Important): Vonage offers different APIs for SMS (the older SMS API and the newer Messages API). The
@vonage/server-sdk
can use both, but the method we'll use (vonage.messages.send
) is part of the Messages API. Ensure it's your account's default for SMS operations.- Navigate to API Settings in the Vonage Dashboard.
- Find the SMS Settings section.
- Under Default SMS API, select Messages API.
- Click Save changes.
- Why is this necessary? Setting the default ensures consistent behavior and webhook formats if you later add receiving capabilities or use other features tied to the Messages API workflow.
-
Configure Environment Variables: Open the
.env
file and add your Vonage credentials and configuration. Replace the placeholder values with your actual details.# .env # Server Configuration PORT=3000 # Vonage Credentials & Configuration VONAGE_APPLICATION_ID=YOUR_APPLICATION_ID_HERE VONAGE_PRIVATE_KEY_PATH=./private.key VONAGE_NUMBER=YOUR_VONAGE_VIRTUAL_NUMBER_HERE # Optional: API Key/Secret (Alternative authentication, not used in this primary example) # VONAGE_API_KEY=YOUR_API_KEY_HERE # VONAGE_API_SECRET=YOUR_API_SECRET_HERE
PORT
: The port your Express server will listen on.VONAGE_APPLICATION_ID
: The Application ID you noted down earlier.VONAGE_PRIVATE_KEY_PATH
: The relative path from your project root to the downloadedprivate.key
file.VONAGE_NUMBER
: The Vonage virtual phone number (in E.164 format, e.g.,14155550100
) linked to your application, which will be used as the sender ID ('From' number).- Security: The
.env
file keeps your sensitive credentials out of your source code. Ensure it's listed in.gitignore
.
3. Implementing the SMS Sending Logic
Let's create a dedicated service module to handle interactions with the Vonage SDK.
- Create Vonage Service (
src/vonageService.js
): This file will initialize the Vonage client and contain the function to send SMS.// src/vonageService.js import { Vonage } from '@vonage/server-sdk'; import { Messages } from '@vonage/messages'; // Import Messages explicitly for type clarity // --- Initialize Vonage Client --- // We use Application ID and Private Key for authentication // Environment variables are expected to be loaded by the entry point (index.js) const vonage = new Vonage({ applicationId: process.env.VONAGE_APPLICATION_ID, privateKey: process.env.VONAGE_PRIVATE_KEY_PATH, }); const vonageMessages = new Messages(vonage.options); // --- Define the Sending Function --- /** * Sends an SMS message using the Vonage Messages API. * @param {string} to - The recipient's phone number in E.164 format (e.g., +14155550101). * @param {string} text - The content of the SMS message. * @returns {Promise<object>} - A promise resolving with the Vonage API response. * @throws {Error} - Throws an error if the SMS sending fails. */ export const sendSms = async (to, text) => { const from = process.env.VONAGE_NUMBER; // Get sender number from env if (!from) { throw new Error(""VONAGE_NUMBER environment variable is not set.""); } if (!to) { // This validation could also be done solely in the API layer throw new Error(""Validation Error: Recipient 'to' number is required.""); } if (!text) { // This validation could also be done solely in the API layer throw new Error(""Validation Error: Message 'text' is required.""); } console.log(`Attempting to send SMS from ${from} to ${to}`); try { const resp = await vonageMessages.send({ message_type: ""text"", // Type of message being sent to: to, // Recipient phone number from: from, // Your Vonage virtual number (Sender ID) channel: ""sms"", // Specify the channel as SMS text: text, // The message content }); console.log(`SMS submitted successfully with Message UUID: ${resp.message_uuid}`); return resp; // Return the full response object } catch (err) { // Log the detailed error from the Vonage SDK console.error(""Error sending SMS via Vonage:""); if (err.response) { // Log specific details if available (like API response errors) console.error(""Status:"", err.response.status); console.error(""Data:"", err.response.data); } else { // Log general error message console.error(err.message); } // Re-throw the error to be caught by the calling function (API endpoint) // Include context from the error if possible const errorMessage = err.response?.data?.title || err.message || 'Unknown error'; throw new Error(`Failed to send SMS: ${errorMessage}`); } };
- Authentication: We initialize
Vonage
using theapplicationId
andprivateKey
path loaded from.env
(handled byindex.js
). This is generally preferred for server-side applications. vonage.messages.send
: This is the core method from the SDK's Messages capability.- Parameters:
message_type: ""text""
: Specifies a plain text SMS.to
: The recipient number (must be E.164 format, e.g.,14155550101
).from
: Your Vonage virtual number from.env
.channel: ""sms""
: Explicitly tells the Messages API to use the SMS channel.text
: The message body.
- Error Handling: A
try...catch
block wraps the API call. If an error occurs (e.g., invalid credentials, network issue, invalid number), it's logged, and a more informative error is thrown to be handled by the API layer. - Modularity: Keeping Vonage logic separate makes the main
index.js
cleaner and thesendSms
function potentially reusable elsewhere.
- Authentication: We initialize
4. Building the Express API Endpoint
Now, let's create the Express server and the /send-sms
route.
-
Create Express Server (
src/index.js
):// src/index.js import express from 'express'; import 'dotenv/config'; // Ensure environment variables are loaded AT THE START import { sendSms } from './vonageService.js'; // Import our sending function // --- Initialize Express App --- const app = express(); const port = process.env.PORT || 3000; // Use port from .env or default to 3000 // --- Middleware --- // Enable Express to parse JSON request bodies app.use(express.json()); // Enable Express to parse URL-encoded request bodies (optional but good practice) app.use(express.urlencoded({ extended: true })); // --- API Routes --- // Basic health check route app.get('/', (req, res) => { res.status(200).json({ status: 'ok', message: 'Vonage SMS API is running!' }); }); // SMS Sending Route app.post('/send-sms', async (req, res) => { // 1. Extract data from request body const { to, text } = req.body; // 2. Basic Input Validation (API Layer) if (!to || !text) { console.error(""Validation Error: 'to' and 'text' fields are required.""); // Return 400 Bad Request for input validation failures return res.status(400).json({ success: false, message: ""Validation Error: Both 'to' (recipient number) and 'text' (message content) are required in the request body."", }); } // Add more robust validation if needed (e.g., regex for phone number format) const phoneRegex = /^\+?[1-9]\d{1,14}$/; // Basic E.164-like format check if (!phoneRegex.test(to)) { console.error(`Validation Error: Invalid 'to' phone number format: ${to}`); // Return 400 Bad Request for input validation failures return res.status(400).json({ success: false, message: ""Validation Error: Invalid 'to' phone number format. Please use E.164 format (e.g., +14155550101)."", }); } try { // 3. Call the Vonage service function const result = await sendSms(to, text); // 4. Send Success Response console.log(`API Endpoint: Successfully processed SMS request for ${to}`); res.status(200).json({ success: true, message: ""SMS sent successfully!"", message_uuid: result.message_uuid, // Include the Vonage message ID }); } catch (error) { // 5. Send Error Response for errors from the service layer console.error(`API Endpoint: Error sending SMS to ${to}:`, error.message); // Use 500 Internal Server Error for errors caught from the service call res.status(500).json({ success: false, message: ""Failed to send SMS."", error: error.message, // Provide the error message from the service }); } }); // --- Start the Server --- app.listen(port, () => { console.log(`Server listening at http://localhost:${port}`); });
- Imports: Import
express
, loaddotenv
(crucially, at the top), and import oursendSms
function. - Middleware:
express.json()
is crucial for parsing the JSON payload ({ ""to"": ""..."", ""text"": ""..."" }
) sent in the POST request body.express.urlencoded
is for form data, included as good practice. /send-sms
Route:- Defined as a
POST
route. - It's
async
because it awaits thesendSms
promise. - Extracts
to
andtext
fromreq.body
. - Performs basic validation to ensure required fields are present and the phone number has a plausible format, returning
400 Bad Request
on failure. - Calls
sendSms
within atry...catch
block. - Sends a
200 OK
JSON response on success, including themessage_uuid
from Vonage. - Sends a
500 Internal Server Error
JSON response ifsendSms
throws an error, including the error message from the service.
- Defined as a
- Server Start:
app.listen
starts the server on the configured port.
- Imports: Import
-
Run the Application: Open your terminal in the project root (
vonage-sms-guide
) and run:npm start
Or directly using node:
node src/index.js
You should see the output:
Server listening at http://localhost:3000
5. Error Handling and Logging
Our current implementation includes basic error handling:
- Input Validation: The
/send-sms
endpoint checks for the presence and basic format ofto
andtext
, returning a400 Bad Request
if invalid. - Vonage Service Errors: The
sendSms
function usestry...catch
to capture errors from the Vonage SDK (e.g., authentication failure, invalid number format recognized by Vonage, network issues). It logs the error details and throws a new error. - API Endpoint Catch Block: The
/send-sms
route'scatch
block captures errors thrown bysendSms
and returns a500 Internal Server Error
with an informative JSON message. - Logging: We use
console.log
for informational messages (server start, SMS submission success) andconsole.error
for validation failures and errors during the Vonage API call.
Further Enhancements (Production Considerations):
- Structured Logging: Use a dedicated logging library (like
winston
orpino
) for structured JSON logs, which are easier to parse and analyze in production environments (e.g., using tools like Datadog, Splunk, or ELK stack). - Centralized Error Handling Middleware: Implement Express error-handling middleware to centralize error responses and avoid repetitive
try...catch
blocks in routes. This middleware can inspect error types (e.g., custom error classes thrown from the service) to return appropriate status codes (4xx for client errors, 5xx for server errors). - Specific Vonage Error Codes: Parse the
err.response.data
from the Vonage SDK error for specific Vonage error codes/messages to provide more granular feedback or implement specific retry logic. Refer to the Vonage Messages API documentation for error details. - Retry Mechanisms: For transient network errors or specific Vonage rate limit errors, implement a retry strategy (e.g., exponential backoff) using libraries like
async-retry
. Caution: Be careful not to retry errors caused by invalid input or permanent issues.
6. Security Considerations
Even for this simple API, security is important:
- Environment Variables: Never commit your
.env
file or hardcode credentials (Application ID
,Private Key
,Vonage Number
) directly in the source code. Use environment variables managed securely in your deployment environment. - Input Validation:
- We added basic validation for
to
andtext
. - Phone Number Validation: The regex
^\+?[1-9]\d{1,14}$
is a basic check. For robust validation, consider libraries likegoogle-libphonenumber
. - Text Sanitization: While SMS content is less prone to injection attacks than web forms, sanitize or validate
text
input if it originates from untrusted sources to prevent unexpected characters or potential abuse. Check length limits (standard SMS is 160 GSM-7 characters or 70 UCS-2 characters).
- We added basic validation for
- Rate Limiting: Protect your API endpoint and your Vonage account from abuse (accidental or malicious) by implementing rate limiting. Use middleware like
express-rate-limit
.npm install express-rate-limit
Adjust// src/index.js (add near the top) import rateLimit from 'express-rate-limit'; // ... (after app initialization) // --- Security Middleware --- const smsLimiter = rateLimit({ windowMs: 15 * 60 * 1000, // 15 minutes max: 10, // Limit each IP to 10 requests per windowMs message: { success: false, message: 'Too many SMS requests from this IP, please try again after 15 minutes.' }, standardHeaders: true, // Return rate limit info in the `RateLimit-*` headers legacyHeaders: false, // Disable the `X-RateLimit-*` headers }); // Apply the rate limiting middleware specifically to the SMS sending route app.use('/send-sms', smsLimiter); // ... (rest of the code)
windowMs
andmax
based on your expected usage. - API Authentication/Authorization: This example API is open. In a real-world scenario, you would protect the
/send-sms
endpoint. Common methods include:- API Keys: Require clients to send a secret API key in a header (
Authorization: ApiKey YOUR_SECRET_KEY
). Validate this key on the server. - JWT (JSON Web Tokens): If the request comes from authenticated users of your application.
- IP Whitelisting: Restrict access to specific IP addresses if the API is only used by known internal services.
- API Keys: Require clients to send a secret API key in a header (
- HTTPS: Always run your Node.js application behind a reverse proxy (like Nginx or Caddy) configured for HTTPS in production to encrypt traffic.
7. Testing the API
You can test the endpoint using tools like curl
or Postman/Insomnia. Make sure your Node.js server is running (npm start
).
Using curl
:
Replace +1_RECIPIENT_NUMBER
with a valid phone number (in E.164 format) that is whitelisted in your Vonage account if you are on a trial account (see Troubleshooting section).
curl -X POST http://localhost:3000/send-sms \
-H ""Content-Type: application/json"" \
-d '{
""to"": ""+1_RECIPIENT_NUMBER"",
""text"": ""Hello from Node.js and Vonage! (Test)""
}'
Example Success Response (200 OK):
{
""success"": true,
""message"": ""SMS sent successfully!"",
""message_uuid"": ""aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee""
}
(You should receive the SMS on the recipient phone shortly after)
Example Validation Error Response (400 Bad Request):
(If to
or text
is missing)
{
""success"": false,
""message"": ""Validation Error: Both 'to' (recipient number) and 'text' (message content) are required in the request body.""
}
Example Vonage Error Response (500 Internal Server Error): (If Vonage rejects the number, credentials fail, etc.)
{
""success"": false,
""message"": ""Failed to send SMS."",
""error"": ""Failed to send SMS: Non-whitelisted destination""
// Error message might vary based on the specific Vonage issue
}
Using Postman/Insomnia:
- Create a new request.
- Set the method to
POST
. - Set the URL to
http://localhost:3000/send-sms
. - Go to the ""Body"" tab, select ""raw"", and choose ""JSON"" from the dropdown.
- Enter the JSON payload:
{ ""to"": ""+1_RECIPIENT_NUMBER"", ""text"": ""Hello from Node.js via Postman! (Test)"" }
- Send the request. Observe the response body and status code.
8. Troubleshooting and Caveats
- Vonage Trial Account Limitations:
- Problem: When using a free trial Vonage account, you can typically only send SMS messages to numbers you have explicitly verified and whitelisted. Sending to other numbers will fail.
- Error Message: You might see an error like
""Non-whitelisted destination""
or similar in the API response or logs. - Solution: Go to your Vonage Dashboard -> Numbers -> Test Numbers (or similar section, the exact name might change) and add the phone number(s) you intend to send test messages to. You will usually need to verify them via an SMS or voice call code.
- Incorrect API Credentials/Configuration:
- Problem:
VONAGE_APPLICATION_ID
,VONAGE_PRIVATE_KEY_PATH
, orVONAGE_NUMBER
in your.env
file are incorrect or missing. The private key file might not exist at the specified path or might be corrupted. - Symptoms: Authentication errors from the Vonage SDK (often a
401 Unauthorized
response buried in the error details), application crashes on startup ifdotenv
fails or critical vars are missing. - Solution: Double-check all values in your
.env
file against your Vonage Application details and the path to yourprivate.key
. Ensure the.env
file is in the project root and is being loaded (import 'dotenv/config';
at the top ofindex.js
). Verify theprivate.key
file exists and is readable.
- Problem:
- Messages API Not Set as Default:
- Problem: If your account default is still the legacy ""SMS API"", the
vonage.messages.send
call might behave unexpectedly or fail, or webhook formats might differ if you add receiving later. - Solution: Ensure you have set Messages API as the default under API Settings -> SMS Settings in the Vonage dashboard.
- Problem: If your account default is still the legacy ""SMS API"", the
- Invalid Phone Number Format:
- Problem: The
to
orfrom
number is not in the required E.164 format (e.g., missing+
and country code). - Error Message: Vonage might return an error like
""Invalid 'to' parameter""
or similar (400 Bad Request
). Our API validation also checks this now. - Solution: Ensure all phone numbers include the country code and are prefixed with
+
(although Vonage is sometimes lenient, E.164 is the standard). E.g.,+14155550101
,+447700900000
.
- Problem: The
dotenv
Not Loading:- Problem: Environment variables are
undefined
in your code. - Solution: Ensure
import 'dotenv/config';
is executed at the very beginning of your main entry file (src/index.js
) before any other code (especially code that relies onprocess.env
). Make sure the.env
file is in the project root directory from where you run thenode
command.
- Problem: Environment variables are
- Network Issues: Standard network connectivity problems between your server and the Vonage API can cause requests to fail or time out. Ensure your server has outbound internet access.
9. Deployment (Conceptual)
Deploying this Node.js application involves running it on a server or platform.
-
Choose a Platform: Options include:
- PaaS (Platform-as-a-Service): Heroku, Vercel (for serverless functions), Render, Google App Engine, Azure App Service. Often simpler to manage.
- IaaS (Infrastructure-as-a-Service): AWS EC2, Google Compute Engine, DigitalOcean Droplets. More control, more management overhead.
- Containers: Dockerizing the app and running it on Kubernetes, AWS ECS, Google Cloud Run, etc.
-
Build for Production: You might add a build step if using TypeScript or other transpilers. For this simple JavaScript app, no build step is strictly needed.
-
Environment Variables: Crucially, configure the environment variables (
PORT
,VONAGE_APPLICATION_ID
,VONAGE_PRIVATE_KEY_PATH
,VONAGE_NUMBER
) securely within your chosen deployment platform's settings. Do not commit the.env
file. You will also need to securely transfer theprivate.key
file to your server or use a secret management system. EnsureVONAGE_PRIVATE_KEY_PATH
points to the correct location on the server. -
Install Dependencies: Run
npm install --omit=dev
(ornpm install --production
for older npm versions) on the server to install only production dependencies. -
Run the App: Use a process manager like
pm2
to run your Node.js application reliably in the background, handle restarts, and manage logs.npm install pm2 -g # Install pm2 globally (or locally) pm2 start src/index.js --name vonage-sms-api # Start the app
-
HTTPS: Configure a reverse proxy (like Nginx) to handle incoming traffic, terminate SSL/TLS (HTTPS), and forward requests to your Node.js app running on
localhost:PORT
. -
CI/CD: Set up a Continuous Integration/Continuous Deployment pipeline (using GitHub Actions, GitLab CI, Jenkins, etc.) to automate testing and deployment whenever you push changes to your repository.
10. Verification and Testing
Beyond manual testing with curl
or Postman:
- Unit Tests: Use a testing framework like Jest or Mocha/Chai to write unit tests for:
- The
sendSms
function invonageService.js
. You would mock the@vonage/server-sdk
to avoid making actual API calls during tests, verifying that the SDK method is called with the correct parameters. - Input validation logic within the API endpoint.
- The
- Integration Tests: Write tests that start your Express server and make actual HTTP requests to the
/send-sms
endpoint (potentially still mocking the Vonage SDK call at the boundary or using dedicated test credentials with Vonage if available). - End-to-End (E2E) Tests: (Use sparingly, can be slow/costly) Tests that make requests to your deployed API and potentially verify SMS delivery using test phone numbers (requires more setup).
Manual Verification Checklist:
- Vonage account created and accessible.
- Vonage Application created, Application ID noted.
private.key
downloaded and placed correctly in the project.- Messages capability enabled for the Vonage Application.
- Vonage virtual number acquired and linked to the Application.
- Messages API set as the default SMS API in Vonage settings.
.env
file created with correctVONAGE_APPLICATION_ID
,VONAGE_PRIVATE_KEY_PATH
, andVONAGE_NUMBER
.- Project dependencies installed (
npm install
). - Application starts without errors (
npm start
). - Test SMS sent successfully using
curl
or Postman to a whitelisted number (if on trial). - SMS message received on the target device.
- Error responses tested (e.g., sending without
to
ortext
, sending to a non-whitelisted number on trial). Logs show appropriate errors. - (If rate limiting added) Rate limit tested by sending multiple requests quickly.
Conclusion
You have successfully built a Node.js Express application capable of sending SMS messages using the Vonage Messages API. We configured the project, handled Vonage credentials securely, implemented the core sending logic with error handling, created an API endpoint, and discussed essential considerations for security, testing, and deployment.