code examples
code examples
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.
Send MMS with Vonage Messages API: Node.js Express Guide with Multimedia Messaging
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/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.- Note:
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-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 API account. Sign up for free.
- Your Vonage API Key and API Secret (found on the Vonage API Dashboard).
- A Vonage Application ID and associated
private.keyfile (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
ngrokinstalled 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.
bashmkdir vonage-mms-sender cd vonage-mms-sender -
Initialize Node.js Project: Create a
package.jsonfile.bashnpm init -y -
Install Dependencies: Install Express for the server, the Vonage Messages SDK, and
dotenvfor environment variables.bashnpm install express @vonage/messages dotenv -
Set Up Project Structure: Create directories for source code and configuration.
bashmkdir src config -
Create 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.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.gitignorein the project root to prevent committing sensitive files and generated folders.text# .gitignore node_modules .env private.key npm-debug.log -
Configuration Loading: Create a file
config/index.jsto load and export environment variables.javascript// 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.
javascript// 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.- 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.gifformats. Source: Vonage MMS Documentation - Async/Await: Using
async/awaitmakes asynchronous code cleaner and easier to read compared to raw promises or callbacks. - Error Handling: The
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-mms endpoint.
-
Create Server File: Create
src/server.js. -
Implement Express Server and Endpoint:
javascript// 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: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:
- Navigate to your Vonage API Dashboard.
- Your
API keyandAPI secretare displayed at the top. - Copy these values into the
VONAGE_API_KEYandVONAGE_API_SECRETfields in your.envfile.
-
Set Default SMS API to
Messages API:- Go to Account Settings.
- Scroll down to "API settings".
- Under "Default SMS Setting", ensure
Messages APIis selected. This is crucial for MMS and the@vonage/messagesSDK to work correctly. - Click "Save changes".
-
Create a Vonage Application:
- Navigate to Applications in the dashboard.
- Click "Create a new application".
- Enter an Application name (e.g., "Node MMS Sender").
- Click "Generate public and private key". This automatically downloads a
private.keyfile to your computer and populates the public key field. - IMPORTANT: Move the downloaded
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). - 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 toPOST. - 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 toPOST.
- 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
- Click "Create application".
- You'll be redirected to the application's page. Copy the Application ID displayed.
- Paste this ID into the
VONAGE_APPLICATION_IDfield in your.envfile.
-
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_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).bashngrok http 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):- Uses
try...catchin 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.
- Uses
-
Logging: Uses
console.logandconsole.error. For production, consider structured logging libraries like Winston or Pino for better log management and analysis.bash# 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:
- Vonage Retries: Vonage automatically retries sending webhooks (like the status update) to your specified URL if it doesn't receive a
200 OKresponse quickly. This is whyres.status(200).send('OK');in the/webhooks/statusendpoint is crucial. - Application Retries: For failures in the initial
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).
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}`), // }); // }; - Vonage Retries: Vonage automatically retries sending webhooks (like the status update) to your specified URL if it doesn't receive a
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:sqlCREATE 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:
- Use an ORM (like Prisma, Sequelize, TypeORM) or a database client (like
pgfor PostgreSQL) to interact with this table. - On Send: After successfully calling
sendMmsand getting themessage_uuid, insert a new record into themessagestable withstatus = 'submitted'. - On Status Webhook: When the
/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.
- Use an ORM (like Prisma, Sequelize, TypeORM) or a database client (like
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 likeexpress-validatorfor 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.
bash# Example: Add express-validator (Optional) npm install express-validatorjavascript// 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 ... // }); - We added basic checks in
-
Protect API Credentials:
- NEVER commit
.envorprivate.keyto 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
.envfiles to production servers.
- NEVER commit
-
Rate Limiting:
- Protect your API endpoint from abuse by implementing rate limiting.
bash# Example: Add express-rate-limit (Optional) npm install express-rate-limitjavascript// 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-mmsendpoint 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.
- API Keys: Require clients to send a secret API key in a header (e.g.,
- The
-
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
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. - Supported Image Formats: Vonage MMS supports
.jpg,.jpeg,.png, and.gifformats. 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/awaitcorrectly 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
sendMmscall. - Load Testing: Use tools like
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. - 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
/healthendpoint 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-mmsendpoint. - Track the latency of calls to the Vonage API (
sendMmsfunction duration). - Monitor the rate of successful requests vs. error responses (HTTP 4xx/5xx).
- Tools: Prometheus with
prom-client, Datadog APM, New Relic.
- Track the latency of requests to the
-
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).
bash# Example: Add Sentry (Optional) npm install @sentry/node @sentry/tracingjavascript// 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/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). - Send logs to a centralized logging platform (e.g., Datadog Logs, ELK Stack, Splunk, Grafana Loki) for searching, analysis, and alerting.
- Replace
-
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.
Related Messaging Guides and Resources
Expand your Vonage messaging capabilities:
- SMS API Integration – Learn how to send standard SMS messages alongside MMS
- Two-Way Messaging – Implement inbound message handling for interactive conversations
- Delivery Status Callbacks – Track message delivery and handle webhook events
- WhatsApp Integration – Extend to WhatsApp messaging for additional channels
- 10DLC Registration Guide – Complete guide to registering your 10DLC numbers for compliance
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:
- Set up the Vonage Messages SDK with proper authentication (API Key, Secret, Application ID, and private key)
- Build a production-ready Express API with MMS sending capabilities
- Handle critical MMS limitations including US number requirements (short codes, 10DLC, toll-free only)
- Implement security features including credential management, input validation, and webhook verification
- Configure webhooks for delivery status tracking using ngrok during development
- Optimize performance and implement monitoring for production deployments
Key Takeaways:
- MMS support has General Availability status as of January 2025
- Only US short codes, 10DLC numbers, and SMS-enabled toll-free numbers support MMS
- Supported image formats:
.jpg,.jpeg,.png,.gif(recommended under 500 KB) - 10DLC registration required for 10DLC numbers
- Vonage Messages SDK (v3.x) provides the
MMSImageclass for structured payloads
Frequently Asked Questions
How to send MMS messages with Node.js?
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.
What is Vonage Messages API used for in Node.js?
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.
Why is Express.js used in the Node.js Vonage MMS setup?
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.
How can I handle Vonage API credentials securely in my Node.js project?
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.
What are the prerequisites for setting up Vonage MMS sending in Node.js?
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.
When should I use ngrok with the Vonage Messages API?
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.
How to create a Vonage application for MMS messaging?
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.
Can I send MMS messages to international numbers using Vonage from my Node.js app?
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.
What is the purpose of the private.key file in the Vonage MMS setup?
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.
How do I set the default SMS API to Messages API in the Vonage dashboard?
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.
How to handle errors when sending MMS messages with the Vonage API?
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.
How do I structure my project to send MMS messages with Node.js and Vonage?
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.
How can I test my Vonage MMS Node.js application locally?
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.
Why do I need to whitelist numbers for testing MMS with a Vonage trial account?
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.
What information should I include in a database schema for tracking sent MMS messages?
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.