This guide provides a step-by-step walkthrough for building a Node.js application using the Express framework to send Multimedia Messaging Service (MMS) messages via the Vonage Messages API. We'll cover project setup, core implementation, API creation, Vonage integration, error handling, security considerations, troubleshooting, and testing.
By the end of this guide, you will have a functional Express API endpoint capable of accepting requests and sending MMS messages containing images to specified phone numbers within the United States.
Project Overview and Goals
Goal: To create a simple, robust Node.js backend service that exposes an API endpoint to send MMS messages using the Vonage Messages API.
Problem Solved: Enables applications to programmatically send rich media content (images) via MMS, enhancing user engagement compared to standard SMS. This is particularly useful for notifications, alerts, marketing campaigns, or interactive applications requiring visual content.
Technologies Used:
- Node.js: A JavaScript runtime environment for building server-side applications. Chosen for its event-driven architecture, large ecosystem (npm), and suitability for I/O-bound tasks like API interactions.
- Express: A minimal and flexible Node.js web application framework. Chosen for its simplicity in setting up routes, middleware, and handling HTTP requests/responses.
- Vonage Messages API: A unified API for sending messages across various channels, including SMS and MMS. Chosen for its specific MMS capabilities for US numbers and comprehensive developer support.
- dotenv: A module to load environment variables from a
.env
file intoprocess.env
. Chosen for securely managing sensitive credentials outside the codebase.
System Architecture:
+-------------+ +------------------------+ +----------------+ +-----------------+
| Client | -----> | Node.js/Express API | -----> | Vonage Messages| -----> | Recipient Phone |
| (e.g., Web, | | (This Application) | | API | | (US Number) |
| Mobile App) | | - POST /send-mms | +----------------+ +-----------------+
| | | - Uses Vonage SDK |
+-------------+ +------------------------+
|
| Uses Credentials from .env
| (API Key/Secret, App ID, Private Key)
|
V
+------------------------+
| Vonage Application |
| (Dashboard Config) |
| - Linked Number |
| - Webhook URLs |
+------------------------+
Prerequisites:
- Node.js and npm (or yarn): Installed on your development machine. Download from nodejs.org.
- Vonage API Account: Sign up at Vonage API Dashboard. You'll receive free credit for testing.
- Vonage Phone Number: A US-based Vonage virtual number capable of sending SMS and MMS. Purchase one via the Vonage Dashboard (Numbers > Buy Numbers). Note: MMS sending is generally restricted to US numbers and Application-to-Person (A2P) use cases.
- Publicly Accessible Image URL: The image you want to send must be hosted online and accessible via a public URL (e.g., on a CDN, public cloud storage bucket, or image hosting service). Supported formats include
.jpg
,.jpeg
, and.png
. - (Recommended for Local Development involving Dashboard Setup) ngrok: A tool to expose your local development server to the internet. While not strictly needed if you only send messages and don't process webhooks, it's practically required for the initial Vonage Application setup in the dashboard (Section 4), which mandates webhook URLs. Download from ngrok.com.
1. Setting up the Project
Let's initialize our Node.js project and install the necessary dependencies.
-
Create Project Directory: Open your terminal or command prompt and create a new directory for your project. Navigate into it.
mkdir vonage-mms-sender cd vonage-mms-sender
-
Initialize Node.js Project: This creates a
package.json
file to manage project dependencies and scripts. The-y
flag accepts default settings.npm init -y
-
Install Dependencies:
@vonage/server-sdk
: The official Vonage SDK for Node.js, which includes the Messages API client.express
: The web framework for building our API.dotenv
: To load environment variables from a.env
file.
npm install @vonage/server-sdk express dotenv
-
Create Project Files: Create the main application file and a file for environment variables.
# For Linux/macOS touch index.js .env .gitignore # For Windows (Command Prompt) type nul > index.js type nul > .env type nul > .gitignore # For Windows (PowerShell) New-Item index.js -ItemType File New-Item .env -ItemType File New-Item .gitignore -ItemType File
-
Configure
.gitignore
: Addnode_modules
and.env
to your.gitignore
file. This prevents committing dependencies and sensitive credentials to version control.# .gitignore node_modules/ .env *.log private.key # If stored directly in the project (see security note)
- Security Note: Storing the
private.key
file directly in the project root is done here for simplicity during initial local testing only. This is not secure and must not be done in production. Secure handling methods for production environments are discussed in Section 7 (Security Features) and Section 12 (Deployment and CI/CD).
- Security Note: Storing the
-
Project Structure: Your initial project structure should look like this:
vonage-mms-sender/ ├── node_modules/ ├── .env ├── .gitignore ├── index.js ├── package-lock.json └── package.json
2. Implementing Core Functionality (MMS Sending Service)
We'll encapsulate the MMS sending logic within a dedicated function for reusability and clarity.
-
Modify
index.js
: Openindex.js
and start by importing necessary modules and setting up the Vonage client configuration.// index.js require('dotenv').config(); // Load environment variables from .env file const express = require('express'); const { Vonage } = require('@vonage/server-sdk'); const { Messages } = require('@vonage/messages'); // Import Messages capability // Basic validation for essential environment variables const requiredEnv = [ 'VONAGE_API_KEY', 'VONAGE_API_SECRET', 'VONAGE_APPLICATION_ID', 'VONAGE_PRIVATE_KEY_PATH', 'VONAGE_SENDER_NUMBER' ]; for (const variable of requiredEnv) { if (!process.env[variable]) { console.error(`Error: Environment variable ${variable} is not set.`); process.exit(1); // Exit if essential config is missing } } // Initialize Vonage Client using Application ID and Private Key for Messages API v1 // This authentication method is required for MMS via Messages API v1. const vonage = new Vonage({ apiKey: process.env.VONAGE_API_KEY, // Optional for Messages API v1, but good practice apiSecret: process.env.VONAGE_API_SECRET, // Optional for Messages API v1, but good practice applicationId: process.env.VONAGE_APPLICATION_ID, privateKey: process.env.VONAGE_PRIVATE_KEY_PATH }); // Create a specific client instance for the Messages API const messagesClient = new Messages(vonage.credentials); // --- MMS Sending Function --- async function sendMmsMessage(recipientNumber, imageUrl, caption = '') { console.log(`Attempting to send MMS to: ${recipientNumber} with image: ${imageUrl}`); try { const response = await messagesClient.send({ message_type: ""image"", // Specify message type as image for MMS to: recipientNumber, // E.164 format recommended (e.g., 14155550100) from: process.env.VONAGE_SENDER_NUMBER, // Your Vonage US number channel: ""mms"", // Specify channel as MMS image: { // Image object url: imageUrl, // Publicly accessible URL of the image caption: caption // Optional caption text } }); console.log('MMS Sent Successfully:', response); // Expected successful response format: { message_uuid: '...' } return { success: true, message_uuid: response.message_uuid }; } catch (error) { console.error('Error sending MMS:', error?.response?.data || error.message || error); // Log the detailed error from Vonage if available let errorMessage = 'Failed to send MMS.'; if (error?.response?.data?.title) { errorMessage = `${error.response.data.title}: ${error.response.data.detail || ''}`; } else if (error.message) { errorMessage = error.message; } return { success: false, error: errorMessage }; } } // --- (API Layer will be added below) ---
-
Explanation:
require('dotenv').config()
: Loads variables from the.env
file.- Imports
express
,Vonage
(main SDK), andMessages
(specific capability). - Environment Variable Validation: A simple loop checks if critical environment variables are set, exiting gracefully if not. This prevents runtime errors due to missing configuration.
- Vonage Client Initialization: We initialize the main
Vonage
client. For the Messages API v1 (required for MMS currently), authentication must use theapplicationId
andprivateKey
. WhileapiKey
andapiSecret
aren't strictly needed for Messages API v1 auth, including them doesn't hurt and might be useful if using other Vonage APIs. Messages
Client: We create a dedicatedmessagesClient
instance using the credentials from the mainvonage
object. This client is specifically designed for the Messages API.sendMmsMessage
Function:- Takes the
recipientNumber
,imageUrl
, and an optionalcaption
as input. - Uses
async/await
for cleaner handling of the promise returned bymessagesClient.send
. - Calls
messagesClient.send
with a specific payload structure for MMS:message_type
: Must be""image""
.to
: The recipient's phone number (ideally E.164 format).from
: Your Vonage US number linked to the application.channel
: Must be""mms""
.image
: An object containing theurl
(required) and optionalcaption
.
- Includes
try...catch
for robust error handling. It logs success or detailed errors (accessing nested properties likeerror?.response?.data
for specific Vonage API error details). - Returns an object indicating
success
(true/false) and either themessage_uuid
or anerror
message.
- Takes the
3. Building a Complete API Layer
Now, let's use Express to create an HTTP endpoint that utilizes our sendMmsMessage
function.
-
Add Express Setup and Route to
index.js
: Append the following code to yourindex.js
file, below thesendMmsMessage
function definition.// index.js (continued) // --- Express API Setup --- const app = express(); const PORT = process.env.PORT || 3000; // Use port from .env or default to 3000 // Middleware to parse JSON request bodies app.use(express.json()); // Middleware to parse URL-encoded request bodies app.use(express.urlencoded({ extended: true })); // --- API Endpoint to Send MMS --- app.post('/send-mms', async (req, res) => { const { recipient, imageUrl, caption } = req.body; // Basic Input Validation if (!recipient || !imageUrl) { console.warn('Validation Error: Missing recipient or imageUrl in request body.'); return res.status(400).json({ success: false, error: 'Missing required fields: recipient and imageUrl are required.' }); } // Validate Image URL format (simple check) if (!imageUrl.startsWith('http://') && !imageUrl.startsWith('https://')) { console.warn(`Validation Error: Invalid image URL format: ${imageUrl}`); return res.status(400).json({ success: false, error: 'Invalid image URL format. URL must start with http:// or https://' }); } // Basic Phone Number Format Check (adjust regex as needed for stricter validation) // This regex checks for optional '+' and digits. More robust validation might be needed. const phoneRegex = /^\+?[1-9]\d{1,14}$/; // Basic E.164-like format check (+optional, digits). Not exhaustive. if (!phoneRegex.test(recipient)) { console.warn(`Validation Error: Invalid recipient phone number format: ${recipient}`); return res.status(400).json({ success: false, error: 'Invalid recipient phone number format. Use E.164 format (e.g., +14155550100).' }); } console.log(`Received request to send MMS to ${recipient}`); const result = await sendMmsMessage(recipient, imageUrl, caption); if (result.success) { console.log(`MMS successfully initiated for ${recipient}. Message UUID: ${result.message_uuid}`); res.status(200).json({ success: true, message: 'MMS sending initiated successfully.', message_uuid: result.message_uuid }); } else { console.error(`Failed to send MMS to ${recipient}: ${result.error}`); // Send a generic error message to the client, log the specific error internally res.status(500).json({ success: false, error: 'Failed to send MMS. Check server logs for details.' // Avoid sending detailed internal errors (like Vonage API errors) to the client // detailed_error: result.error // Potentially expose internal info, use with caution }); } }); // --- Root Endpoint for Health Check --- app.get('/', (req, res) => { res.status(200).send('Vonage MMS Sender API is running!'); }); // --- Start the Server --- app.listen(PORT, () => { console.log(`Server listening on port ${PORT}`); console.log(`API Endpoint available at http://localhost:${PORT}/send-mms (POST)`); });
-
Explanation:
- Express Initialization: Creates an Express application instance.
- Port: Defines the port number, preferring the
PORT
environment variable if set, otherwise defaulting to 3000. - Middleware:
express.json()
: Parses incoming requests with JSON payloads (needed forreq.body
).express.urlencoded()
: Parses incoming requests with URL-encoded payloads.
/send-mms
Endpoint (POST):- Defines a route that listens for POST requests at
/send-mms
. - Extracts
recipient
,imageUrl
, and optionalcaption
from the request body (req.body
). - Input Validation: Performs basic checks:
- Ensures
recipient
andimageUrl
are present. - Checks if the
imageUrl
starts withhttp://
orhttps://
. - Uses a simple regex (
phoneRegex
) to validate the basic structure of the phone number. Note: Robust E.164 validation is complex; this is a basic check. The error message guides the user towards the preferred E.164 format. - Returns a
400 Bad Request
status with an error message if validation fails.
- Ensures
- Calls the
sendMmsMessage
function with the validated inputs. - Responds to the client based on the
result
fromsendMmsMessage
:- On success: Sends a
200 OK
status with themessage_uuid
. - On failure: Sends a
500 Internal Server Error
status with a generic error message. It's crucial not to expose detailed internal Vonage error messages directly to the client for security reasons. Log the detailed error server-side.
- On success: Sends a
- Defines a route that listens for POST requests at
/
Endpoint (GET): A simple root endpoint for basic health checks or landing page.app.listen
: Starts the Express server, making it listen for incoming connections on the specifiedPORT
. Logs confirmation messages to the console.
4. Integrating with Vonage (Dashboard Configuration)
This is a critical step where you configure your Vonage account and link it to your application code via credentials.
-
Log in to Vonage API Dashboard: Access your dashboard at dashboard.nexmo.com.
-
Create a Vonage Application:
- Navigate to ""Applications"" in the left-hand menu and click ""Create a new application"".
- Name: Give your application a descriptive name (e.g., ""Node Express MMS Sender"").
- Capabilities: Find the ""Messages"" capability and toggle it ON.
- Webhooks (Inbound & Status): You must provide URLs for both ""Inbound URL"" and ""Status URL"" when enabling the Messages capability.
- Why? Even if this simple sender application doesn't process incoming messages or status updates, Vonage requires valid, publicly accessible URLs during setup for the Messages capability. The platform uses these endpoints to report message delivery statuses and handle incoming messages directed to your linked number. Without valid URLs that respond with
200 OK
, the platform might retry sending webhook data, and application setup might fail or behave unexpectedly. - Therefore, for local development and testing that involves setting up the application in the Vonage dashboard, a tool like ngrok becomes practically necessary to provide these required URLs.
- Development: Use
ngrok
to get a public URL for your local server. If your app runs on port 3000, start ngrok:ngrok http 3000
. Copy thehttps://
forwarding URL provided by ngrok (e.g.,https://<unique-code>.ngrok.io
).- Inbound URL:
https://<unique-code>.ngrok.io/webhooks/inbound
(Even if you don't implement this route yet) - Status URL:
https://<unique-code>.ngrok.io/webhooks/status
(Even if you don't implement this route yet)
- Inbound URL:
- Production: Replace these with the actual public URLs of your deployed application's webhook handlers.
- Placeholder (Alternative): You can use a service like Mockbin to generate URLs that simply return a 200 OK status. This is sufficient if you only need to send and don't care about status/inbound webhooks for now.
- Why? Even if this simple sender application doesn't process incoming messages or status updates, Vonage requires valid, publicly accessible URLs during setup for the Messages capability. The platform uses these endpoints to report message delivery statuses and handle incoming messages directed to your linked number. Without valid URLs that respond with
- Generate Public/Private Key: Click the ""Generate public and private key"" link.
- A public key will be added to the application settings.
- A
private.key
file will be automatically downloaded. Save this file securely. For this guide, move it into your project's root directory (vonage-mms-sender/private.key
). Remember to addprivate.key
to your.gitignore
.
- Click ""Generate new application"".
-
Note Application ID: After creation, you'll be taken to the application's details page. Copy the Application ID.
-
Link Your Vonage Number:
- Scroll down to the ""Linked numbers"" section on the application details page.
- Find your US MMS-capable Vonage number and click the ""Link"" button next to it. If you don't have one, click ""Buy numbers"". Linking ensures messages sent from this number use this application's settings (including authentication) and incoming messages to this number trigger the Inbound webhook.
-
Get API Key and Secret:
- Click your username/profile icon in the top-right corner of the dashboard or navigate to the main dashboard overview page.
- Your API Key and API Secret are displayed near the top. Copy both.
-
Configure
.env
File: Open the.env
file in your project and add the credentials you just gathered.# .env - Vonage Credentials and Configuration # Vonage API Credentials (Found on Dashboard Home) VONAGE_API_KEY=YOUR_API_KEY_HERE VONAGE_API_SECRET=YOUR_API_SECRET_HERE # Vonage Application Credentials (Generated during Application setup) VONAGE_APPLICATION_ID=YOUR_APPLICATION_ID_HERE # Path relative to the project root where private.key is stored VONAGE_PRIVATE_KEY_PATH=./private.key # Vonage Number linked to the Application (Use E.164 format ideally, e.g., 14155550100) VONAGE_SENDER_NUMBER=YOUR_VONAGE_US_NUMBER_HERE # Optional: Server Port PORT=3000
- Replace the placeholder values with your actual credentials.
- Ensure
VONAGE_PRIVATE_KEY_PATH
points correctly to where you saved theprivate.key
file. - Use your purchased/linked Vonage US number for
VONAGE_SENDER_NUMBER
.
5. Implementing Error Handling and Logging
We've already incorporated basic error handling, but let's refine and discuss logging.
-
Error Handling Strategy:
- Input Validation: Handle invalid client requests early (in the API route handler) with
400 Bad Request
responses. - Vonage API Errors: Catch errors during the
messagesClient.send
call within thesendMmsMessage
function. Log detailed errors server-side. Respond to the client with a generic500 Internal Server Error
to avoid leaking internal details. - Configuration Errors: Check for missing environment variables on startup and exit gracefully.
- Input Validation: Handle invalid client requests early (in the API route handler) with
-
Logging:
- Current Logging: We are using
console.log
for informational messages (request received, MMS initiated) andconsole.error
for errors (validation failures, Vonage API errors). - Production Logging: For production, replace
console.log
/console.error
with a dedicated logging library like Winston or Pino. These offer features like:- Log levels (debug, info, warn, error).
- Structured logging (JSON format for easier parsing).
- Multiple transports (writing logs to files, databases, or logging services).
- Log rotation.
- Example (Conceptual with Winston):
// // Conceptual Winston Setup (replace console logs) // const winston = require('winston'); // const logger = winston.createLogger({ // level: 'info', // Log info and above // format: winston.format.json(), // Log in JSON format // transports: [ // new winston.transports.Console(), // Log to console // // new winston.transports.File({ filename: 'error.log', level: 'error' }), // Log errors to file // // new winston.transports.File({ filename: 'combined.log' }) // Log all levels to another file // ], // }); // // // Replace console.log('Info message') with logger.info('Info message'); // // Replace console.error('Error message', error) with logger.error('Error message', { error: error.message });
- Current Logging: We are using
-
Retry Mechanisms: The Vonage platform itself often has retry mechanisms for webhooks. For sending messages, if a send operation fails due to a transient network issue or temporary Vonage outage (e.g., 5xx errors from Vonage), you could implement a retry strategy with exponential backoff in your
sendMmsMessage
function. However, for sending single transactional MMS, retrying immediately might not always be desirable (could lead to duplicate sends if the first request actually succeeded but the response failed). A more robust approach often involves queuing failed messages for later retry attempts or manual intervention, which is beyond the scope of this basic guide.
6. Database Schema and Data Layer
For this specific application (simply sending MMS via an API call), a database is not required. We are not storing message history, user data, or application state beyond the configuration in .env
.
If you were building a more complex application (e.g., tracking sent messages, managing contacts, queuing messages), you would introduce a database (like PostgreSQL, MongoDB) and a data access layer (using an ORM like Prisma or Sequelize, or native drivers). This would involve:
- Defining schemas/models (e.g., a
Messages
table withrecipient
,status
,message_uuid
,sent_at
, etc.). - Implementing functions to interact with the database (create, read, update records).
- Setting up database migrations.
7. Adding Security Features
Security is paramount, especially when handling API keys and sending messages.
-
Input Validation and Sanitization:
- We implemented basic validation for required fields (
recipient
,imageUrl
), URL format, and phone number format in the/send-mms
route. - Enhancement: Use libraries like
joi
orexpress-validator
for more robust and declarative validation schemas. - Sanitization: While less critical for the fields used here (phone number, URL), always sanitize user input intended for display or database storage to prevent Cross-Site Scripting (XSS) attacks. Libraries like
express-validator
often include sanitization methods.
- We implemented basic validation for required fields (
-
Secure Credential Handling:
.env
File: We use.env
to keep credentials out of the code..gitignore
: Ensure.env
andprivate.key
are listed in.gitignore
.- Production: Use environment variables provided by your deployment platform (e.g., Heroku Config Vars, AWS Secrets Manager, Docker environment variables) instead of committing a
.env
file. Load theprivate.key
content securely, potentially directly into an environment variable or from a secure file mount. (See Section 12 - Note: Section 12 was not provided in the original text).
-
Protection Against Common Vulnerabilities:
- Rate Limiting: Prevent abuse by limiting the number of requests a client can make to your
/send-mms
endpoint within a given time window. Use middleware likeexpress-rate-limit
.npm install express-rate-limit
// // Example Rate Limiting (add before your routes in index.js) // const rateLimit = require('express-rate-limit'); // const limiter = rateLimit({ // windowMs: 15 * 60 * 1000, // 15 minutes // max: 100, // Limit each IP to 100 requests per windowMs // message: 'Too many requests from this IP, please try again after 15 minutes' // }); // app.use('/send-mms', limiter); // Apply limiter specifically to the send endpoint
- Helmet: Use the
helmet
middleware to set various HTTP headers that improve security (e.g.,X-Content-Type-Options
,Referrer-Policy
,Strict-Transport-Security
).npm install helmet
// // Example Helmet Usage (add near the top of middleware in index.js) // const helmet = require('helmet'); // app.use(helmet());
- Rate Limiting: Prevent abuse by limiting the number of requests a client can make to your
-
Authentication/Authorization (API Layer):
- Our current API is open. In a real-world scenario, you would protect the
/send-mms
endpoint. Common methods include:- API Key: Require clients to send a secret API key in a header (e.g.,
X-API-Key
). Validate this key on the server. - JWT (JSON Web Tokens): Implement user authentication, issue JWTs upon login, and require valid JWTs for API access.
- API Key: Require clients to send a secret API key in a header (e.g.,
- Our current API is open. In a real-world scenario, you would protect the
8. Handling Special Cases
- Image URL Requirements: The
imageUrl
must be publicly accessible without requiring authentication. Vonage servers need to fetch this image to send it. Ensure the URL points directly to the image file (.jpg
,.jpeg
,.png
). Redirects might cause issues. - US Number Restrictions: Vonage MMS via the Messages API generally works for sending from US 10DLC, Toll-Free, or Short Code numbers to US destination numbers. Sending to international numbers or using non-US Vonage numbers for MMS via this API might not be supported or may require different configurations. Always check the latest Vonage documentation for number capabilities.
- A2P Use Case: MMS is intended for Application-to-Person communication. Using Vonage virtual numbers to send MMS to other Vonage virtual numbers might not work reliably or might be blocked.
- Character Limits: While MMS supports longer text captions than SMS, there are still practical limits. Keep captions reasonably concise.
- Encoding: Ensure your Node.js environment and Express app handle UTF-8 encoding correctly, especially if dealing with captions containing special characters. Express generally handles this well by default.
9. Implementing Performance Optimizations
For this simple sending API, performance bottlenecks are unlikely unless sending extremely high volumes concurrently.
- SDK Efficiency: The Vonage Node.js SDK is generally efficient.
- Asynchronous Operations: Using
async/await
ensures Node.js isn't blocked while waiting for the Vonage API response. - Connection Pooling: The underlying HTTP requests made by the SDK typically benefit from Node.js's default connection pooling.
- Caching: Caching is not applicable here, as each API call represents a unique send request.
- Load Testing: If high throughput is expected, use tools like
k6
,Artillery
, orApacheBench (ab)
to load test the/send-mms
endpoint and identify potential bottlenecks in your infrastructure or rate limiting by Vonage. - Profiling: Use Node.js built-in profiler (
node --prof index.js
) or tools like Clinic.js to analyze CPU usage and event loop delays under load if performance issues arise.
10. Adding Monitoring, Observability, and Analytics
- Health Checks: The
/
endpoint provides a basic health check. Monitoring services (like UptimeRobot, Pingdom, or Kubernetes liveness probes) can ping this endpoint to ensure the service is running. - Logging: As discussed in Section 5, robust logging (preferably structured JSON) is key. Forward logs to a centralized logging platform (e.g., Datadog, Splunk, ELK stack) for analysis and alerting.
- Error Tracking: Integrate services like Sentry or Bugsnag to automatically capture, aggregate, and alert on unhandled exceptions and errors within your application.
- Vonage Dashboard: Monitor message status, usage, and potential delivery errors directly within the Vonage API Dashboard under ""Logs"" > ""Messages API Logs"". Filter by Application ID or Message UUID.
- Metrics: Instrument your application to send metrics (e.g., request count, error rate, response latency for
/send-mms
, MMS success/failure count) to a monitoring system like Prometheus (with Grafana for dashboards) or Datadog.
11. Troubleshooting and Caveats
401 Unauthorized
Error:- Cause: Incorrect credentials or authentication method. For Messages API v1 (MMS), ensure you are initializing the
Vonage
client withapplicationId
andprivateKey
. Double-checkVONAGE_APPLICATION_ID
and the pathVONAGE_PRIVATE_KEY_PATH
in.env
. Verify theprivate.key
file content is correct and hasn't been corrupted. Ensure the numberVONAGE_SENDER_NUMBER
is correctly linked to theVONAGE_APPLICATION_ID
in the dashboard. - Solution: Verify all credentials and the path. Ensure the number is linked. Confirm MMS capability is enabled on your account/number if necessary (contact Vonage support).
- Cause: Incorrect credentials or authentication method. For Messages API v1 (MMS), ensure you are initializing the
Non-Whitelisted Destination
Error (During Testing/Trial):- Cause: Vonage trial accounts can typically only send messages to phone numbers verified and