code examples

Sent logo
Sent TeamMay 3, 2025 / code examples / Article

Send MMS with Node.js, Express, and Vonage

A guide to building a Node.js and Express application for sending MMS messages using the Vonage Messages API, covering setup, implementation, and testing.

This guide provides a step-by-step walkthrough for building a Node.js and Express application capable of sending MMS (Multimedia Messaging Service) messages using the Vonage Messages API. We'll cover everything from project setup and Vonage configuration to implementing the core sending logic, handling errors, and testing the endpoint.

By the end of this tutorial, you will have a functional Express API endpoint that accepts a recipient phone number, an image URL, and an optional caption, then sends an MMS message via Vonage.

Technologies Used:

  • Node.js: A JavaScript runtime environment for server-side development.
  • Express: A minimal and flexible Node.js web application framework.
  • Vonage Messages API: A multi-channel API enabling communication via SMS, MMS, WhatsApp, and more. We'll use its MMS capabilities.
  • @vonage/messages SDK: The official Vonage Node.js SDK specifically for interacting with the Messages API.
  • dotenv: A module to load environment variables from a .env file.
  • ngrok (for setup/testing): A tool to expose local servers to the internet, necessary for configuring Vonage webhooks during setup.

System Architecture:

A typical flow involves an end-user triggering your Express API, which then uses the Vonage SDK to call the Vonage Messages API. Vonage handles the interaction with carrier networks to deliver the MMS to the recipient's phone. Configuration details like API keys are read from environment variables.

(A diagram illustrating this flow would typically be included here.)

Prerequisites:

  • Node.js and npm (or yarn): Installed on your development machine. (Download Node.js)
  • Vonage API Account: Sign up for free if you don't have one. (Vonage Signup) You'll get some free credit to start.
  • Vonage US Number: Purchase an MMS-capable US number from your Vonage dashboard (Numbers > Buy Numbers). MMS sending is primarily supported from US 10DLC, Toll-Free, or Short Code numbers to US recipients.
  • ngrok: Installed and authenticated (a free account is sufficient). (Download ngrok) We need this temporarily during Vonage application setup.
  • Basic understanding of JavaScript, Node.js, and REST APIs.

1. Vonage Account and Application Setup

