This guide provides a step-by-step walkthrough for building a Node.js application using the Express framework to send Multimedia Messaging Service (MMS) and Short Message Service (SMS) messages via the Vonage Messages API. We will cover project setup, configuration, core implementation, security basics, error handling, and testing.
By the end of this tutorial, you will have a functional Express API capable of sending image-based MMS messages and standard text SMS messages, along with the knowledge to integrate Vonage messaging capabilities into your own applications.
Project Overview and Goals
Goal: To create a simple yet robust Node.js Express API that can programmatically send MMS messages (containing images) and fallback SMS messages using the Vonage Messages API.
Problem Solved: This application provides a backend service enabling other applications or systems to send MMS/SMS notifications or communications without directly handling the complexities of carrier interactions. It specifically addresses the need to send rich media messages (MMS) where supported, primarily within the US market.
Technologies Used:
- 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 the API endpoints.
- Vonage Messages API: A unified API from Vonage enabling communication across various channels, including SMS and MMS. We'll use it for its versatility.
@vonage/server-sdk
: The official Vonage Server SDK for Node.js, simplifying interactions with the Vonage APIs.dotenv
: A module to load environment variables from a.env
file, keeping sensitive credentials out of the codebase.- ngrok (Optional): A tool to expose local servers to the internet, useful for testing webhook functionality like delivery receipts. This is primarily needed only if you plan to implement the optional webhook section (Section 6).
System Architecture:
- Client Application (e.g., cURL, Postman, another app): Sends an HTTP POST request to the Node.js/Express API endpoint (
/send-mms
or/send-sms
). - Node.js/Express API: Receives the request, validates it, and uses the Vonage SDK.
- Vonage SDK (
@vonage/server-sdk
): Calls the Vonage Messages API (vonage.messages.send()
). - Vonage Messages API: Processes the request and sends the MMS or SMS message to the recipient's phone.
- Recipient's Phone: Receives the message.
- (Optional Flow for Webhooks):
- Vonage Messages API: Sends a status update (webhook) to a configured URL.
- ngrok: If testing locally, ngrok forwards the webhook from a public URL to the local Express server.
- Node.js/Express API: Receives the status webhook at a dedicated endpoint (e.g.,
/webhooks/status
) for processing.
Expected Outcome:
- A running Node.js Express server with two API endpoints:
POST /send-mms
: Accepts a recipient number, image URL, and caption to send an MMS.POST /send-sms
: Accepts a recipient number and text message to send an SMS.
- Secure configuration using environment variables.
- Basic error handling and logging for message sending attempts.
Prerequisites:
- Node.js and npm (or yarn): Installed on your development machine. Download Node.js
- Vonage API Account: Sign up for free if you don't have one. Vonage Signup
- Vonage Phone Number: A US-based virtual number capable of sending SMS and MMS, purchased through your Vonage account. Note that MMS is primarily a US-centric feature for this type of sending.
- Basic understanding of JavaScript and REST APIs.
- (Optional) ngrok: For testing webhook functionality. Download ngrok
1. Setting up the Project
Let's initialize the Node.js project and install the necessary dependencies.
-
Create Project Directory: Open your terminal or command prompt and create a new directory for your project, then navigate into it.
mkdir vonage-mms-sender cd vonage-mms-sender
-
Initialize Node.js Project: This command creates a
package.json
file to manage your project's dependencies and scripts.npm init -y
-
Install Dependencies: We need Express for the web server, the Vonage SDK to interact with the API, and
dotenv
for managing environment variables.npm install express @vonage/server-sdk dotenv
express
: Web framework.@vonage/server-sdk
: Vonage Node.js library.dotenv
: Loads environment variables from.env
.
-
Create Project Files: Create the main application file and files for configuration and security.
# On Linux/macOS touch index.js .env .gitignore # On Windows (Command Prompt) type nul > index.js type nul > .env type nul > .gitignore # On Windows (PowerShell) New-Item index.js -ItemType File New-Item .env -ItemType File New-Item .gitignore -ItemType File
-
Configure
.gitignore
: It's crucial to prevent sensitive information and unnecessary files from being committed to version control (like Git). Add the following lines to your.gitignore
file:# Node modules node_modules/ # Environment variables .env # Log files *.log # OS generated files .DS_Store Thumbs.db # Vonage private key (if stored directly, though ENV var is better) private.key *.key
Project Structure Explanation:
index.js
: The main entry point for our Express application.package.json
: Defines project metadata and dependencies.package-lock.json
: Records exact dependency versions..env
: Stores environment variables (API keys, secrets, etc.). Never commit this file..gitignore
: Specifies intentionally untracked files that Git should ignore.node_modules/
: Directory where npm installs project dependencies.
2. Vonage Account and Application Setup
Before writing code, you need to configure your Vonage account and set up a Vonage Application. The Messages API requires an Application context for authentication using a public/private key pair.
- Log in to Vonage Dashboard: Access your Vonage API Dashboard.
- Note API Key and Secret: You can find your main account
API key
andAPI secret
on the dashboard homepage. While we primarily use Application ID and Private Key for the Messages API, it's good to know where these are. - Buy a Number:
- Navigate to Numbers > Buy numbers.
- Search for numbers in the United States.
- Ensure the number has SMS and MMS capabilities listed in its features. Note that MMS sending capability via long codes/TFNs is primarily a US/Canada feature.
- Purchase a suitable number. Note this number down – it will be your
VONAGE_NUMBER
.
- Create a Vonage Application:
- Navigate to Applications > + Create a new application.
- Give your application a name (e.g.,
""Node MMS Sender""
). - Click Generate public and private key. This will automatically download a
private.key
file to your computer and populate the Public key field. Store theprivate.key
file securely. We will reference its path later. It's best practice not to commit this key file directly to your repository. - Enable the Messages capability.
- You'll see fields for Inbound URL and Status URL. For sending messages, the Status URL is important for receiving delivery receipts (DLRs). The Inbound URL is for receiving messages sent to your Vonage number.
- For now, you can use a placeholder like
https://example.com/webhooks/status
andhttps://example.com/webhooks/inbound
. We'll configure actual URLs later if we implement webhook handling (Section 6). If using ngrok, you'd put your ngrok forwarding URL here (e.g.,https://<your-ngrok-subdomain>.ngrok.io/webhooks/status
).
- For now, you can use a placeholder like
- Click Generate new application.
- You will be taken to the application's details page. Copy the Application ID. This is your
VONAGE_APPLICATION_ID
.
- Link Your Number:
- On the application details page, scroll down to the Linked numbers section.
- Click Link next to the US number you purchased earlier.
- Set Default SMS API:
- Navigate to Account > API settings.
- Scroll down to the SMS settings section.
- Ensure Default SMS Setting is set to Messages API. This ensures consistency when using the SDK methods intended for the Messages API. Click Save changes.
You now have:
- Your Vonage Number (
VONAGE_NUMBER
) - Your Application ID (
VONAGE_APPLICATION_ID
) - The path to your downloaded
private.key
file (VONAGE_PRIVATE_KEY_PATH
) - Your main account API Key and Secret (stored for reference, but less critical for this specific Messages API flow)
3. Environment Configuration
Store your credentials and configuration securely using a .env
file.
-
Move the Private Key (Optional but Recommended): Move the downloaded
private.key
file into your project directory (e.g., the rootvonage-mms-sender/
). Remember this file is listed in.gitignore
. -
Edit
.env
File: Open the.env
file and add the following variables, replacing the placeholder values with your actual credentials obtained in the previous step.# Vonage Credentials # Found on the Vonage Dashboard homepage VONAGE_API_KEY=YOUR_API_KEY VONAGE_API_SECRET=YOUR_API_SECRET # Found in your Vonage Application settings VONAGE_APPLICATION_ID=YOUR_APPLICATION_ID # Path to the private key file downloaded when creating the application # Example: ./private.key if it's in the project root VONAGE_PRIVATE_KEY_PATH=./private.key # Your Vonage virtual number (US MMS/SMS capable) # Use E.164 format (e.g., 12015550123) VONAGE_NUMBER=YOUR_VONAGE_NUMBER_E164 # Application Port APP_PORT=3000 # Example for Section 7 Security (Optional - uncomment and set a value if using the example) # MY_SECRET_API_KEY=YOUR_CHOSEN_SECRET_API_KEY
Explanation of Variables:
VONAGE_API_KEY
,VONAGE_API_SECRET
: Your main account credentials. While the Messages API primarily uses the App ID/Private Key for authentication via the SDK's JWT generation, having these might be useful for other potential API interactions or CLI usage.VONAGE_APPLICATION_ID
: Identifies the Vonage application context for your messaging.VONAGE_PRIVATE_KEY_PATH
: The file system path to your private key. The SDK uses this to authenticate requests for the Messages API.VONAGE_NUMBER
: The Vonage virtual number (sender ID) from which messages will be sent. Must be in E.164 format.APP_PORT
: The port on which your Express server will listen.MY_SECRET_API_KEY
: (Optional) A secret key you define for basic API authentication, used in the example in Section 7.
Security: The .env
file keeps sensitive data separate from your code. The .gitignore
entry ensures it's not accidentally exposed in version control. For production deployments, you'll typically set these environment variables directly on the hosting platform.
4. Implement Express Server
Set up the basic Express server structure.
Edit your index.js
file:
// index.js
require('dotenv').config(); // Load environment variables from .env file
const express = require('express');
// --- Basic Server Setup ---
const app = express();
const port = process.env.APP_PORT || 3000; // Use port from .env or default to 3000
// --- Middleware ---
// Enable parsing of JSON request bodies
app.use(express.json());
// Enable parsing of URL-encoded request bodies
app.use(express.urlencoded({ extended: true }));
// --- Basic Route ---
app.get('/', (req, res) => {
res.send('Vonage MMS/SMS Sender API is running!');
});
// --- Placeholder for API Endpoints (We will add these next) ---
// app.post('/send-mms', ...);
// app.post('/send-sms', ...);
// app.post('/webhooks/status', ...); // Optional for DLRs
// --- Start Server ---
app.listen(port, () => {
// Log server start with current date
const startDate = new Date().toLocaleDateString('en-US', { month: 'long', day: 'numeric', year: 'numeric' });
console.log(`Server listening at http://localhost:${port} on ${startDate}`);
});
// --- Basic Error Handling (Example - enhance as needed) ---
app.use((err, req, res, next) => {
console.error(""Unhandled Error:"", err.stack);
res.status(500).send('Something broke!');
});
// Export app for potential testing frameworks
module.exports = app;
Explanation:
require('dotenv').config();
: Loads variables from the.env
file intoprocess.env
.express()
: Creates an Express application instance.app.use(express.json())
,app.use(express.urlencoded(...))
: Middleware to parse incoming JSON and URL-encoded request payloads, making them available asreq.body
.app.get('/')
: A simple route to confirm the server is running.app.listen()
: Starts the server and makes it listen for connections on the specified port.- Basic error handling middleware is added as a safety net.
You can run this basic server now:
node index.js
You should see the ""Server listening..."" message in your console. Open http://localhost:3000
in your browser to see the welcome message. Press Ctrl+C
to stop the server.
5. Implement Sending Logic (MMS & SMS)
Now, let's integrate the Vonage SDK and create the API endpoints for sending messages.
First, initialize the Vonage client near the top of index.js
, after loading dotenv:
// index.js
require('dotenv').config();
const express = require('express');
const { Vonage } = require('@vonage/server-sdk'); // Import Vonage
const fs = require('fs'); // Import Node.js file system module
// --- Vonage Client Initialization ---
let vonage;
try {
// Ensure the private key path exists before initializing
const privateKeyPath = process.env.VONAGE_PRIVATE_KEY_PATH;
if (!privateKeyPath || !fs.existsSync(privateKeyPath)) {
throw new Error(`Private key file not found at path: ${privateKeyPath}. Please check your VONAGE_PRIVATE_KEY_PATH environment variable.`);
}
vonage = new Vonage({
apiKey: process.env.VONAGE_API_KEY, // Good practice to include, though Messages uses App ID/Key primarily
apiSecret: process.env.VONAGE_API_SECRET,
applicationId: process.env.VONAGE_APPLICATION_ID,
privateKey: privateKeyPath // Provide the path here
}, {
// Optional: Custom logger, user agent, etc.
// logger: console // Example: Use console for logging SDK actions
});
console.log(""Vonage client initialized successfully."");
} catch (error) {
console.error(""FATAL: Failed to initialize Vonage client:"", error.message);
// Optionally exit if Vonage client is critical and cannot be initialized
// process.exit(1);
}
// --- Basic Server Setup ---
// ... (rest of the server setup code from Section 4) ...
Now, add the API endpoints below the basic /
route and before the app.listen
call:
// index.js
// ... (Vonage client initialization and basic server setup) ...
// --- API Endpoints ---
/**
* @route POST /send-mms
* @description Sends an MMS message with an image.
* @access Public (Add auth middleware in production)
* @requestBody { ""to"": ""E.164_PHONE_NUMBER"", ""imageUrl"": ""PUBLIC_IMAGE_URL"", ""caption"": ""Optional text caption"" }
* @response 200 { ""success"": true, ""message_uuid"": ""VONAGE_MESSAGE_UUID"" }
* @response 400 { ""success"": false, ""error"": ""Description of validation error"" }
* @response 500 { ""success"": false, ""error"": ""Description of sending error"" }
*/
app.post('/send-mms', async (req, res) => {
if (!vonage) {
return res.status(500).json({ success: false, error: ""Vonage client not initialized."" });
}
const { to, imageUrl, caption } = req.body;
const from = process.env.VONAGE_NUMBER;
// Basic Input Validation
if (!to || !imageUrl) {
return res.status(400).json({ success: false, error: ""Missing required fields: 'to' and 'imageUrl'"" });
}
// Add more robust validation (e.g., E.164 format check for 'to', URL validation for 'imageUrl')
console.log(`Attempting to send MMS to: ${to} from: ${from} with image: ${imageUrl}`);
try {
const resp = await vonage.messages.send({
message_type: ""image"",
image: {
url: imageUrl,
caption: caption || """" // Use provided caption or empty string
},
to: to,
from: from,
channel: ""mms""
});
console.log(""MMS Sent Successfully:"", resp);
res.status(200).json({ success: true, message_uuid: resp.message_uuid });
} catch (error) {
console.error(""Error sending MMS:"", error?.response?.data || error.message); // Log detailed error if available
// Provide a more user-friendly error message
let errorMessage = ""Failed to send MMS."";
if (error?.response?.data?.title) {
errorMessage = `Failed to send MMS: ${error.response.data.title} - ${error.response.data.detail || ''}`;
} else if (error.message) {
errorMessage = `Failed to send MMS: ${error.message}`;
}
res.status(error?.response?.status || 500).json({ success: false, error: errorMessage });
}
});
/**
* @route POST /send-sms
* @description Sends a standard SMS text message.
* @access Public (Add auth middleware in production)
* @requestBody { ""to"": ""E.164_PHONE_NUMBER"", ""text"": ""Your message content"" }
* @response 200 { ""success"": true, ""message_uuid"": ""VONAGE_MESSAGE_UUID"" }
* @response 400 { ""success"": false, ""error"": ""Description of validation error"" }
* @response 500 { ""success"": false, ""error"": ""Description of sending error"" }
*/
app.post('/send-sms', async (req, res) => {
if (!vonage) {
return res.status(500).json({ success: false, error: ""Vonage client not initialized."" });
}
const { to, text } = req.body;
const from = process.env.VONAGE_NUMBER;
// Basic Input Validation
if (!to || !text) {
return res.status(400).json({ success: false, error: ""Missing required fields: 'to' and 'text'"" });
}
// Add more robust validation
console.log(`Attempting to send SMS to: ${to} from: ${from} with text: ""${text}""`);
try {
const resp = await vonage.messages.send({
message_type: ""text"",
text: text,
to: to,
from: from,
channel: ""sms""
});
console.log(""SMS Sent Successfully:"", resp);
res.status(200).json({ success: true, message_uuid: resp.message_uuid });
} catch (error) {
console.error(""Error sending SMS:"", error?.response?.data || error.message);
let errorMessage = ""Failed to send SMS."";
if (error?.response?.data?.title) {
errorMessage = `Failed to send SMS: ${error.response.data.title} - ${error.response.data.detail || ''}`;
} else if (error.message) {
errorMessage = `Failed to send SMS: ${error.message}`;
}
res.status(error?.response?.status || 500).json({ success: false, error: errorMessage });
}
});
// --- Start Server ---
// ... (app.listen call) ...
// --- Basic Error Handling ---
// ... (app.use error handler) ...
Explanation:
- Vonage Client: The
vonage
instance is initialized using credentials from.env
. A check is added to ensure the private key file exists. Error handling is included for initialization failure. - Async/Await: The route handlers are
async
functions to allow usingawait
for the asynchronousvonage.messages.send
call. - Input Validation: Basic checks ensure required fields (
to
,imageUrl
/text
) are present in the request body (req.body
). Production applications need more robust validation (e.g., using libraries likejoi
orexpress-validator
). vonage.messages.send()
: This is the core function from the Vonage SDK used to send messages via the Messages API.message_type
: Set to""image""
for MMS or""text""
for SMS.image
: An object containing theurl
(must be publicly accessible) and an optionalcaption
for MMS. Supported image types are typically JPEG, PNG, GIF. Check Vonage documentation for specifics and size limits.text
: The message content for SMS.to
: The recipient's phone number in E.164 format (e.g.,14155550101
).from
: Your Vonage virtual number (VONAGE_NUMBER
).channel
: Explicitly set to""mms""
or""sms""
.
- Response: On success, it returns a 200 status with the
message_uuid
provided by Vonage. On failure, it logs the error and returns an appropriate status code (400 for bad input, 500 or Vonage's error status for sending issues) with an error message. - Error Handling: The
try...catch
block handles errors during the API call. It attempts to log detailed error information from Vonage (error.response.data
) if available.
6. Handling Webhooks (Optional - Delivery Receipts)
To confirm message delivery status, Vonage sends information to the ""Status URL"" you configured in your Vonage Application. Let's set up ngrok and a basic webhook handler.
-
Start ngrok: If you haven't already, download and set up ngrok. Run it to expose your local server's port (e.g., 3000).
./ngrok http 3000 # Or on Windows: ngrok.exe http 3000
ngrok will provide a forwarding URL (e.g.,
https://abcd-1234.ngrok.io
). Copy thehttps
version. -
Update Vonage Application Status URL:
- Go back to your application settings in the Vonage Dashboard.
- Edit the Messages capability.
- Paste your ngrok forwarding URL into the Status URL field, appending a path like
/webhooks/status
. Example:https://abcd-1234.ngrok.io/webhooks/status
. - Set the HTTP Method for the Status URL to
POST
. - Save the changes.
-
Add Webhook Endpoint in
index.js
: Add this route handler before theapp.listen
call:// index.js // ... (other routes) ... /** * @route POST /webhooks/status * @description Receives message status updates (DLRs) from Vonage. * @access Public (Verify requests in production using JWT or signatures) * @requestBody Vonage Status Webhook Payload * @response 200 OK */ app.post('/webhooks/status', (req, res) => { console.log(""--- Status Webhook Received ---""); console.log(""Timestamp:"", new Date().toISOString()); console.log(""Body:"", JSON.stringify(req.body, null, 2)); // Log the entire status update // Add logic here to process the status (e.g., update database) // Example: Log key info if (req.body.message_uuid && req.body.status) { console.log(`Status for ${req.body.message_uuid}: ${req.body.status}`); } // Vonage expects a 200 OK response to acknowledge receipt res.status(200).end(); }); // --- Start Server --- // ... (app.listen call) ...
Explanation:
- This endpoint listens for
POST
requests at the path you configured in Vonage (/webhooks/status
). - It logs the received status update payload. The payload structure contains details like
message_uuid
,status
(delivered
,failed
,rejected
, etc.),timestamp
, and potentially error codes. Refer to the Vonage Messages API documentation for the exact payload structure. - Crucially, it sends back a
200 OK
status immediately. If Vonage doesn't receive a 200 OK, it will retry sending the webhook, leading to duplicate processing. - Security: In production, you must secure this webhook endpoint. Vonage provides mechanisms like Signed Webhooks (using JWT) to verify that incoming requests genuinely originated from Vonage. Implementing webhook signature verification is beyond this basic guide but essential for production.
Restart your server (node index.js
) after adding the webhook. Now, when you send messages, status updates should be logged to your console via ngrok.
7. Security Considerations
While this guide focuses on basic functionality, production applications require stronger security:
- Input Validation: Implement thorough validation for all inputs (
to
number format,imageUrl
validity and source,text
length and content). Libraries likejoi
orexpress-validator
are recommended.// Example using basic regex for E.164 (adapt as needed) const e164Pattern = /^\+[1-9]\d{1,14}$/; if (!e164Pattern.test(to)) { return res.status(400).json({ success: false, error: ""Invalid 'to' phone number format. Use E.164 (e.g., +12125551234)."" }); }
- Authentication/Authorization: Protect your API endpoints. Implement API keys, JWT tokens, OAuth, or other mechanisms to ensure only authorized clients can send messages.
// Example: Simple API Key Check (Replace with robust auth) app.use((req, res, next) => { const apiKey = req.headers['x-api-key']; // Make sure MY_SECRET_API_KEY is set in your .env file if (apiKey && process.env.MY_SECRET_API_KEY && apiKey === process.env.MY_SECRET_API_KEY) { next(); } else { // Avoid logging unauthorized attempts unless debugging, could be noisy console.warn('Unauthorized API attempt detected.'); res.status(401).json({ success: false, error: 'Unauthorized' }); } });
- Rate Limiting: Prevent abuse by limiting the number of requests a client can make within a certain time window. Use middleware like
express-rate-limit
.npm install express-rate-limit
// In index.js 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 all requests // app.use(limiter); // Or apply specifically to sending routes app.use('/send-mms', limiter); app.use('/send-sms', limiter);
- Webhook Security: As mentioned, verify incoming webhooks using Vonage's signing mechanisms (JWT).
- Secure Key Management: Never hardcode credentials. Use environment variables and secure storage mechanisms provided by your deployment platform. Ensure the
private.key
file has restricted permissions on the server. Consider loading the key content directly into an environment variable instead of relying on a file path in production.
8. Error Handling and Logging
Robust error handling and logging are vital for debugging and monitoring.
- Consistent Error Responses: Standardize your error response format (e.g.,
{ success: false, error: ""Error message"", code: ""ERROR_CODE"" }
). - Detailed Logging: Use a dedicated logging library like
Winston
for production instead ofconsole.log
. Configure log levels (info, warn, error) and output destinations (file, console, external service).npm install winston
// Example: Basic Winston setup const winston = require('winston'); const logger = winston.createLogger({ level: process.env.LOG_LEVEL || 'info', // Control level via environment format: winston.format.combine( winston.format.timestamp(), winston.format.json() // Use JSON format for structured logging ), transports: [ new winston.transports.Console({ format: winston.format.combine( winston.format.colorize(), // Add color for console readability winston.format.simple() ) }) // Add file transport for production (recommended) // new winston.transports.File({ filename: 'error.log', level: 'error' }), // new winston.transports.File({ filename: 'combined.log' }), ], }); // Replace console.log/error with logger.info, logger.warn, logger.error // Example: logger.info(`Server listening at http://localhost:${port}`); // Example: logger.error(""Error sending MMS:"", { message: error.message, response: error?.response?.data });
- Specific Vonage Errors: Handle specific error codes or messages returned by the Vonage API for more granular retry logic or user feedback (e.g., invalid number format, insufficient funds, carrier violations). Check the
error.response.data
object. - Retry Mechanisms: For transient network issues or temporary Vonage service problems, implement retry logic (e.g., using libraries like
async-retry
) with exponential backoff for sending requests. Be cautious not to retry indefinitely or for non-recoverable errors.
9. Testing and Verification
Test your endpoints thoroughly.
-
Start Your Server:
node index.js
-
Send Test MMS (using cURL): Replace placeholders with your test recipient number (must be whitelisted if your Vonage account is in trial mode) and a valid public image URL.
curl -X POST http://localhost:3000/send-mms \ -H ""Content-Type: application/json"" \ -H ""x-api-key: YOUR_CHOSEN_SECRET_API_KEY"" \ -d '{ ""to"": ""+1YOUR_TEST_RECIPIENT_NUMBER"", ""imageUrl"": ""https://placekitten.com/200/300"", ""caption"": ""Hello from Node/Vonage!"" }'
(Note: Add the
-H ""x-api-key: ...""
header if you implemented the example security middleware from Section 7)Expected Success Response:
{ ""success"": true, ""message_uuid"": ""xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"" }
Check the recipient's phone for the MMS message. Check your console logs for success messages.
-
Send Test SMS (using cURL):
curl -X POST http://localhost:3000/send-sms \ -H ""Content-Type: application/json"" \ -H ""x-api-key: YOUR_CHOSEN_SECRET_API_KEY"" \ -d '{ ""to"": ""+1YOUR_TEST_RECIPIENT_NUMBER"", ""text"": ""This is a test SMS from Node/Vonage."" }'
(Note: Add the
-H ""x-api-key: ...""
header if you implemented the example security middleware from Section 7)Expected Success Response:
{ ""success"": true, ""message_uuid"": ""yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy"" }
Check the recipient's phone for the SMS message. Check your console logs.
-
Test Error Cases:
- Send requests with missing fields (
to
,imageUrl
,text
). - Send requests with invalid phone number formats.
- Send requests with invalid image URLs (for MMS).
- Send requests without the API key (if implemented) or with an incorrect one.
- Temporarily modify
.env
with incorrect Vonage credentials to trigger authentication errors. - Check console logs for detailed error messages.
- Send requests with missing fields (
-
Verify Webhooks (if configured):
- Check the console where
node index.js
is running for ""Status Webhook Received"" logs after sending messages. - You can also inspect requests in the ngrok web interface (usually
http://127.0.0.1:4040
).
- Check the console where
10. Troubleshooting and Caveats
- MMS US/Canada Only: Vonage MMS sending via long codes/Toll-Free Numbers is primarily supported for sending to US and Canadian numbers from US/Canada numbers. Check Vonage documentation for the latest country support and regulations. SMS has much broader global reach.
- Trial Account Limitations: If your Vonage account is new/in trial mode, you can typically only send messages to phone numbers you have verified and added to your account's whitelist (Set up in the Vonage Dashboard).