How to Send MMS Messages with Vonage Messages API in Node.js | Complete Guide
Learn how to send MMS multimedia messages using Vonage Messages API in Node.js and Express. Complete tutorial with SDK setup, authentication, webhook handling, and production deployment for US 10DLC and short code numbers.
Important Notice: This guide implements MMS sending using Node.js with Express framework, not Next.js with NextAuth. If you need Next.js implementation, refer to Next.js-specific Vonage guides.
This guide walks you through building a production-ready Node.js application to send MMS messages using the Vonage Messages API and Express framework. You'll learn how to configure the Vonage Node.js SDK for multimedia messaging, handle API credentials securely, build API endpoints to trigger MMS sending, and implement essential features like error handling and logging. By the end, you'll have a functional MMS service capable of sending images programmatically to US-based phone numbers.
MMS Availability (as of January 2025): MMS sending through Vonage Messages API is available with General Availability status. However, only US short codes, 10DLC numbers, and SMS-enabled toll-free numbers are currently supported. For US short codes, MMS messages can be sent to AT&T, T-Mobile (formerly Sprint), and Verizon networks in the US. Source: Vonage MMS Documentation
What You'll Build: MMS Sending Project Overview
What You're Building: A Node.js Express API with a single endpoint (/send-mms). When this endpoint receives a POST request containing a recipient phone number, a publicly accessible image URL, and an optional caption, it uses the Vonage Messages API to send an MMS message.
Problem Solved: This enables applications to programmatically send rich media content (images) via MMS – useful for notifications, alerts, marketing campaigns, or integrating media sharing into workflows.
Technologies Used:
Node.js: A JavaScript runtime for building server-side applications. Chosen for its asynchronous nature and large ecosystem (npm).
Express: A minimal and flexible Node.js web application framework. Chosen for its simplicity in creating API endpoints.
Vonage Messages API: A unified API for sending messages across various channels, including MMS. Chosen for its robust features and official Node.js SDK.
@vonage/messages SDK: The official Vonage Node.js SDK (v3.x) specifically for interacting with the Messages API. As of January 2025, MMS support has General Availability status. Source: npm @vonage/messages
dotenv: A module to load environment variables from a .env file into process.env. Chosen for easy management of configuration and secrets during development.
Note: ngrok is used as a development utility to expose the local server for receiving webhook status updates.
System Architecture:
An API client (like curl, Postman, or another application) sends a POST request to the /send-mms endpoint of the Node.js/Express API. The Express API uses the @vonage/messages SDK to call the send method with an MMS image message object. The SDK sends an MMS request to the Vonage Messages API. Vonage delivers the MMS to the recipient's phone. Vonage also sends status updates (webhooks) about the message delivery. During development, these webhooks are sent to an ngrok tunnel, which forwards them to the /webhooks/status endpoint on the local Express API server.
Prerequisites for Sending MMS with Vonage
Before you begin, ensure you have:
Node.js (v14 or higher recommended) and npm (or yarn) installed locally. Download Node.js
A Vonage Application ID and associated private.key file (created in Section 4).
A Vonage US phone number capable of sending MMS. Purchase one from the Numbers section of your Vonage dashboard. Critical: Only US short codes, 10DLC numbers, or SMS-enabled toll-free numbers support MMS. Standard long codes do not support MMS. Source: Vonage MMS Documentation
ngrok installed and authenticated (a free account is sufficient). Download ngrok. Used for receiving webhook status updates during development.
A target US phone number to receive the MMS. If using a trial Vonage account, add this number to the whitelisted numbers in your dashboard.
How to Set Up Your Node.js MMS Project
Initialize your Node.js project and install the necessary dependencies.
Create Project Directory:
Open your terminal and create a new directory for the project, then navigate into it.
Bash
mkdir vonage-mms-sender
cd vonage-mms-sender
Initialize Node.js Project:
Create a package.json file.
Bash
npm init -y
Install Dependencies:
Install Express for the server, the Vonage Messages SDK, and dotenv for environment variables.
Bash
npm install express @vonage/messages dotenv
Set Up Project Structure:
Create directories for source code and configuration.
Bash
mkdir src config
Create Environment File (.env):
Create a file named .env in the project root. This file stores sensitive credentials and configuration. Never commit this file to version control.
Text
# .env
# Vonage API Credentials (From Dashboard -> API Settings)
VONAGE_API_KEY=YOUR_API_KEY
VONAGE_API_SECRET=YOUR_API_SECRET
# Vonage Application Credentials (Generated in Dashboard -> Applications)
VONAGE_APPLICATION_ID=YOUR_APPLICATION_ID
VONAGE_PRIVATE_KEY_PATH=./private.key # Relative path to your private key file
# Vonage Number (From Dashboard -> Numbers -> Your Numbers)
VONAGE_FROM_NUMBER=YOUR_VONAGE_US_MMS_NUMBER # Must be MMS-capable US number, e.g., 14155550100
# Server Configuration
PORT=3000
# Ngrok URL (For development status webhooks)
# Example: https://YOUR_UNIQUE_SUBDOMAIN.ngrok-free.app
# Leave blank initially, fill in after running ngrok
NGROK_BASE_URL=
VONAGE_API_KEY, VONAGE_API_SECRET: Found directly on your Vonage dashboard. Required for basic SDK authentication.
VONAGE_APPLICATION_ID, VONAGE_PRIVATE_KEY_PATH: Obtained when creating a Vonage Application (covered in Section 4). Used for authenticating requests specifically for the Messages API.
VONAGE_FROM_NUMBER: Your purchased Vonage US number capable of sending MMS. Enter it without + or spaces.
PORT: The port your Express server listens on.
NGROK_BASE_URL: The public URL provided by ngrok, used for receiving status webhooks during development.
Create Git Ignore File (.gitignore):
Create a file named .gitignore in the project root to prevent committing sensitive files and generated folders.
Configuration Loading:
Create a file config/index.js to load and export environment variables.
JavaScript
// config/index.jsrequire('dotenv').config(); // Load variables from .env into process.envconst config = {
vonage: {
apiKey: process.env.VONAGE_API_KEY,
apiSecret: process.env.VONAGE_API_SECRET,
applicationId: process.env.VONAGE_APPLICATION_ID,
privateKeyPath: process.env.VONAGE_PRIVATE_KEY_PATH,
fromNumber: process.env.VONAGE_FROM_NUMBER,
},
server: {
port: process.env.PORT || 3000,
},
ngrokBaseUrl: process.env.NGROK_BASE_URL, // Used later for webhook setup if needed
};
// Basic validationif (!config.vonage.apiKey || !config.vonage.apiSecret || !config.vonage.applicationId || !config.vonage.privateKeyPath || !config.vonage.fromNumber) {
console.error('Missing required Vonage credentials in .env file');
process.exit(1); // Exit if critical config is missing
}
module.exports = config;
How to Implement the Vonage MMS Service
Create a dedicated service file to handle interactions with the Vonage Messages API. This promotes separation of concerns.
Create Service File:
Create src/services/vonageService.js.
Implement MMS Sending Logic:
Add the following code to initialize the Vonage SDK and define the function to send MMS.
JavaScript
// src/services/vonageService.jsconst { Messages, MMSImage } = require('@vonage/messages');
const config = require('../../config'); // Load our configuration// Initialize the Vonage Messages client// The Messages API uses Application ID + Private Key for JWT authentication,// alongside the standard API Key + Secret.const vonageMessages = newMessages({
apiKey: config.vonage.apiKey,
apiSecret: config.vonage.apiSecret,
applicationId: config.vonage.applicationId,
privateKey: config.vonage.privateKeyPath, // SDK reads the file path
});
/**
* Sends an MMS message using the Vonage Messages API.
* @param {string} to - The recipient phone number (E.164 format, e.g., 14155550101).
* @param {string} imageUrl - The publicly accessible URL of the image to send.
* @param {string} [caption=''] - Optional caption for the image.
* @returns {Promise<object>} - A promise that resolves with the Vonage API response.
* @throws {Error} - Throws an error if the message sending fails.
*/constsendMms = async (to, imageUrl, caption = '') => {
console.log(`Attempting to send MMS to ${to} from ${config.vonage.fromNumber}`);
// Validate image URL (basic check)if (!imageUrl || !imageUrl.startsWith('http')) {
thrownewError('Invalid or missing image URL. Must be a public HTTP/HTTPS URL.');
}
// Validate image formatconst supportedFormats = ['.jpg', '.jpeg', '.png', '.gif'];
const urlLower = imageUrl.toLowerCase();
const isSupported = supportedFormats.some(format => urlLower.includes(format));
if (!isSupported) {
console.warn(`Image URL may not be a supported format. Vonage MMS supports: ${supportedFormats.join(', ')}`);
}
// Construct the MMS message payload using the MMSImage classconst messagePayload = newMMSImage({
to: to,
from: config.vonage.fromNumber, // Your Vonage MMS-capable numberimage: {
url: imageUrl,
caption: caption, // Optional caption
},
channel: 'mms', // Specify the channel as MMSmessage_type: 'image', // Specify message type
});
try {
// Send the message using the SDKconst response = await vonageMessages.send(messagePayload);
console.log(`MMS submitted successfully to Vonage. Message UUID: ${response.message_uuid}`);
return response; // Contains message_uuid
} catch (error) {
console.error(`Error sending MMS via Vonage: ${error.message}`);
// Log more details for debugging if availableif (error.response && error.response.data) {
console.error('Vonage API Error Details:', JSON.stringify(error.response.data, null, 2));
}
// Re-throw a structured error or handle appropriatelythrownewError(`Failed to send MMS: ${error.message || 'Unknown Vonage API error'}`);
}
};
module.exports = {
sendMms,
};
Why this approach?
@vonage/messages SDK: This specific SDK package is designed for the Vonage Messages API, which handles MMS with General Availability status as of January 2025. Older SDKs or different methods might target the legacy SMS API.
MMSImage Class: The SDK provides convenient classes like MMSImage to structure the payload correctly for different message types, reducing errors.
Application ID + Private Key: The Messages API requires JWT authentication generated from your Application ID and private key for sending messages via specific channels like MMS, WhatsApp, etc. The SDK handles JWT generation internally when you provide the App ID and private key path.
Image Format Validation: Added validation to warn about unsupported formats. Vonage MMS accepts .jpg, .jpeg, .png, and .gif formats. Source: Vonage MMS Documentation
Async/Await: Using async/await makes asynchronous code cleaner and easier to read compared to raw promises or callbacks.
Error Handling: The try...catch block ensures that errors from the Vonage API are caught, logged, and potentially transformed before being propagated, allowing the calling code (your API endpoint) to handle them gracefully.
How to Build the Express API Endpoint for MMS
Create the Express server and the /send-mms endpoint.
Create Server File:
Create src/server.js.
Implement Express Server and Endpoint:
JavaScript
// src/server.jsconst express = require('express');
const config = require('../config'); // Load configurationconst { sendMms } = require('./services/vonageService'); // Import our service functionconst app = express();
// --- Middleware ---// Parse JSON request bodies
app.use(express.json());
// Parse URL-encoded request bodies
app.use(express.urlencoded({ extended: true }));
// Simple request logger middleware (optional but helpful)
app.use((req, res, next) => {
console.log(`[${newDate().toISOString()}] ${req.method}${req.url}`);
next();
});
// --- Routes ---// Health check endpoint
app.get('/health', (req, res) => {
res.status(200).json({ status: 'OK', timestamp: newDate().toISOString() });
});
// Endpoint to send MMS
app.post('/send-mms', async (req, res, next) => {
// Basic Input Validation (Consider using a library like express-validator for production)const { to, imageUrl, caption } = req.body;
if (!to || !imageUrl) {
return res.status(400).json({
success: false,
message: 'Missing required fields: `to` and `imageUrl` are required.',
});
}
// Simple validation for phone number format (basic example)if (!/^\d{10,15}$/.test(to.replace(/^\+/, ''))) {
return res.status(400).json({
success: false,
message: 'Invalid `to` phone number format. Use E.164 or digits only (10–15 digits).',
});
}
try {
// Call the Vonage service functionconst result = awaitsendMms(to, imageUrl, caption);
// Send success response
res.status(202).json({ // 202 Accepted: Request received, processing initiatedsuccess: true,
message: 'MMS submission accepted by Vonage.',
data: result, // Contains message_uuid
});
} catch (error) {
// Pass error to the error handling middlewarenext(error);
}
});
// --- Webhook Endpoint (for status updates) ---// Vonage sends status updates here (POST or GET depending on config)
app.all('/webhooks/status', (req, res) => {
console.log('Webhook received (Status):');
console.log('Headers:', JSON.stringify(req.headers, null, 2));
console.log('Body:', JSON.stringify(req.body, null, 2)); // Body format depends on Vonage settingsconsole.log('Query Params:', JSON.stringify(req.query, null, 2));
// IMPORTANT: Always respond with 200 OK to Vonage webhooks// Otherwise, Vonage will retry, potentially causing duplicate processing.
res.status(200).send('OK');
});
// --- Global Error Handler ---// This middleware catches errors passed via next(error)
app.use((err, req, res, next) => {
console.error('Global Error Handler Caught:', err.stack || err);
// Determine status code – default to 500const statusCode = err.statusCode || 500;
res.status(statusCode).json({
success: false,
message: err.message || 'An internal server error occurred.',
// Optionally include stack trace in development
...(process.env.NODE_ENV === 'development' && { stack: err.stack }),
});
});
// --- Start Server ---constPORT = config.server.port;
app.listen(PORT, () => {
console.log(`Server listening on http://localhost:${PORT}`);
console.log(`Health check available at http://localhost:${PORT}/health`);
if (config.ngrokBaseUrl) {
console.log(`Status Webhook expected at: ${config.ngrokBaseUrl}/webhooks/status`);
} else {
console.warn("NGROK_BASE_URL not set in .env – Status webhooks won't be received locally without ngrok.");
}
});
Add Start Script to package.json:
Modify the scripts section in your package.json:
JSON
// package.json{// ... other properties"scripts":{"start":"node src/server.js","dev":"nodemon src/server.js"// Optional: if you install nodemon (`npm install --save-dev nodemon`)},// ... other properties}
How to Configure Vonage Dashboard for MMS Sending
Before running the code, configure your Vonage account and application correctly.
Enter an Application name (e.g., "Node MMS Sender").
Click "Generate public and private key". This automatically downloads a private.key file to your computer and populates the public key field.
IMPORTANT: Move the downloaded private.key file into the root directory of your Node.js project (the same level as your .env file). Ensure the VONAGE_PRIVATE_KEY_PATH in your .env file points to it (e.g., ./private.key).
Enable the "Messages" capability.
You'll see fields for Inbound URL and Status URL. These are webhook endpoints where Vonage sends data to your application.
Status URL: This is where Vonage sends updates about the delivery status of your outgoing MMS messages. For development, use ngrok. Leave it blank for now, or put a placeholder like http://localhost:3000/webhooks/status. Update this after starting ngrok. Set the HTTP method to POST.
Inbound URL: This is where Vonage sends incoming messages sent to your Vonage number. We are not handling inbound MMS in this guide, but it's required. Use the same placeholder: http://localhost:3000/webhooks/inbound. Set the HTTP method to POST.
Click "Create application".
You'll be redirected to the application's page. Copy the Application ID displayed.
Paste this ID into the VONAGE_APPLICATION_ID field in your .env file.
Link Your Vonage Number:
On the application page you were just directed to (or by navigating back to Applications and clicking your app name), scroll down to the "Linked numbers" section.
Find your US MMS-capable Vonage number in the list.
Click the "Link" button next to it. If you don't have a suitable number, click "Buy numbers".
Ensure the VONAGE_FROM_NUMBER in your .env file matches this linked number (use E.164 format without +, e.g., 14155550100).
Set up ngrok (for Status Webhooks during Development):
Open a new terminal window (keep your Node.js app terminal separate).
Run ngrok to expose the port your Express app listens on (defined in .env, default 3000).
Bash
ngrok http 3000
ngrok displays output including a Forwarding URL (e.g., https://random-subdomain.ngrok-free.app). Copy this HTTPS URL.
Paste this base URL into the NGROK_BASE_URL field in your .env file.
Edit the Status URL under the "Messages" capability. Set it to your ngrok Forwarding URL followed by the webhook path defined in server.js: YOUR_NGROK_URL/webhooks/status (e.g., https://random-subdomain.ngrok-free.app/webhooks/status). Ensure the method is POST.
Update the Inbound URL similarly: YOUR_NGROK_URL/webhooks/inbound.
Click "Save changes".
How to Handle Errors and Implement Retry Logic
Your current setup includes basic error handling:
Service Level (vonageService.js): Catches errors during the vonageMessages.send call, logs details, and throws a new error.
API Level (server.js):
Uses try...catch in the route handler to catch errors from the service.
Passes caught errors to a global Express error handling middleware using next(error).
The global error handler logs the error stack and sends a standardized JSON error response to the client.
Basic input validation prevents obviously bad requests.
Logging: Uses console.log and console.error. For production, consider structured logging libraries like Winston or Pino for better log management and analysis.
You would then configure Winston (e.g., log to files, different levels) and replace console.log/error calls.
Retry Mechanisms:
Vonage Retries: Vonage automatically retries sending webhooks (like the status update) to your specified URL if it doesn't receive a 200 OK response quickly. This is why res.status(200).send('OK'); in the /webhooks/status endpoint is crucial.
Application Retries: For failures in the initial sendMms call (e.g., temporary network issue to Vonage, intermittent Vonage API errors), you might implement application-level retries. Libraries like async-retry can help implement strategies like exponential backoff. However, be cautious about retrying errors that are clearly permanent (e.g., invalid credentials, invalid recipient number).
JavaScript
// Conceptual example using async-retry (Install: npm install async-retry)// In vonageService.js// const retry = require('async-retry');//// const sendMmsWithRetry = async (to, imageUrl, caption = '') => {// await retry(async bail => {// // If Vonage returns specific errors indicating non-transient failure, use bail()// // Example: if (error.response && error.response.data.code === 'INVALID_CREDENTIALS') {// // bail(new Error('Non-retryable error: Invalid Credentials'));// // return;// // }// await sendMms(to, imageUrl, caption); // Call original function// }, {// retries: 3, // Number of retries// factor: 2, // Exponential backoff factor// minTimeout: 1000, // Initial timeout// onRetry: (error, attempt) => console.warn(`Retry attempt ${attempt} failed: ${error.message}`),// });// };
How to Track MMS Delivery Status with Webhooks
While this guide focuses solely on sending MMS, a production application often needs to track the status of sent messages. This typically involves a database.
Conceptual Schema: You might have a messages table:
SQL
CREATE TABLE messages (
id SERIAL PRIMARY KEY, -- Or UUID
vonage_message_uuid VARCHAR(255) UNIQUE, -- UUID returned by Vonage
recipient_number VARCHAR(20) NOT NULL,
sender_number VARCHAR(20) NOT NULL,
image_url TEXT,
caption TEXT,
status VARCHAR(50) DEFAULT'submitted', -- e.g., submitted, delivered, failed, unknown
status_timestamp TIMESTAMPTZ,
vonage_status_code VARCHAR(10), -- Code received in status webhook
error_description TEXT, -- Error details from webhook
submitted_at TIMESTAMPTZ DEFAULTCURRENT_TIMESTAMP,
updated_at TIMESTAMPTZ DEFAULTCURRENT_TIMESTAMP
);
Data Layer:
Use an ORM (like Prisma, Sequelize, TypeORM) or a database client (like pg for PostgreSQL) to interact with this table.
On Send: After successfully calling sendMms and getting the message_uuid, insert a new record into the messages table with status = 'submitted'.
On Status Webhook: When the /webhooks/status endpoint receives an update from Vonage containing a message_uuid, find the corresponding record in the messages table and update its status, status_timestamp, vonage_status_code, and potentially error_description based on the webhook data.
Implementing this is beyond the scope of this specific guide but is a critical next step for robust tracking. For more details on handling webhook callbacks, see our guide on delivery status callbacks.
How to Secure Your Vonage MMS API
Security is paramount. Here are essential considerations:
Input Validation and Sanitization:
We added basic checks in server.js. For production, use a dedicated library like express-validator for more robust validation (e.g., checking phone number formats more strictly, validating URL structure, limiting caption length).
Sanitize inputs to prevent Cross-Site Scripting (XSS) if captions or other data are ever displayed in a web context.
// Example usage in server.js route// const { body, validationResult } = require('express-validator');//// app.post('/send-mms',// body('to').isMobilePhone('any', { strictMode: false }).withMessage('Invalid phone number format'),// body('imageUrl').isURL({ protocols: ['http', 'https'] }).withMessage('Invalid or non-HTTPS image URL'),// body('caption').optional().isLength({ max: 1000 }).escape(), // Escape for safety// async (req, res, next) => {// const errors = validationResult(req);// if (!errors.isEmpty()) {// return res.status(400).json({ success: false, errors: errors.array() });// }// // ... rest of the route logic ...// });
Protect API Credentials:
NEVER commit .env or private.key to Git (enforced by .gitignore).
In production environments, use secure methods for managing secrets (e.g., environment variables injected by the platform, AWS Secrets Manager, HashiCorp Vault). Do not deploy .env files to production servers.
Rate Limiting:
Protect your API endpoint from abuse by implementing rate limiting.
// Example usage in server.js (apply before routes)// 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',// });// app.use('/send-mms', limiter); // Apply specifically to the send endpoint
API Endpoint Authentication/Authorization:
The /send-mms endpoint itself is currently open. In a real application, protect it. Methods include:
API Keys: Require clients to send a secret API key in a header (e.g., X-API-Key). Validate this key in middleware.
JWT Tokens: If users log in to your application, issue JWTs and require them for API calls.
IP Whitelisting: Restrict access to specific IP addresses if applicable.
Webhook Security:
Vonage supports signing webhooks using either a shared secret or your application's private key (JWT). Validating these signatures ensures that incoming webhook requests genuinely originated from Vonage. Refer to the Vonage documentation on securing webhooks. Implementing signature validation is highly recommended for production.
Understanding MMS Limitations and Requirements
Understanding Vonage MMS limitations is critical for successful implementation:
US Number Requirement (Critical): Vonage MMS sending is only supported from US short codes, 10DLC numbers, or SMS-enabled toll-free numbers. Standard US long codes do not support MMS. MMS can be sent to US numbers on AT&T, T-Mobile (formerly Sprint), and Verizon networks. Sending to international numbers or from non-US/Canada numbers will not work. Source: Vonage MMS Documentation
10DLC Registration: If using a 10DLC number, ensure you have completed 10DLC registration including brand and campaign registration. Message throughput and deliverability vary by number type. For detailed guidance, see our 10DLC SMS registration guide.
Publicly Accessible Image URL: The imageUrl provided must resolve to a publicly accessible image file over HTTP or HTTPS. Vonage needs to fetch this image to send it. Local file paths or private URLs will not work.
Supported Image Formats: Vonage MMS supports .jpg, .jpeg, .png, and .gif formats. Verify the image URL resolves to one of these formats. Source: Vonage MMS Documentation
Image Size Limits: While Vonage documentation does not specify exact file size limits, carrier restrictions typically limit MMS messages to 300–600 KB total size. Test with images under 500 KB for best compatibility across carriers.
Trial Account Limitations: If using a free trial Vonage account, you can only send messages (SMS/MMS) to phone numbers that you have verified and added to your test numbers list in the dashboard. Attempting to send to other numbers will result in a "Non-Whitelisted Destination" error.
Character Encoding/Captions: Ensure captions use standard character sets (like UTF-8). Special characters might be handled differently by recipient carriers. Keep captions concise (recommended under 160 characters).
A2P Compliance: Ensure your use case complies with Application-to-Person messaging regulations and Vonage's acceptable use policies, especially regarding consent if sending marketing messages. US carriers enforce strict A2P compliance for 10DLC and short code messaging.
How to Optimize MMS Sending Performance
For this specific use case (sending individual MMS messages triggered by an API call), major performance bottlenecks are less likely within the Node.js application itself compared to external factors (Vonage API latency, carrier delivery). However:
Asynchronous Operations: Node.js and the Vonage SDK are inherently asynchronous. Ensure you don't block the event loop with synchronous code in your route handlers or services. Using async/await correctly helps manage this.
Resource Usage: Monitor CPU and memory usage under load. If the service handles high traffic, ensure efficient JSON parsing and minimize unnecessary computation per request.
Connection Pooling: If interacting with a database (Section 6), ensure your ORM or client uses connection pooling effectively.
Caching: Caching is generally not applicable for the sending action itself. However, if you frequently retrieve data before sending (e.g., user details, image URLs from a CMS), caching that retrieved data can improve the performance of the steps leading up to the sendMms call.
Load Testing: Use tools like k6, artillery, or ApacheBench (ab) to simulate traffic against your /send-mms endpoint and identify potential bottlenecks under load. Monitor Vonage API response times and error rates during tests.
Profiling: Use Node.js built-in profiler or tools like Clinic.js to analyze CPU usage and identify performance hotspots within your code if needed.
How to Monitor Your MMS Service in Production
To understand how your service behaves in production:
Health Checks: The /health endpoint provides a basic check. Monitoring systems (like Prometheus, Datadog, UptimeRobot) can periodically ping this endpoint to ensure the service is running.
Performance Metrics:
Track the latency of requests to the /send-mms endpoint.
Track the latency of calls to the Vonage API (sendMms function duration).
Monitor the rate of successful requests vs. error responses (HTTP 4xx/5xx).
Tools: Prometheus with prom-client, Datadog APM, New Relic.
Error Tracking:
Integrate an error tracking service (e.g., Sentry, Bugsnag, Datadog Error Tracking). These services capture unhandled exceptions and errors passed to the global error handler, group them, and provide detailed context (stack traces, request data).
// Example integration in server.js (early in the file)// const Sentry = require('@sentry/node');// const Tracing = require('@sentry/tracing'); // If using tracing//// Sentry.init({// dsn: "YOUR_SENTRY_DSN",// integrations: [// // enable HTTP calls tracing// new Sentry.Integrations.Http({ tracing: true }),// // enable Express.js middleware tracing// new Tracing.Integrations.Express({ app }),// ],// // Set tracesSampleRate to 1.0 to capture 100%// // of transactions for performance monitoring.// // Adjust in production!// tracesSampleRate: 1.0,// });//// // RequestHandler creates a separate execution context using domains, so that every// // transaction/span/breadcrumb is attached to its own Hub instance// app.use(Sentry.Handlers.requestHandler());// // TracingHandler creates a trace for every incoming request// app.use(Sentry.Handlers.tracingHandler());//// // ... Your routes BEFORE the error handler ...//// // The error handler must be before any other error middleware and after all controllers// app.use(Sentry.Handlers.errorHandler());//// // Optional fallthrough error handler// app.use(function onError(err, req, res, next) {// // The error id is attached to `res.sentry` to be returned// // and optionally displayed to the user for support.// res.statusCode = 500;// res.end(res.sentry + "\n");// });
Structured Logging:
Replace console.log/error with a structured logging library (Winston, Pino). Log events with consistent formats (JSON is common), including timestamps, severity levels, request IDs, and relevant context (e.g., message_uuid, recipient).
Send logs to a centralized logging platform (e.g., Datadog Logs, ELK Stack, Splunk, Grafana Loki) for searching, analysis, and alerting.
Vonage Dashboard & Analytics:
Regularly check the Vonage Messages API Dashboard for insights into delivery rates, error codes, and usage trends provided directly by Vonage. This complements your application-level monitoring.
By implementing these observability practices, you gain crucial visibility into your MMS sending service's health, performance, and potential issues.
Vonage Messages SDK (v3.x) provides the MMSImage class for structured payloads
Frequently asked questions
Use the Vonage Messages API with the official Node.js SDK (@vonage/messages) and Express.js to create an API endpoint that handles MMS sending. The API endpoint receives the recipient's number, image URL, and an optional caption, then uses the Vonage SDK to send the MMS via the Vonage Messages API. This allows you to integrate rich media messaging into your Node.js application.
The Vonage Messages API is a unified API for sending messages through various channels, including MMS, and it's used with the @vonage/messages SDK in Node.js for sending image and text based messages. It is chosen for its rich features and ease of integration with the Node.js ecosystem. This enables sending of MMS messages, notifications, alerts, and incorporating rich media content into your application workflows.
Express.js simplifies creating the necessary API endpoints for sending MMS messages. Its minimal and flexible structure makes setting up routes, handling requests, and managing middleware easy, providing a solid foundation for the MMS sending application. Express.js is well-suited for building APIs and web applications in Node.js.
Store credentials like API keys and secrets in a .env file. Use the dotenv package to load these variables into process.env. Never commit the .env file to version control. In production, employ more secure methods like environment variables injected by the platform, AWS Secrets Manager, or HashiCorp Vault.
You'll need Node.js, npm or yarn, a Vonage API account with an API key and secret, a Vonage application with an associated private.key file, a Vonage virtual US phone number enabled for MMS, ngrok for local development webhooks, and a target US phone number for testing.
Use ngrok during development to create a public URL that tunnels webhook requests from the Vonage Messages API to your local server. This allows you to receive status updates about your messages in your development environment without deploying your application publicly.
In your Vonage dashboard, navigate to 'Applications' and click 'Create a new application.' Generate public and private keys (store the private key securely). Enable the 'Messages' capability, setting Inbound and Status URLs to your application endpoints. Link your Vonage number capable of sending MMS to this application.
Vonage's MMS functionality is primarily designed for sending messages from US/Canada numbers to US numbers. While some international sending might be possible, there are limitations. Check Vonage's documentation for specific international capabilities from your number and potential restrictions.
The private.key file is used for authentication and authorization. It's part of the JWT (JSON Web Token) authentication process that the Vonage Messages API uses, alongside your Application ID. The Vonage Node.js SDK reads this file to securely sign API requests, ensuring only your application can send messages associated with your account.
Go to your Vonage Account Settings, then API Settings. Under 'Default SMS Setting,' select 'Messages API.' This setting is crucial for MMS and the Vonage Node.js messages SDK to function correctly.
Implement error handling with try-catch blocks around the Vonage SDK's send function. Use a global error handler in Express.js to log detailed error information, including stack traces. Consider using a dedicated logging library like Winston or Pino for improved logging in production. Use res.status(200).send('OK') in webhook endpoints to avoid Vonage retrying failed webhooks.
Set up separate folders for source code (src), configuration (config), and routes. Create a dedicated service module to encapsulate interactions with the Vonage Messages API, and manage configuration and credentials securely. Consider libraries like express-validator and retry mechanisms using async-retry for more robust code in production.
Run your Express server, use ngrok to create a public tunnel to your localhost, and update your Vonage application webhook URLs to use the ngrok address. Then, use tools like curl or Postman to send test MMS messages through your API endpoint, and inspect status updates delivered by Vonage to your local server through the ngrok tunnel.
With a Vonage trial account, you can only send SMS/MMS to verified numbers added to your 'test numbers' list in the dashboard. This is a security measure. Add your test recipient numbers to this whitelist to avoid 'Non-Whitelisted Destination' errors during testing.
Include fields for Vonage's message UUID, recipient and sender numbers, image URL, caption, message status, status timestamps, Vonage status codes, error descriptions, and timestamps for when messages were submitted and updated. This comprehensive data will help in tracking and managing sent messages.
Important Notice: This guide implements MMS sending using Node.js with Express framework, not Next.js with NextAuth. If you need Next.js implementation, refer to Next.js-specific Vonage guides.
This guide walks you through building a production-ready Node.js application to send MMS messages using the Vonage Messages API and Express framework. You'll learn how to configure the Vonage Node.js SDK for multimedia messaging, handle API credentials securely, build API endpoints to trigger MMS sending, and implement essential features like error handling and logging. By the end, you'll have a functional MMS service capable of sending images programmatically to US-based phone numbers.
MMS Availability (as of January 2025): MMS sending through Vonage Messages API is available with General Availability status. However, only US short codes, 10DLC numbers, and SMS-enabled toll-free numbers are currently supported. For US short codes, MMS messages can be sent to AT&T, T-Mobile (formerly Sprint), and Verizon networks in the US. Source: Vonage MMS Documentation
What You'll Build: MMS Sending Project Overview
What You're Building: A Node.js Express API with a single endpoint (
/send-mms). When this endpoint receives a POST request containing a recipient phone number, a publicly accessible image URL, and an optional caption, it uses the Vonage Messages API to send an MMS message.Problem Solved: This enables applications to programmatically send rich media content (images) via MMS – useful for notifications, alerts, marketing campaigns, or integrating media sharing into workflows.
Technologies Used:
@vonage/messagesSDK: The official Vonage Node.js SDK (v3.x) specifically for interacting with the Messages API. As of January 2025, MMS support has General Availability status. Source: npm @vonage/messagesdotenv: A module to load environment variables from a.envfile intoprocess.env. Chosen for easy management of configuration and secrets during development.ngrokis used as a development utility to expose the local server for receiving webhook status updates.System Architecture:
An API client (like curl, Postman, or another application) sends a POST request to the
/send-mmsendpoint of the Node.js/Express API. The Express API uses the@vonage/messagesSDK to call thesendmethod with an MMS image message object. The SDK sends an MMS request to the Vonage Messages API. Vonage delivers the MMS to the recipient's phone. Vonage also sends status updates (webhooks) about the message delivery. During development, these webhooks are sent to anngroktunnel, which forwards them to the/webhooks/statusendpoint on the local Express API server.Prerequisites for Sending MMS with Vonage
Before you begin, ensure you have:
private.keyfile (created in Section 4).ngrokinstalled and authenticated (a free account is sufficient). Download ngrok. Used for receiving webhook status updates during development.How to Set Up Your Node.js MMS Project
Initialize your Node.js project and install the necessary dependencies.
Create Project Directory: Open your terminal and create a new directory for the project, then navigate into it.
mkdir vonage-mms-sender cd vonage-mms-senderInitialize Node.js Project: Create a
package.jsonfile.Install Dependencies: Install Express for the server, the Vonage Messages SDK, and
dotenvfor environment variables.Set Up Project Structure: Create directories for source code and configuration.
mkdir src configCreate Environment File (
.env): Create a file named.envin the project root. This file stores sensitive credentials and configuration. Never commit this file to version control.VONAGE_API_KEY,VONAGE_API_SECRET: Found directly on your Vonage dashboard. Required for basic SDK authentication.VONAGE_APPLICATION_ID,VONAGE_PRIVATE_KEY_PATH: Obtained when creating a Vonage Application (covered in Section 4). Used for authenticating requests specifically for the Messages API.VONAGE_FROM_NUMBER: Your purchased Vonage US number capable of sending MMS. Enter it without+or spaces.PORT: The port your Express server listens on.NGROK_BASE_URL: The public URL provided by ngrok, used for receiving status webhooks during development.Create Git Ignore File (
.gitignore): Create a file named.gitignorein the project root to prevent committing sensitive files and generated folders.Configuration Loading: Create a file
config/index.jsto load and export environment variables.// config/index.js require('dotenv').config(); // Load variables from .env into process.env const config = { vonage: { apiKey: process.env.VONAGE_API_KEY, apiSecret: process.env.VONAGE_API_SECRET, applicationId: process.env.VONAGE_APPLICATION_ID, privateKeyPath: process.env.VONAGE_PRIVATE_KEY_PATH, fromNumber: process.env.VONAGE_FROM_NUMBER, }, server: { port: process.env.PORT || 3000, }, ngrokBaseUrl: process.env.NGROK_BASE_URL, // Used later for webhook setup if needed }; // Basic validation if (!config.vonage.apiKey || !config.vonage.apiSecret || !config.vonage.applicationId || !config.vonage.privateKeyPath || !config.vonage.fromNumber) { console.error('Missing required Vonage credentials in .env file'); process.exit(1); // Exit if critical config is missing } module.exports = config;How to Implement the Vonage MMS Service
Create a dedicated service file to handle interactions with the Vonage Messages API. This promotes separation of concerns.
Create Service File: Create
src/services/vonageService.js.Implement MMS Sending Logic: Add the following code to initialize the Vonage SDK and define the function to send MMS.
// src/services/vonageService.js const { Messages, MMSImage } = require('@vonage/messages'); const config = require('../../config'); // Load our configuration // Initialize the Vonage Messages client // The Messages API uses Application ID + Private Key for JWT authentication, // alongside the standard API Key + Secret. const vonageMessages = new Messages({ apiKey: config.vonage.apiKey, apiSecret: config.vonage.apiSecret, applicationId: config.vonage.applicationId, privateKey: config.vonage.privateKeyPath, // SDK reads the file path }); /** * Sends an MMS message using the Vonage Messages API. * @param {string} to - The recipient phone number (E.164 format, e.g., 14155550101). * @param {string} imageUrl - The publicly accessible URL of the image to send. * @param {string} [caption=''] - Optional caption for the image. * @returns {Promise<object>} - A promise that resolves with the Vonage API response. * @throws {Error} - Throws an error if the message sending fails. */ const sendMms = async (to, imageUrl, caption = '') => { console.log(`Attempting to send MMS to ${to} from ${config.vonage.fromNumber}`); // Validate image URL (basic check) if (!imageUrl || !imageUrl.startsWith('http')) { throw new Error('Invalid or missing image URL. Must be a public HTTP/HTTPS URL.'); } // Validate image format const supportedFormats = ['.jpg', '.jpeg', '.png', '.gif']; const urlLower = imageUrl.toLowerCase(); const isSupported = supportedFormats.some(format => urlLower.includes(format)); if (!isSupported) { console.warn(`Image URL may not be a supported format. Vonage MMS supports: ${supportedFormats.join(', ')}`); } // Construct the MMS message payload using the MMSImage class const messagePayload = new MMSImage({ to: to, from: config.vonage.fromNumber, // Your Vonage MMS-capable number image: { url: imageUrl, caption: caption, // Optional caption }, channel: 'mms', // Specify the channel as MMS message_type: 'image', // Specify message type }); try { // Send the message using the SDK const response = await vonageMessages.send(messagePayload); console.log(`MMS submitted successfully to Vonage. Message UUID: ${response.message_uuid}`); return response; // Contains message_uuid } catch (error) { console.error(`Error sending MMS via Vonage: ${error.message}`); // Log more details for debugging if available if (error.response && error.response.data) { console.error('Vonage API Error Details:', JSON.stringify(error.response.data, null, 2)); } // Re-throw a structured error or handle appropriately throw new Error(`Failed to send MMS: ${error.message || 'Unknown Vonage API error'}`); } }; module.exports = { sendMms, };Why this approach?
@vonage/messagesSDK: This specific SDK package is designed for the Vonage Messages API, which handles MMS with General Availability status as of January 2025. Older SDKs or different methods might target the legacy SMS API.MMSImageClass: The SDK provides convenient classes likeMMSImageto structure the payload correctly for different message types, reducing errors..jpg,.jpeg,.png, and.gifformats. Source: Vonage MMS Documentationasync/awaitmakes asynchronous code cleaner and easier to read compared to raw promises or callbacks.try...catchblock ensures that errors from the Vonage API are caught, logged, and potentially transformed before being propagated, allowing the calling code (your API endpoint) to handle them gracefully.How to Build the Express API Endpoint for MMS
Create the Express server and the
/send-mmsendpoint.Create Server File: Create
src/server.js.Implement Express Server and Endpoint:
// src/server.js const express = require('express'); const config = require('../config'); // Load configuration const { sendMms } = require('./services/vonageService'); // Import our service function const app = express(); // --- Middleware --- // Parse JSON request bodies app.use(express.json()); // Parse URL-encoded request bodies app.use(express.urlencoded({ extended: true })); // Simple request logger middleware (optional but helpful) app.use((req, res, next) => { console.log(`[${new Date().toISOString()}] ${req.method} ${req.url}`); next(); }); // --- Routes --- // Health check endpoint app.get('/health', (req, res) => { res.status(200).json({ status: 'OK', timestamp: new Date().toISOString() }); }); // Endpoint to send MMS app.post('/send-mms', async (req, res, next) => { // Basic Input Validation (Consider using a library like express-validator for production) const { to, imageUrl, caption } = req.body; if (!to || !imageUrl) { return res.status(400).json({ success: false, message: 'Missing required fields: `to` and `imageUrl` are required.', }); } // Simple validation for phone number format (basic example) if (!/^\d{10,15}$/.test(to.replace(/^\+/, ''))) { return res.status(400).json({ success: false, message: 'Invalid `to` phone number format. Use E.164 or digits only (10–15 digits).', }); } try { // Call the Vonage service function const result = await sendMms(to, imageUrl, caption); // Send success response res.status(202).json({ // 202 Accepted: Request received, processing initiated success: true, message: 'MMS submission accepted by Vonage.', data: result, // Contains message_uuid }); } catch (error) { // Pass error to the error handling middleware next(error); } }); // --- Webhook Endpoint (for status updates) --- // Vonage sends status updates here (POST or GET depending on config) app.all('/webhooks/status', (req, res) => { console.log('Webhook received (Status):'); console.log('Headers:', JSON.stringify(req.headers, null, 2)); console.log('Body:', JSON.stringify(req.body, null, 2)); // Body format depends on Vonage settings console.log('Query Params:', JSON.stringify(req.query, null, 2)); // IMPORTANT: Always respond with 200 OK to Vonage webhooks // Otherwise, Vonage will retry, potentially causing duplicate processing. res.status(200).send('OK'); }); // --- Global Error Handler --- // This middleware catches errors passed via next(error) app.use((err, req, res, next) => { console.error('Global Error Handler Caught:', err.stack || err); // Determine status code – default to 500 const statusCode = err.statusCode || 500; res.status(statusCode).json({ success: false, message: err.message || 'An internal server error occurred.', // Optionally include stack trace in development ...(process.env.NODE_ENV === 'development' && { stack: err.stack }), }); }); // --- Start Server --- const PORT = config.server.port; app.listen(PORT, () => { console.log(`Server listening on http://localhost:${PORT}`); console.log(`Health check available at http://localhost:${PORT}/health`); if (config.ngrokBaseUrl) { console.log(`Status Webhook expected at: ${config.ngrokBaseUrl}/webhooks/status`); } else { console.warn("NGROK_BASE_URL not set in .env – Status webhooks won't be received locally without ngrok."); } });Add Start Script to
package.json: Modify thescriptssection in yourpackage.json:// package.json { // ... other properties "scripts": { "start": "node src/server.js", "dev": "nodemon src/server.js" // Optional: if you install nodemon (`npm install --save-dev nodemon`) }, // ... other properties }How to Configure Vonage Dashboard for MMS Sending
Before running the code, configure your Vonage account and application correctly.
Get API Key and Secret:
API keyandAPI secretare displayed at the top.VONAGE_API_KEYandVONAGE_API_SECRETfields in your.envfile.Set Default SMS API to
Messages API:Messages APIis selected. This is crucial for MMS and the@vonage/messagesSDK to work correctly.Create a Vonage Application:
private.keyfile to your computer and populates the public key field.private.keyfile into the root directory of your Node.js project (the same level as your.envfile). Ensure theVONAGE_PRIVATE_KEY_PATHin your.envfile points to it (e.g.,./private.key).http://localhost:3000/webhooks/status. Update this after starting ngrok. Set the HTTP method toPOST.http://localhost:3000/webhooks/inbound. Set the HTTP method toPOST.VONAGE_APPLICATION_IDfield in your.envfile.Link Your Vonage Number:
VONAGE_FROM_NUMBERin your.envfile matches this linked number (use E.164 format without+, e.g.,14155550100).Set up ngrok (for Status Webhooks during Development):
Open a new terminal window (keep your Node.js app terminal separate).
Run ngrok to expose the port your Express app listens on (defined in
.env, default 3000).ngrok displays output including a
ForwardingURL (e.g.,https://random-subdomain.ngrok-free.app). Copy this HTTPS URL.Paste this base URL into the
NGROK_BASE_URLfield in your.envfile.Go back to your application settings in the Vonage Dashboard.
Edit the Status URL under the "Messages" capability. Set it to your ngrok Forwarding URL followed by the webhook path defined in
server.js:YOUR_NGROK_URL/webhooks/status(e.g.,https://random-subdomain.ngrok-free.app/webhooks/status). Ensure the method isPOST.Update the Inbound URL similarly:
YOUR_NGROK_URL/webhooks/inbound.Click "Save changes".
How to Handle Errors and Implement Retry Logic
Your current setup includes basic error handling:
Service Level (
vonageService.js): Catches errors during thevonageMessages.sendcall, logs details, and throws a new error.API Level (
server.js):try...catchin the route handler to catch errors from the service.next(error).Logging: Uses
console.logandconsole.error. For production, consider structured logging libraries like Winston or Pino for better log management and analysis.# Example: Add Winston (Optional) npm install winstonYou would then configure Winston (e.g., log to files, different levels) and replace
console.log/errorcalls.Retry Mechanisms:
200 OKresponse quickly. This is whyres.status(200).send('OK');in the/webhooks/statusendpoint is crucial.sendMmscall (e.g., temporary network issue to Vonage, intermittent Vonage API errors), you might implement application-level retries. Libraries likeasync-retrycan help implement strategies like exponential backoff. However, be cautious about retrying errors that are clearly permanent (e.g., invalid credentials, invalid recipient number).// Conceptual example using async-retry (Install: npm install async-retry) // In vonageService.js // const retry = require('async-retry'); // // const sendMmsWithRetry = async (to, imageUrl, caption = '') => { // await retry(async bail => { // // If Vonage returns specific errors indicating non-transient failure, use bail() // // Example: if (error.response && error.response.data.code === 'INVALID_CREDENTIALS') { // // bail(new Error('Non-retryable error: Invalid Credentials')); // // return; // // } // await sendMms(to, imageUrl, caption); // Call original function // }, { // retries: 3, // Number of retries // factor: 2, // Exponential backoff factor // minTimeout: 1000, // Initial timeout // onRetry: (error, attempt) => console.warn(`Retry attempt ${attempt} failed: ${error.message}`), // }); // };How to Track MMS Delivery Status with Webhooks
While this guide focuses solely on sending MMS, a production application often needs to track the status of sent messages. This typically involves a database.
Conceptual Schema: You might have a
messagestable:CREATE TABLE messages ( id SERIAL PRIMARY KEY, -- Or UUID vonage_message_uuid VARCHAR(255) UNIQUE, -- UUID returned by Vonage recipient_number VARCHAR(20) NOT NULL, sender_number VARCHAR(20) NOT NULL, image_url TEXT, caption TEXT, status VARCHAR(50) DEFAULT 'submitted', -- e.g., submitted, delivered, failed, unknown status_timestamp TIMESTAMPTZ, vonage_status_code VARCHAR(10), -- Code received in status webhook error_description TEXT, -- Error details from webhook submitted_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP );Data Layer:
pgfor PostgreSQL) to interact with this table.sendMmsand getting themessage_uuid, insert a new record into themessagestable withstatus = 'submitted'./webhooks/statusendpoint receives an update from Vonage containing amessage_uuid, find the corresponding record in themessagestable and update itsstatus,status_timestamp,vonage_status_code, and potentiallyerror_descriptionbased on the webhook data.Implementing this is beyond the scope of this specific guide but is a critical next step for robust tracking. For more details on handling webhook callbacks, see our guide on delivery status callbacks.
How to Secure Your Vonage MMS API
Security is paramount. Here are essential considerations:
Input Validation and Sanitization:
server.js. For production, use a dedicated library likeexpress-validatorfor more robust validation (e.g., checking phone number formats more strictly, validating URL structure, limiting caption length).# Example: Add express-validator (Optional) npm install express-validator// Example usage in server.js route // const { body, validationResult } = require('express-validator'); // // app.post('/send-mms', // body('to').isMobilePhone('any', { strictMode: false }).withMessage('Invalid phone number format'), // body('imageUrl').isURL({ protocols: ['http', 'https'] }).withMessage('Invalid or non-HTTPS image URL'), // body('caption').optional().isLength({ max: 1000 }).escape(), // Escape for safety // async (req, res, next) => { // const errors = validationResult(req); // if (!errors.isEmpty()) { // return res.status(400).json({ success: false, errors: errors.array() }); // } // // ... rest of the route logic ... // });Protect API Credentials:
.envorprivate.keyto Git (enforced by.gitignore)..envfiles to production servers.Rate Limiting:
# Example: Add express-rate-limit (Optional) npm install express-rate-limit// Example usage in server.js (apply before routes) // 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', // }); // app.use('/send-mms', limiter); // Apply specifically to the send endpointAPI Endpoint Authentication/Authorization:
/send-mmsendpoint itself is currently open. In a real application, protect it. Methods include:X-API-Key). Validate this key in middleware.Webhook Security:
Understanding MMS Limitations and Requirements
Understanding Vonage MMS limitations is critical for successful implementation:
imageUrlprovided must resolve to a publicly accessible image file over HTTP or HTTPS. Vonage needs to fetch this image to send it. Local file paths or private URLs will not work..jpg,.jpeg,.png, and.gifformats. Verify the image URL resolves to one of these formats. Source: Vonage MMS DocumentationHow to Optimize MMS Sending Performance
For this specific use case (sending individual MMS messages triggered by an API call), major performance bottlenecks are less likely within the Node.js application itself compared to external factors (Vonage API latency, carrier delivery). However:
async/awaitcorrectly helps manage this.sendMmscall.k6,artillery, or ApacheBench (ab) to simulate traffic against your/send-mmsendpoint and identify potential bottlenecks under load. Monitor Vonage API response times and error rates during tests.How to Monitor Your MMS Service in Production
To understand how your service behaves in production:
Health Checks: The
/healthendpoint provides a basic check. Monitoring systems (like Prometheus, Datadog, UptimeRobot) can periodically ping this endpoint to ensure the service is running.Performance Metrics:
/send-mmsendpoint.sendMmsfunction duration).prom-client, Datadog APM, New Relic.Error Tracking:
# Example: Add Sentry (Optional) npm install @sentry/node @sentry/tracing// Example integration in server.js (early in the file) // const Sentry = require('@sentry/node'); // const Tracing = require('@sentry/tracing'); // If using tracing // // Sentry.init({ // dsn: "YOUR_SENTRY_DSN", // integrations: [ // // enable HTTP calls tracing // new Sentry.Integrations.Http({ tracing: true }), // // enable Express.js middleware tracing // new Tracing.Integrations.Express({ app }), // ], // // Set tracesSampleRate to 1.0 to capture 100% // // of transactions for performance monitoring. // // Adjust in production! // tracesSampleRate: 1.0, // }); // // // RequestHandler creates a separate execution context using domains, so that every // // transaction/span/breadcrumb is attached to its own Hub instance // app.use(Sentry.Handlers.requestHandler()); // // TracingHandler creates a trace for every incoming request // app.use(Sentry.Handlers.tracingHandler()); // // // ... Your routes BEFORE the error handler ... // // // The error handler must be before any other error middleware and after all controllers // app.use(Sentry.Handlers.errorHandler()); // // // Optional fallthrough error handler // app.use(function onError(err, req, res, next) { // // The error id is attached to `res.sentry` to be returned // // and optionally displayed to the user for support. // res.statusCode = 500; // res.end(res.sentry + "\n"); // });Structured Logging:
console.log/errorwith a structured logging library (Winston, Pino). Log events with consistent formats (JSON is common), including timestamps, severity levels, request IDs, and relevant context (e.g.,message_uuid,recipient).Vonage Dashboard & Analytics:
By implementing these observability practices, you gain crucial visibility into your MMS sending service's health, performance, and potential issues.
Related Messaging Guides and Resources
Expand your Vonage messaging capabilities:
Vonage MMS Implementation Summary
This guide covered how to send MMS messages using the Vonage Messages API with Node.js and Express. You learned to:
Key Takeaways:
.jpg,.jpeg,.png,.gif(recommended under 500 KB)MMSImageclass for structured payloads