Before writing code, we need to configure Vonage correctly.

  1. Log in to your Vonage API Dashboard.
  2. Get API Key and Secret: Note down your API key and API secret found at the top of the dashboard.
  3. Purchase a Number: Navigate to Numbers > Buy numbers. Search for a US number with SMS and MMS capabilities enabled. Purchase one. Note down this number (e.g., 12015550123). This will be your VONAGE_NUMBER.
  4. Set Messages API as Default: Go to Account Settings. Scroll down to API settings > Default SMS Setting. Ensure Messages API is selected as the default for sending SMS messages. This ensures consistency if you later mix SMS and MMS via the Messages API. Click Save changes.
  5. Create a Vonage Application:
    • Navigate to Applications > + Create a new application.
    • Give it a name (e.g., My Node MMS App).
    • Generate Public/Private Key: Click Generate public and private key. A public key will appear in the form, and a private.key file will be downloaded. Save this private.key file securely — we'll place it in our project directory later.
    • Enable Capabilities: Toggle on Messages. This will reveal fields for Status URL and Inbound URL.
    • Configure Webhooks (Temporary Setup): Vonage requires these URLs even if you're only sending MMS, as they can receive delivery status updates. We'll use ngrok to create temporary public URLs pointing to our local machine.
      • Open a terminal and run: ngrok http 3000 (assuming our Express app will run on port 3000).
      • Copy the Forwarding URL provided by ngrok (it looks like https://<random_string>.ngrok.io).
      • In the Vonage application settings:
        • Set Status URL to <your_ngrok_url>/webhooks/status
        • Set Inbound URL to <your_ngrok_url>/webhooks/inbound
        • Select POST for the HTTP Method for both.
      • Note: These endpoints don't need to actually exist in our simple sending application, but Vonage requires valid URLs during setup.
    • Click Create application.
  6. Link Your Number: On the next screen, find the US number you purchased earlier and click the Link button next to it to associate it with this application.
  7. Note Application ID: After linking the number, you'll be back on the application's overview page. Note down the Application ID.

You now have:

  • Vonage API Key
  • Vonage API Secret
  • Vonage Application ID
  • Your purchased Vonage Number (Sender Number)
  • The private.key file

2. Setting Up the Node.js Project

Let's create our Node.js project structure.

  1. Create Project Directory:

    bash
    mkdir vonage-mms-sender
    cd vonage-mms-sender
  2. Initialize Node.js Project:

    bash
    npm init -y

    This creates a package.json file.

  3. Enable ES Modules: Open the generated package.json file and add the following top-level key-value pair to enable ES Module syntax (import/export) used in the code:

    json
    {
      ""name"": ""vonage-mms-sender"",
      ""version"": ""1.0.0"",
      ""description"": """",
      ""main"": ""index.js"",
      ""type"": ""module"",
      ""scripts"": {
        ""test"": ""echo \""Error: no test specified\"" && exit 1""
      },
      ""keywords"": [],
      ""author"": """",
      ""license"": ""ISC""
    }

    Save the package.json file.

  4. Install Dependencies:

    bash
    npm install express @vonage/messages dotenv
    • express: The web framework.
    • @vonage/messages: The Vonage SDK for the Messages API.
    • dotenv: To manage environment variables.
  5. Create Project Files:

    bash
    touch index.js .env .gitignore
  6. Configure .gitignore: Add the following lines to your .gitignore file to prevent committing sensitive information and unnecessary files:

    text
    # Dependencies
    node_modules
    
    # Environment variables
    .env
    
    # Vonage Private Key
    private.key
    
    # Logs
    npm-debug.log*
    yarn-debug.log*
    yarn-error.log*
  7. Place Private Key: Move the private.key file you downloaded from Vonage into the root of your vonage-mms-sender project directory.

  8. Set Up Environment Variables: Open the .env file and add your Vonage credentials and configuration. Replace the placeholder values with your actual credentials.

    dotenv
    # .env
    
    # Vonage Credentials
    VONAGE_API_KEY=YOUR_VONAGE_API_KEY
    VONAGE_API_SECRET=YOUR_VONAGE_API_SECRET
    VONAGE_APP_ID=YOUR_VONAGE_APPLICATION_ID
    VONAGE_PRIVATE_KEY_PATH=./private.key # Path relative to project root
    
    # Vonage Number (Must be MMS capable and linked to the App ID)
    # Use E.164 format (e.g., 12015550123)
    VONAGE_NUMBER=YOUR_VONAGE_SENDER_NUMBER
    
    # Server Configuration
    PORT=3000
    • VONAGE_API_KEY: Found on your Vonage Dashboard.
    • VONAGE_API_SECRET: Found on your Vonage Dashboard.
    • VONAGE_APP_ID: Found on your Vonage Application's page after creation.
    • VONAGE_PRIVATE_KEY_PATH: The path to the private.key file you placed in the project root. ./private.key is correct if it's in the same directory as index.js.
    • VONAGE_NUMBER: The MMS-capable US number you purchased and linked, in E.164 format.
    • PORT: The port your Express server will listen on (matching the ngrok setup).

3. Implementing Core Functionality: The Express API

Now, let's write the code for our Express server and the MMS sending logic.

Edit index.js:

javascript
// index.js
import express from 'express';
import 'dotenv/config'; // Load environment variables from .env file
import { Messages, MMSImage } from '@vonage/messages'; // Import necessary classes

// --- Configuration ---
const PORT = process.env.PORT || 3000;
const VONAGE_API_KEY = process.env.VONAGE_API_KEY;
const VONAGE_API_SECRET = process.env.VONAGE_API_SECRET;
const VONAGE_APP_ID = process.env.VONAGE_APP_ID;
const VONAGE_PRIVATE_KEY_PATH = process.env.VONAGE_PRIVATE_KEY_PATH;
const VONAGE_NUMBER = process.env.VONAGE_NUMBER;

// Basic validation for essential environment variables
if (!VONAGE_API_KEY || !VONAGE_API_SECRET || !VONAGE_APP_ID || !VONAGE_PRIVATE_KEY_PATH || !VONAGE_NUMBER) {
    console.error(""Error: Missing required Vonage environment variables. Please check your .env file."");
    process.exit(1); // Exit if configuration is incomplete
}

// --- Initialize Vonage Client ---
// Use a try-catch block for robustness in case the private key path is wrong
let vonageMessages;
try {
    vonageMessages = new Messages({
        apiKey: VONAGE_API_KEY,
        apiSecret: VONAGE_API_SECRET,
        applicationId: VONAGE_APP_ID,
        privateKey: VONAGE_PRIVATE_KEY_PATH,
    });
    console.info(""Vonage client initialized successfully."");
} catch (error) {
    console.error(""Error initializing Vonage client:"", error.message);
    console.error(""Ensure VONAGE_PRIVATE_KEY_PATH in .env points to your private.key file."");
    process.exit(1);
}


// --- Initialize Express App ---
const app = express();

// Middleware to parse JSON request bodies
app.use(express.json());
// Middleware to parse URL-encoded request bodies
app.use(express.urlencoded({ extended: true }));

// --- API Routes ---

// Simple health check endpoint
app.get('/', (req, res) => {
    res.status(200).json({ message: 'Vonage MMS Sender API is running!' });
});

/**
 * POST /send-mms
 * Sends an MMS message via Vonage.
 * Request Body:
 * {
 *   ""to"": ""RECIPIENT_PHONE_NUMBER"", // E.164 format (e.g., 14155550100)
 *   ""imageUrl"": ""PUBLICLY_ACCESSIBLE_IMAGE_URL"", // e.g., https://placekitten.com/200/300
 *   ""caption"": ""Optional image caption"" // Optional
 * }
 */
app.post('/send-mms', async (req, res) => {
    console.log(""Received request to /send-mms:"", req.body);

    const { to, imageUrl, caption } = req.body;

    // --- Input Validation ---
    if (!to || !imageUrl) {
        console.error(""Validation Error: 'to' and 'imageUrl' are required."");
        return res.status(400).json({ success: false, message: ""Missing required fields: 'to' and 'imageUrl'."" });
    }

    // Basic validation for phone number format (simple check)
    // WARNING: Basic E.164 format check. Use a library like libphonenumber-js for production.
    if (!/^\+?[1-9]\d{1,14}$/.test(to)) {
         console.error(`Validation Error: Invalid 'to' phone number format: ${to}`);
         return res.status(400).json({ success: false, message: ""Invalid 'to' phone number format. Use E.164 format (e.g., 14155550100)."" });
    }

    // Basic validation for URL format (simple check)
    try {
        new URL(imageUrl);
    } catch (_) {
        console.error(`Validation Error: Invalid 'imageUrl': ${imageUrl}`);
        return res.status(400).json({ success: false, message: ""Invalid 'imageUrl'. Must be a valid URL."" });
    }

    // --- Construct MMS Payload ---
    const mmsPayload = new MMSImage({
        to: to,
        from: VONAGE_NUMBER, // Your Vonage sender number from .env
        image: {
            url: imageUrl,
            caption: caption || '', // Use provided caption or empty string
        },
        // channel: 'mms' // Channel is inferred by MMSImage, but can be explicit
    });

    // --- Send MMS via Vonage ---
    try {
        console.log(`Attempting to send MMS to ${to} from ${VONAGE_NUMBER}`);
        const response = await vonageMessages.send(mmsPayload);

        console.log(""Success: Vonage API Response:"", response);
        res.status(200).json({
            success: true,
            message: ""MMS sent successfully!"",
            message_uuid: response.message_uuid,
        });

    } catch (error) {
        console.error(""Error sending MMS via Vonage:"", error);

        // Provide more specific feedback if possible
        let errorMessage = ""Failed to send MMS."";
        if (error.response && error.response.data) {
            console.error(""Vonage Error Details:"", error.response.data);
            errorMessage = error.response.data.title || error.response.data.detail || errorMessage;
             // Check for common trial account error
            if (error.response.data.detail && error.response.data.detail.includes(""Non-Whitelisted Destination"")) {
                errorMessage += "" Ensure the recipient number is added to your Vonage account's allowed list for trial accounts."";
            }
        } else if (error.message) {
             errorMessage = error.message;
        }


        res.status(500).json({
            success: false,
            message: ""Error sending MMS."",
            error: errorMessage,
            details: error.response ? error.response.data : ""No response data"" // Include details if available
        });
    }
});

// --- Start Server ---
app.listen(PORT, () => {
    console.log(`Server listening on port ${PORT}`);
    console.log(`Vonage Number (Sender): ${VONAGE_NUMBER}`);
    console.log(`API Key Loaded: ${!!VONAGE_API_KEY}`);
    console.log(`App ID Loaded: ${!!VONAGE_APP_ID}`);
    console.log(`Private Key Path: ${VONAGE_PRIVATE_KEY_PATH}`);
    console.log(`\nSend POST requests to http://localhost:${PORT}/send-mms`);
    console.log(`Example Body: { ""to"": ""1..."", ""imageUrl"": ""https://..."", ""caption"": ""Hi!"" }`);
});

Code Explanation:

  1. Imports: We import express, dotenv/config (to load .env immediately), and the necessary classes (Messages, MMSImage) from @vonage/messages.
  2. Configuration: We load environment variables using process.env and perform basic checks to ensure critical Vonage credentials are set.
  3. Vonage Client Initialization: We create an instance of the Messages client, passing our API key, secret, application ID, and the path to the private key. A try-catch block handles potential errors during initialization (e.g., wrong private key path).
  4. Express Setup: We initialize the Express app and add middleware (express.json, express.urlencoded) to parse incoming request bodies.
  5. Health Check Route (/): A simple GET route to verify the server is running.
  6. /send-mms Route (POST):
    • This is the core endpoint. It's an async function to handle the asynchronous vonageMessages.send call.
    • Input Extraction: It retrieves to, imageUrl, and caption from the req.body.
    • Input Validation: It performs basic checks:
      • Ensures to and imageUrl are present.
      • Uses a simple regex to validate the to number format. Note: This regex is very basic and primarily for demonstration. For production applications, use a dedicated, robust phone number validation library (like libphonenumber-js) to handle various international formats and validity rules correctly.
      • Uses new URL() in a try-catch to validate the imageUrl.
    • Payload Construction: It creates an MMSImage object, providing the to number, the from number (your Vonage number from .env), and an image object containing the url and caption.
    • Sending: It calls vonageMessages.send(mmsPayload) within a try...catch block.
    • Success Response: If the API call is successful, it logs the response and sends a 200 status with the message_uuid.
    • Error Handling: If the API call fails, it logs the error extensively. It attempts to extract specific error messages from the Vonage response (error.response.data) and sends a 500 status with details about the failure. It specifically checks for the ""Non-Whitelisted Destination"" error common with trial accounts.
  7. Server Start: app.listen starts the server on the specified PORT and logs informative messages to the console.

4. Running and Testing the Application

  1. Start the Server: Open your terminal in the vonage-mms-sender directory and run:

    bash
    node index.js

    (Because we added ""type"": ""module"" to package.json, we can run the file directly with node). You should see output indicating the server is running on port 3000 and confirming your configuration loaded.

  2. Test with curl or Postman: Send a POST request to your running server.

    Using curl: Replace <RECIPIENT_PHONE_NUMBER> with a valid US phone number (in E.164 format, e.g., 14155550100). If you have a trial Vonage account, this number must be added to your allowed list in the Vonage Dashboard (Sandbox & Test Numbers section). Replace <PUBLIC_IMAGE_URL> with a direct link to a JPG or PNG image (e.g., https://placekitten.com/300/400).

    bash
    curl -X POST http://localhost:3000/send-mms \
    -H ""Content-Type: application/json"" \
    -d '{
      ""to"": ""<RECIPIENT_PHONE_NUMBER>"",
      ""imageUrl"": ""<PUBLIC_IMAGE_URL>"",
      ""caption"": ""Hello from Node.js and Vonage!""
    }'

    Using Postman:

    • Create a new request.
    • Set the method to POST.
    • Set the URL to http://localhost:3000/send-mms.
    • Go to the Body tab, select raw, and choose JSON from the dropdown.
    • Paste the JSON payload:
      json
      {
        ""to"": ""<RECIPIENT_PHONE_NUMBER>"",
        ""imageUrl"": ""<PUBLIC_IMAGE_URL>"",
        ""caption"": ""Hello from Postman, Node.js and Vonage!""
      }
    • Click Send.
  3. Check the Response:

    • Success: You should receive a 200 OK status code and a JSON response like:
      json
      {
        ""success"": true,
        ""message"": ""MMS sent successfully!"",
        ""message_uuid"": ""some-unique-message-identifier""
      }
      Check the recipient's phone; the MMS should arrive shortly. Also, check your terminal running the Node.js app for logs.
    • Failure: You might receive:
      • 400 Bad Request: If required fields are missing or formats are invalid (check terminal logs for specifics).
      • 500 Internal Server Error: If Vonage failed to send the message (check terminal logs for Vonage error details). Common issues include invalid credentials, non-whitelisted number on trial accounts, or problems with the image URL.

5. Troubleshooting and Caveats

  • Trial Account Limitation: If you're using a free trial Vonage account, you can only send messages to phone numbers you've verified and added to your test numbers list in the dashboard (Sandbox & Test Numbers). Attempts to send elsewhere will result in a ""Non-Whitelisted Destination"" error.
  • A2P (Application-to-Person) Only: The Vonage Messages API, like most carrier-based messaging, generally does not support sending MMS from one virtual number (like your Vonage number) to another virtual number. It's designed for sending from an application/number to an end-user's actual mobile device on a carrier network. This limitation is typical for standard MMS delivery.
  • US MMS Routing: MMS sending via Vonage is primarily supported from registered US 10DLC, Toll-Free, or Short Code numbers to recipients within the US. International MMS has limited support and may require specific configurations. Always consult the official Vonage documentation for the most up-to-date information on international MMS capabilities and requirements.
  • Publicly Accessible Image URL: The imageUrl must point to a publicly accessible JPG, JPEG, or PNG file. Vonage needs to fetch this image to send it. Private URLs or URLs requiring authentication will not work. Use services like Imgur or public cloud storage buckets (ensure permissions are public read).
  • File Size Limits: Carriers often impose limits on MMS message size (typically 300KB - 1MB). Very large images might fail to send.
  • Invalid Credentials/Setup: Double-check your VONAGE_API_KEY, VONAGE_API_SECRET, VONAGE_APP_ID, and VONAGE_PRIVATE_KEY_PATH in your .env file. Ensure the private.key file exists at the specified path. Make sure the VONAGE_NUMBER is correctly linked to the VONAGE_APP_ID in the dashboard.
  • Number Formatting: Always use the E.164 format for phone numbers (e.g., +14155550100 or 14155550100).
  • Webhook Configuration: While our app doesn't use the webhook endpoints defined during setup, Vonage requires them for the application configuration. Ensure the ngrok tunnel used during setup was running and the URLs were entered correctly. For production, you'd replace these with actual endpoints on your deployed server to handle status updates.
  • SDK Versioning: Ensure you are using compatible versions of Node and the @vonage/messages SDK. Check the SDK documentation for requirements if you encounter unexpected issues.

6. Security Considerations

This example provides a basic, open endpoint. For production use, consider:

  • Authentication/Authorization: Protect the /send-mms endpoint. Implement API key checking, JWT validation, or other mechanisms to ensure only authorized clients can trigger MMS sending.
  • Input Validation & Sanitization: Use a robust validation library (like joi or express-validator) to thoroughly check incoming to, imageUrl, and caption data against expected formats and lengths. Sanitize inputs to prevent potential injection attacks (though less critical for these specific fields, it's good practice). The basic regex and new URL() checks included in this example are insufficient for a production environment.
  • Rate Limiting: Implement rate limiting (e.g., using express-rate-limit) to prevent abuse and control costs. Limit how many MMS messages a single client or IP address can send within a certain time window.
  • Secret Management: In production deployments, avoid storing secrets directly in .env files within the repository. Use dedicated secret management solutions provided by your cloud provider (e.g., AWS Secrets Manager, Google Secret Manager, Azure Key Vault) or tools like HashiCorp Vault.
  • Error Handling: Log errors appropriately but avoid leaking sensitive details (like full error stacks or internal paths) in responses sent back to the client.

7. Deployment and CI/CD (Conceptual)

  • Environment Configuration: Use environment variables specific to your deployment environment (staging, production). Do not commit .env files with production secrets.
  • Platform Choice: Deploy to platforms like Heroku, AWS (EC2, Lambda, Fargate), Google Cloud (App Engine, Cloud Run), Azure (App Service), or DigitalOcean.
  • Build Process: Your CI/CD pipeline would typically:
    1. Check out code.
    2. Install dependencies (npm install).
    3. Run tests (npm test - you'd add tests!).
    4. Build (if necessary).
    5. Package the application (e.g., into a Docker container).
    6. Deploy the package/container to your chosen platform, injecting environment variables securely.
  • Webhooks in Production: Update the Vonage Application's Status URL and Inbound URL to point to the actual public URLs of your deployed application (e.g., https://your-app-domain.com/webhooks/status). Implement handlers for these endpoints if you need delivery receipts or want to process inbound messages.

8. Verification and Further Steps

  • Manual Verification: Send test MMS messages to different (whitelisted, if trial) numbers and confirm receipt. Test with various valid image URLs. Test edge cases like missing captions or different image types (JPG vs PNG). Test invalid inputs (bad phone numbers, non-existent URLs) to ensure error handling works.
  • Logging: Enhance logging using a dedicated library (like winston or pino) for structured logging, different log levels, and easier analysis in production.
  • Delivery Status: Implement the /webhooks/status endpoint to receive delivery receipts (DLRs) from Vonage, allowing you to track if messages were successfully delivered to the carrier and handset.
  • Fallback: For critical messages, consider using the Vonage Dispatch API. If MMS delivery fails (indicated by a DLR), Dispatch could automatically try sending the message content via SMS (perhaps with a link to the image).
  • Testing: Add unit tests (e.g., using Jest or Mocha) to test individual functions and input validation logic. Add integration tests to verify the endpoint's interaction with the Vonage SDK (potentially using mocks or a dedicated test account).

This guide provides a solid foundation for sending MMS messages using Node.js, Express, and Vonage. Remember to adapt the security, error handling, and deployment strategies for your specific production requirements.

Frequently Asked Questions

How to send MMS with Node.js and Express?

Use the Vonage Messages API and the @vonage/messages SDK. Set up an Express server, configure your Vonage account, and create an API endpoint that accepts recipient details and image information. The Vonage SDK handles communication with the API to deliver the MMS.

What is the Vonage Messages API used for?

The Vonage Messages API is a multi-channel API that enables sending messages via various channels like SMS, MMS, WhatsApp, and more. In this tutorial, it's used to send multimedia messages (MMS) containing images and captions.

Why does Vonage require a private key?

The private key is crucial for secure authentication with the Vonage API. It's used to sign API requests, ensuring that only authorized applications can access your Vonage account and send messages.

When should I use ngrok for Vonage setup?

ngrok is useful during development and initial setup when your local server isn't publicly accessible. It creates a temporary public URL that Vonage can use for webhooks, which are necessary for the setup process, even for just sending MMS.

Can I send MMS to international numbers with Vonage?

International MMS support is limited. While Vonage primarily supports MMS from US numbers to US recipients, some international options might exist. Consult the Vonage documentation for the most current information on international MMS capabilities and any specific requirements or limitations.

How to set up a Vonage application for MMS?

Log into your Vonage dashboard, create a new application, enable the Messages capability, generate and securely store your private key, and link an MMS-capable number to your Vonage application. Set up the necessary webhooks and note your Application ID.

What is the purpose of the private.key file?

The `private.key` file contains your Vonage application's private key, which is essential for authenticating your application with the Vonage API. It must be kept secure and should not be shared or committed to version control.

How to install the necessary Node.js packages?

Use `npm install express @vonage/messages dotenv` to install the required packages. `express` is the web framework, `@vonage/messages` is the Vonage SDK, and `dotenv` helps manage environment variables.

Why do I need to configure webhooks for sending MMS?

While the basic MMS sending example doesn't actively use webhooks, Vonage requires them to be set up during application creation. They are typically used for receiving delivery receipts and inbound messages, which might be needed for more advanced functionalities.

What is the maximum MMS file size Vonage supports?

Carriers typically impose MMS file size limits, often between 300KB and 1MB. While not explicitly mentioned in the article with respect to Vonage's limits, large files may cause failures, and it's recommended to keep files small or compress them before sending.

How to handle errors when sending MMS with Vonage?

The provided code includes robust error handling using try-catch blocks around the API call. It logs errors to the console, attempts to extract specific error messages from the Vonage API response, and returns user-friendly errors to the client.

What is the 'Non-Whitelisted Destination' error?

This error occurs with trial Vonage accounts when you try to send an MMS to a number that hasn't been added to your allowed list in the Vonage dashboard's Sandbox & Test Numbers section. Add the recipient's number to your allowed list to resolve the issue.

How to structure the request body for sending MMS?

The request body must be JSON formatted and should include the recipient's phone number (`to`), the publicly accessible image URL (`imageUrl`), and an optional caption (`caption`). Format phone numbers using E.164.

What are some security best practices for a production MMS application?

Implement authentication and authorization for your sending endpoint. Use strong input validation, sanitize user inputs, implement rate limiting to prevent abuse, and use secure methods to manage secrets, avoiding storing them directly in `.env` files.