messaging channels
messaging channels
How to Send MMS with Plivo, Node.js, and Express: Complete API Guide
Learn how to send MMS messages using Plivo Node.js SDK and Express. Step-by-step tutorial with code examples for building a production-ready multimedia messaging API with images, videos, and audio.
Learn how to send MMS messages with Plivo using Node.js and Express in this comprehensive guide. Multimedia Messaging Service (MMS) lets you enrich user communication by sending images, videos, and audio files alongside text messages.
This tutorial shows you how to build a production-ready MMS API using the Plivo Node.js SDK and Express framework. You'll start with a basic script and progressively build toward a robust API endpoint capable of handling MMS requests – covering setup, authentication, error handling, security, and deployment best practices.
Project Overview and Goals
What You're Building:
Create a Node.js application that programmatically sends MMS messages via Plivo's API. This involves:
- A standalone script for sending a single MMS message
- An Express.js API endpoint (
POST /send-mms) that accepts recipient details, text, and a media URL to send an MMS
Problem Solved:
Integrate rich media messaging capabilities into your applications – move beyond simple text (SMS) to create engaging user experiences for notifications, alerts, marketing, or customer support.
Technologies Used:
- Node.js – JavaScript runtime environment for building scalable network applications
- Express.js – Minimal and flexible Node.js web application framework for creating API endpoints
- Plivo – Cloud communications platform providing APIs for voice, SMS, and MMS. You'll use their Node.js SDK (version 4.75.1) as of January 2025.
dotenv– Module to load environment variables from a.envfile, keeping sensitive credentials out of source code
System Architecture:
The basic flow for sending an MMS via your API endpoint looks like this:
[Client Application (e.g., Frontend, Mobile App, Backend Service)]
|
| Makes HTTP POST request to /send-mms
| (with destination number, text, media URL)
V
[Node.js/Express API Server] --(Uses Plivo SDK)--> [Plivo API Platform]
| |
| 1. Receives request | 2. Processes request, validates
| 2. Validates input | 3. Sends MMS via carrier networks
| 3. Uses Plivo SDK to call Plivo's API |
| 4. Returns response (success/failure) |
V V
[Client Application] [Recipient's Mobile Device]
| |
| Receives API response | Receives MMS messagePrerequisites:
- Node.js and npm (or yarn) – Install on your system. Verify with
node -vandnpm -v. Compatible with Node.js versions 5.5 and higher per the Plivo SDK documentation. Learn more about E.164 phone number formatting for international compliance. - Plivo Account – Sign up for a free Plivo trial account if you don't have one.
- Plivo Auth ID and Auth Token – Find these on the overview page of your Plivo console after signing up.
- MMS-Enabled Plivo Phone Number – You need a US or Canadian Plivo number (long code, toll-free, or short code) that supports MMS. Toll-free MMS support was added in July 2020. Check capabilities and purchase numbers in the Plivo console under Phone Numbers > Buy Numbers. Plivo supports MMS only in the US and Canada. If you need 10DLC registration for high-volume messaging, see our guide on 10DLC SMS registration.
- Trial Account Limitations – If using a Plivo trial account, you can only send MMS to phone numbers verified in your Plivo console under Phone Numbers > Sandbox Numbers. Trial accounts require a minimum $25 recharge to upgrade and remove sandbox restrictions. Alphanumeric sender IDs are not supported on trial accounts.
Expected Outcome:
You'll have a functional Node.js application capable of sending MMS messages programmatically – both via a direct script and through a secure, testable API endpoint. You'll understand the key configuration steps, error handling, and best practices for using Plivo's MMS API.
Setting 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 your project:
bashmkdir plivo-mms-sender cd plivo-mms-sender -
Initialize Node.js Project: Create a
package.jsonfile to manage your project's dependencies and scripts:bashnpm init -y -
Install Dependencies: Install the Plivo Node.js SDK, Express framework, and
dotenvfor managing environment variables:bashnpm install plivo express dotenvplivo– Official Plivo library for interacting with their APIexpress– Web server framework for building your API endpointdotenv– Loads environment variables from a.envfile
-
Create Project Structure: Set up the basic file structure:
textplivo-mms-sender/ ├── node_modules/ ├── .env # Stores environment variables (API keys, phone number) – DO NOT COMMIT ├── .gitignore # Specifies intentionally untracked files that Git should ignore ├── send-mms.js # Standalone script for sending MMS ├── app.js # Express application with the API endpoint ├── package.json └── package-lock.json -
Configure Environment Variables (
.env): Create a file named.envin your project root. This file holds your sensitive Plivo credentials and phone number. Never commit this file to version control.dotenv# .env PLIVO_AUTH_ID=YOUR_PLIVO_AUTH_ID PLIVO_AUTH_TOKEN=YOUR_PLIVO_AUTH_TOKEN PLIVO_SENDER_NUMBER=YOUR_MMS_ENABLED_PLIVO_NUMBER- Replace
YOUR_PLIVO_AUTH_IDandYOUR_PLIVO_AUTH_TOKENwith credentials from your Plivo Console dashboard - Replace
YOUR_MMS_ENABLED_PLIVO_NUMBERwith your E.164 formatted Plivo phone number (e.g.,+14155551212)
- Replace
-
Configure
.gitignore: Create a file named.gitignorein your project root. Addnode_modulesand.envto prevent committing them to your Git repository:text# .gitignore node_modules .envWhy
.gitignore? Security and efficiency –node_modulescan be large and easily reinstalled usingnpm install..envcontains sensitive API keys that should never be exposed in your codebase history.
Your project environment is ready for implementation.
Implementing MMS Sending with Plivo SDK
Create a simple script to send one MMS message directly using the Plivo SDK. This helps verify your credentials and Plivo number setup.
-
Create the Sending Script (
send-mms.js): Create the filesend-mms.jsand add the following code:javascript// send-mms.js require('dotenv').config(); // Load environment variables from .env file const plivo = require('plivo'); // Ensure environment variables are loaded const authId = process.env.PLIVO_AUTH_ID; const authToken = process.env.PLIVO_AUTH_TOKEN; const senderNumber = process.env.PLIVO_SENDER_NUMBER; if (!authId || !authToken || !senderNumber) { console.error('Error: Plivo credentials or sender number not found in .env file.'); process.exit(1); // Exit if credentials are missing } // --- Configuration --- // IMPORTANT: Replace with the recipient's phone number in E.164 format. // If using a Plivo trial account, this MUST be a number verified // in your Plivo Console under Phone Numbers > Sandbox Numbers. const recipientNumber = '+14155551234'; // Example - CHANGE THIS to a valid recipient number // Replace with the URL of the media file you want to send (must be publicly accessible) const mediaUrl = 'https://media.giphy.com/media/26gscSULUcfKU7dHq/source.gif'; // Example GIF - CHANGE THIS if needed // The text content of your message const messageText = 'Hello from Node.js with Plivo MMS!'; // --- End Configuration --- // Create a Plivo client instance const client = new plivo.Client(authId, authToken); console.log(`Attempting to send MMS from ${senderNumber} to ${recipientNumber}...`); // Use the client to send the message client.messages.create({ src: senderNumber, // Your Plivo phone number (must be MMS enabled) dst: recipientNumber, // The destination phone number text: messageText, // The text part of the message type: 'mms', // Specify message type as MMS media_urls: [mediaUrl] // Array of publicly accessible URLs for media files // You can also use media_ids if you've uploaded media to Plivo: // media_ids: ['YOUR_UPLOADED_MEDIA_ID'] }) .then(function(message_created) { console.log('MMS Sent Successfully!'); console.log('Message UUID:', message_created.messageUuid[0]); // Plivo returns UUIDs in an array console.log('API Response:', message_created); }) .catch(function(error) { console.error('Error sending MMS:', error); }); -
Explanation:
require('dotenv').config();loads the variables from your.envfile intoprocess.env- Credential Check: Basic validation ensures the script doesn't run without necessary credentials
- Configuration: Clearly defined variables for recipient number, media URL, and text. Change
recipientNumberto a valid target number before running. If using a trial account, ensure it's a verified sandbox number. new plivo.Client()initializes the connection to the Plivo API using your Auth ID and Tokenclient.messages.create()is the core function call:src: Your MMS-enabled Plivo number (from.env)dst: The recipient's numbertext: The message bodytype: 'mms': Crucial for sending MMS. Without this, it defaults to SMS.media_urls: An array containing one or more publicly accessible URLs pointing to the media files (images, GIFs, videos, audio). Plivo fetches the media from these URLs. Ensure the URLs are valid and accessible.
.then()handles the successful API response from Plivo, typically containing message UUIDs and status information.catch()catches and logs any errors during the API call (e.g., invalid credentials, invalid number format, inaccessible media URL)
-
Run the Script: Execute the script from your terminal:
bashnode send-mms.js -
Verification:
- Check your terminal for the "MMS Sent Successfully!" message and the response details from Plivo
- Check the recipient's phone – they should receive the MMS message shortly
- Check the Plivo Console under Logs > Messaging Logs for the status of the sent message
- If you encounter errors, check the console output and refer to the "Troubleshooting" section below. Common issues include incorrect credentials, non-verified sandbox numbers (for trial accounts), invalid recipient number format (use E.164:
+1…), or inaccessiblemedia_urls.
Building an Express API Endpoint for MMS
While the script is useful for testing, a more practical approach is to create an API endpoint that other services or frontends can call to send MMS messages.
-
Create the Express App (
app.js): Create the fileapp.jsand add the following code:javascript// app.js require('dotenv').config(); const express = require('express'); const plivo = require('plivo'); const app = express(); const port = process.env.PORT || 3000; // Use environment variable for port or default to 3000 // Middleware to parse JSON bodies app.use(express.json()); // Middleware to parse URL-encoded bodies (often used by HTML forms) app.use(express.urlencoded({ extended: true })); // --- Plivo Configuration --- const authId = process.env.PLIVO_AUTH_ID; const authToken = process.env.PLIVO_AUTH_TOKEN; const senderNumber = process.env.PLIVO_SENDER_NUMBER; if (!authId || !authToken || !senderNumber) { console.error('CRITICAL ERROR: Plivo credentials or sender number not found in .env file. API cannot start.'); process.exit(1); // Prevent server start if config is missing } const plivoClient = new plivo.Client(authId, authToken); // --- End Plivo Configuration --- // --- API Endpoint: POST /send-mms --- app.post('/send-mms', async (req, res) => { const { recipientNumber, messageText, mediaUrl } = req.body; // --- Basic Input Validation --- if (!recipientNumber || !messageText || !mediaUrl) { return res.status(400).json({ error: 'Missing required fields: recipientNumber, messageText, mediaUrl', }); } // Basic E.164 format check (improves reliability but not foolproof) // Consider libraries like 'libphonenumber-js' for robust validation in production. if (!/^\+[1-9]\d{1,14}$/.test(recipientNumber)) { return res.status(400).json({ error: 'Invalid recipientNumber format. Use E.164 format (e.g., +14155551212).', }); } // Basic URL validation try { new URL(mediaUrl); } catch (_) { return res.status(400).json({ error: 'Invalid mediaUrl format.' }); } // --- End Basic Input Validation --- console.log(`API Request: Send MMS from ${senderNumber} to ${recipientNumber}`); try { // This implementation expects a single mediaUrl from the request body // and passes it as a single-element array to Plivo. const response = await plivoClient.messages.create({ src: senderNumber, dst: recipientNumber, text: messageText, type: 'mms', media_urls: [mediaUrl], // Expecting a single URL for simplicity here }); console.log('Plivo API Success:', response); res.status(200).json({ message: 'MMS sent successfully.', messageUuid: response.messageUuid[0], // Extract the UUID plivoResponse: response, }); } catch (error) { console.error('Plivo API Error:', error); // Provide more specific feedback if possible let statusCode = 500; let errorMessage = 'Failed to send MMS due to an internal server error.'; if (error.statusCode) { // Use Plivo's status code if available (e.g., 400 Bad Request, 401 Unauthorized) statusCode = error.statusCode; errorMessage = error.message || 'Plivo API request failed.'; } res.status(statusCode).json({ error: errorMessage, details: error.message, // Include Plivo's error message if helpful }); } }); // --- Health Check Endpoint --- app.get('/health', (req, res) => { res.status(200).json({ status: 'UP', timestamp: new Date().toISOString() }); }); // --- Start Server --- app.listen(port, () => { console.log(`MMS Sender API listening on port ${port}`); console.log(`Plivo Sender Number: ${senderNumber}`); if (process.env.NODE_ENV !== 'production') { console.log(`\nTest endpoint locally using curl (replace placeholders!):\n`); console.log(`curl -X POST http://localhost:${port}/send-mms -H "Content-Type: application/json" -d '{"recipientNumber": "+1...", "messageText": "API Test", "mediaUrl": "https://..."}'\n`); } }); -
Explanation:
- Dependencies: Imports
expressandplivo, loads.env - Middleware:
express.json()andexpress.urlencoded()are essential for parsing incoming request bodies (JSON and form data) - Plivo Client: The client is initialized once when the app starts
/send-mmsEndpoint (POST):- Defines a route that listens for
POSTrequests at the/send-mmspath - Extracts
recipientNumber,messageText, andmediaUrlfrom the request body (req.body) - Input Validation: Performs basic checks: presence of required fields, basic E.164 format for the number, and basic URL validity. The E.164 regex (
^\+[1-9]\d{1,14}$) is a basic check; while helpful, it might allow technically invalid numbers (e.g., incorrect length for a country). For production, use a dedicated library likelibphonenumber-jsfor robust phone number validation. mediaUrlHandling: This implementation expects a singlemediaUrlfield in the request body. It then wraps this URL in an array ([mediaUrl]) as required by the Plivo API'smedia_urlsparameter. Modify the API to accept an array of URLs directly if needed.- Async/Await: Uses
async/awaitfor cleaner handling of the asynchronous Plivo API call - Plivo Call: Calls
plivoClient.messages.createwithin atry…catchblock - Success Response (200): If the Plivo API call succeeds (doesn't throw an error), it sends back a JSON response confirming initiation and includes the message UUID
- Error Response (400/500): If validation fails (400) or the Plivo API call throws an error (usually 500, but uses Plivo's status code if available), it logs the error and sends back a JSON error response
- Defines a route that listens for
/healthEndpoint (GET): A simple endpoint used for monitoring to check if the service is runningapp.listen(): Starts the Express server on the specified port and provides a samplecurlcommand for local testing
- Dependencies: Imports
-
Run the API Server: Execute the app from your terminal:
bashnode app.jsYou should see the message "MMS Sender API listening on port 3000" and the sample
curlcommand. -
Test the API Endpoint: Use
curl(or tools like Postman or Insomnia) to send a POST request to your running server. Open a new terminal window (leave the server running in the first one).IMPORTANT: Replace the placeholder values below (
+14155551234and themediaUrl) with a valid recipient number (remember the sandbox verification requirement if using a Plivo trial account) and a working, publicly accessible media URL.bashcurl -X POST http://localhost:3000/send-mms \ -H "Content-Type: application/json" \ -d '{ "recipientNumber": "+14155551234", "messageText": "Testing MMS from my API!", "mediaUrl": "https://media.giphy.com/media/3o7TKS6AWgP3FpO2LS/giphy.gif" }' -
Verification:
- API Response: You should receive a JSON response in your terminal like:
json
{ "message": "MMS sent successfully.", "messageUuid": "some-uuid-string-from-plivo", "plivoResponse": { ... detailed Plivo response ...} } - Server Logs: Check the terminal where
node app.jsis running for log messages - Recipient Phone: The MMS should arrive on the recipient's device
- Plivo Console: Check the Messaging Logs
- Error Testing: Try sending requests with missing fields, invalid numbers, or invalid URLs to see the error responses (e.g., 400 Bad Request)
- API Response: You should receive a JSON response in your terminal like:
Plivo API Authentication and Configuration
You've already used the Plivo credentials. Here's where to find them and how they work.
-
Auth ID and Auth Token:
- Purpose: These act like your username and password for the Plivo API. They authenticate your requests.
- How to Obtain: Log in to your Plivo Console. They are prominently displayed on the main Dashboard/Overview page.
- Secure Storage: Store these in environment variables (
.envlocally, secure configuration management in production) and never hardcode them directly into your source code. Usedotenvlocally and your deployment platform's environment variable system in production.
-
MMS-Enabled Plivo Number (
src):- Purpose: This is the phone number from which your MMS messages will appear to be sent. It must be capable of sending MMS messages in the US and Canada.
- How to Obtain/Verify:
- Go to Phone Numbers > Your Numbers in the Plivo Console
- Check the "Capabilities" column for your existing numbers. Look for "MMS"
- If you need a new number, go to Phone Numbers > Buy Numbers. Filter by "MMS" capability and select a US or Canadian number (Long Code or Toll-Free).
- Note: Toll-free numbers may require verification for messaging. Follow Plivo's guidelines. As of January 31, 2024, unverified toll-free numbers may have messages blocked.
- Format: Use the E.164 format (e.g.,
+14155551212) - Storage: Store this in your
.envfile asPLIVO_SENDER_NUMBER
-
Media URLs (
media_urls):- Purpose: Plivo needs publicly accessible URLs to fetch the media files (images, videos, audio, GIFs) you want to include in the MMS.
- Requirements:
- Must be publicly accessible (not behind firewalls or login pages)
- URLs must return proper
content-typeandcontent-lengthresponse headers, otherwise Plivo will reject the request - Supported Formats: Plivo fully supports and formats JPEG, PNG, and GIF images for device compatibility. Additional formats (various image, video, and audio types) are accepted but not formatted for destination device compatibility. See the full list of supported MIME types.
- Size Limits:
- Maximum 10 attachments (combined
media_urlsandmedia_ids) - Maximum 2 MB per attachment
- Total message size (text + all attachments) must be less than 5 MB
- Message body text: up to 1,600 characters (approximately 4.8 KB)
- Carrier Recommendations: For US carriers, use attachments no larger than 600 KB for non-JPEG/PNG/GIF files. For Canadian carriers, keep attachments under 1 MB.
- Error: Messages exceeding 5 MB total size will fail with Plivo error code 120.
- Maximum 10 attachments (combined
- URLs should be stable and remain accessible during message processing
- Alternative (
media_ids): Upload media directly to Plivo via their console (Messaging > MMS Media Upload) or API. Uploaded media gets amedia_id. You can then usemedia_ids: ['YOUR_MEDIA_ID']instead ofmedia_urls. This can be useful for frequently used media or if you don't have a public hosting location. The same size limits apply (2 MB per media, 5 MB total).
-
Plivo Console Dashboard: Familiarize yourself with:
- Dashboard: Auth ID/Token, account balance
- Messaging > Logs: Check the status, content, and any errors for sent/received messages. Indispensable for debugging.
- Phone Numbers > Your Numbers / Buy Numbers: Manage your Plivo numbers. Verify MMS capability is enabled.
- Phone Numbers > Sandbox Numbers: Verify recipient numbers for testing during a trial (required for trial accounts)
- Messaging > MMS Media Upload: Manage pre-uploaded media files
MMS Error Handling and Retry Logic
Robust applications need solid error handling and logging.
-
Error Handling Strategy:
- API Level: Use
try…catchblocks around asynchronous operations like Plivo API calls - Validation: Catch invalid inputs early (as shown in
app.js) and return clear4xxerror responses - Plivo Errors: The Plivo SDK throws errors that often contain useful information, including Plivo-specific error messages and sometimes HTTP status codes. Catch these errors and log them. Return appropriate HTTP status codes (
5xxfor server/Plivo issues,4xxfor client errors) and informative JSON error messages to the API caller. - Network Issues: Network problems between your server and Plivo can occur. Ensure your
catchblocks handle generic network errors too.
- API Level: Use
-
Logging:
- Basic Logging:
console.logandconsole.errorare sufficient for simple cases and development - Production Logging: For production, use a dedicated logging library like
winstonorpino. These offer:- Log Levels: (debug, info, warn, error) – Filter logs based on severity
- Structured Logging: Output logs in JSON format for easier parsing by log management systems (like Datadog, Splunk, ELK stack)
- Transports: Send logs to files, databases, or external logging services
- What to Log:
- Incoming API requests (excluding sensitive data)
- Key parameters used in Plivo calls (sender, recipient, media URL type)
- Successful Plivo API responses (especially message UUIDs)
- Detailed error information when Plivo calls fail (stack traces, error messages, Plivo status codes)
- Validation failures
Example using
console(adapt for libraries):javascript// Inside the /send-mms route console.info(`[INFO] Received request to send MMS to ${recipientNumber}`); // ... validation ... try { // ... plivo call ... const response = await plivoClient.messages.create({ /* ... params ... */ }); console.info(`[SUCCESS] Plivo API call successful for ${recipientNumber}. UUID: ${response.messageUuid[0]}`); res.status(200).json(/* ... */); } catch (error) { console.error(`[ERROR] Plivo API call failed for ${recipientNumber}. Status: ${error.statusCode || 'N/A'}, Message: ${error.message}`, error); // Log full error object too // Determine statusCode based on error const statusCode = error.statusCode && error.statusCode >= 400 && error.statusCode < 500 ? error.statusCode : 500; res.status(statusCode).json(/* ... */); } - Basic Logging:
-
Retry Mechanisms:
- Why: Transient network issues or temporary Plivo outages might cause API calls to fail. Retrying can improve reliability.
- Strategy: Implement exponential backoff. If a request fails, wait a short period (e.g., 1 second), retry. If it fails again, wait longer (e.g., 2 seconds), retry. Increase the delay exponentially up to a maximum number of retries.
- Implementation: Libraries like
async-retryorp-retrycan simplify this. Be cautious about retrying errors that are clearly not transient (e.g., 401 Unauthorized, 400 Bad Request due to invalid number format). Only retry on likely temporary issues (e.g., 5xx errors, network timeouts).
Conceptual example (without a library):
javascriptasync function sendMmsWithRetry(params, retries = 3, delay = 1000) { try { return await plivoClient.messages.create(params); } catch (error) { // Only retry on specific error types (e.g., network or 5xx) // Example condition: retry on network errors or Plivo server errors (5xx) const shouldRetry = !error.statusCode || error.statusCode >= 500 || (error.code && ['ECONNRESET', 'ETIMEDOUT', 'ENETUNREACH'].includes(error.code)); if (retries > 0 && shouldRetry) { console.warn(`[RETRY] Plivo call failed, retrying in ${delay}ms... (${retries} retries left)`); await new Promise(resolve => setTimeout(resolve, delay)); // Exponential backoff: double the delay for the next retry return sendMmsWithRetry(params, retries - 1, delay * 2); } else { console.error(`[FAIL] Plivo call failed after retries or due to non-retryable error.`); throw error; // Re-throw the error if retries exhausted or not retryable } } } // In your API route: // try { // const response = await sendMmsWithRetry({ /* Plivo params */ }); // // Handle success // } catch (error) { // // Handle final failure // }
Tracking MMS Status with a Database
While your simple API doesn't require a database, a production system often benefits from one for:
- Tracking Message Status: Store the
messageUuidreturned by Plivo and later update its status (sent, delivered, failed) using Plivo's message status callbacks (webhooks) - Auditing and History: Keep a log of all MMS messages sent, including recipient, content (or reference), timestamp, and status
- User Data: Associate MMS messages with specific users in your application
- Rate Limiting/Analytics: Store usage data
If adding a database (e.g., PostgreSQL with Prisma):
-
Schema Design (Conceptual
schema.prisma):prisma// schema.prisma datasource db { provider = "postgresql" // or mysql, sqlite, sqlserver, mongodb url = env("DATABASE_URL") } generator client { provider = "prisma-client-js" } model MmsMessage { id String @id @default(cuid()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt plivoMessageUuid String? @unique // Store the UUID returned by Plivo senderNumber String // Your Plivo number used recipientNumber String // The destination number messageText String? mediaUrl String? mediaId String? // If using Plivo media upload status String @default("initiated") // e.g., initiated, queued, sent, delivered, failed, undelivered plivoStatus String? // Store the status from Plivo callback errorCode String? // Store Plivo error code on failure // Optional: Link to a User model if applicable // userId String? // user User? @relation(fields: [userId], references: [id]) @@index([recipientNumber]) @@index([plivoMessageUuid]) @@index([status]) } // model User { ... } // If needed -
Data Access: Use an ORM like Prisma or Sequelize to interact with the database, providing type safety and simplifying queries. Your API endpoint would first save a record with
status: 'initiated'and then update it based on the Plivo API response or subsequent status callbacks. -
Migrations: Use the ORM's migration tools (e.g.,
prisma migrate dev,sequelize db:migrate) to manage schema changes safely.
This section is conceptual. Implementing a full database layer is beyond the scope of this specific MMS sending guide but is a common next step for production systems.
Security Best Practices for MMS APIs
Secure your API endpoint.
-
Input Validation and Sanitization:
- Validation: You added basic checks. Use robust libraries (
joi,express-validator,libphonenumber-js) to enforce strict rules onrecipientNumber(valid E.164 format),messageText(length limits, character types), andmediaUrl(valid URL format, perhaps restricting domains). - Sanitization: While less critical for API parameters passed directly to Plivo, if you were embedding user input into
messageTextthat might be displayed elsewhere, use libraries likedompurify(for HTML) or ensure proper escaping to prevent cross-site scripting (XSS). Plivo handles the SMS/MMS encoding.
- Validation: You added basic checks. Use robust libraries (
-
Authentication/Authorization:
- Your current API is open. In production, protect it.
- API Keys: Issue unique API keys to trusted clients. Clients include the key in a header (e.g.,
Authorization: Bearer YOUR_API_KEYorX-API-Key: YOUR_API_KEY). Your Express app verifies the key against a stored list/database before processing the request. - JWT/OAuth: For user-centric applications, use standard authentication flows like JSON Web Tokens or OAuth.
-
Rate Limiting:
- Prevent abuse and control costs by limiting how many requests a client can make in a given time window.
- Use middleware like
express-rate-limit. Configure it based on IP address or API key. - Plivo has account-level and phone number-level rate limits for MMS.
Example using
express-rate-limit:bashnpm install express-rate-limitjavascript// app.js const rateLimit = require('express-rate-limit'); const apiLimiter = 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', standardHeaders: true, // Return rate limit info in the `RateLimit-*` headers legacyHeaders: false, // Disable the `X-RateLimit-*` headers }); // Apply the rate limiting middleware to API routes // Apply it before your main route handler for /send-mms app.use('/send-mms', apiLimiter); // ... rest of your app.js, including the app.post('/send-mms', ...) route ... -
HTTPS: Always use HTTPS in production to encrypt data in transit. Deployment platforms like Heroku or using a reverse proxy like Nginx typically handle TLS/SSL termination.
-
Environment Variables: Keep sensitive data (API keys, Plivo Auth tokens) out of your code using environment variables. Ensure your
.envfile is in.gitignore. For production, do not deploy the.envfile. Instead, use your hosting platform's built-in environment variable configuration (e.g., Heroku Config Vars, AWS Parameter Store, Azure App Configuration) or a dedicated secrets management service (e.g., AWS Secrets Manager, HashiCorp Vault). For related SMS implementations, check out our guides on basic SMS sending with Plivo and two-way messaging.
Frequently Asked Questions
What is the maximum file size for MMS attachments with Plivo?
Plivo supports a maximum of 2 MB per attachment with up to 10 attachments per message. The total message size (text + all attachments) must be less than 5 MB. Messages exceeding 5 MB will fail with error code 120. For optimal carrier compatibility, keep attachments under 600 KB for US carriers and under 1 MB for Canadian carriers.
Can I send MMS messages internationally with Plivo?
No. Plivo MMS is only available for US and Canadian phone numbers. You need a US or Canadian Plivo number to send MMS, and recipients must also be in the US or Canada. For international messaging, consider using SMS or other messaging channels like WhatsApp.
How do I send MMS from a Plivo trial account?
Trial accounts can only send MMS to verified sandbox numbers. Add recipient numbers in the Plivo Console under Phone Numbers > Sandbox Numbers. Trial accounts cannot use alphanumeric sender IDs and require a minimum $25 recharge to upgrade and remove restrictions.
What media formats does Plivo MMS support?
Plivo fully supports and formats JPEG, PNG, and GIF images for device compatibility. Additional formats (various image, video, and audio types) are accepted but not automatically formatted for destination devices. See the complete list of supported MIME types. Always test with your target carriers to ensure compatibility.
How do I handle MMS delivery status in Node.js?
Implement webhook endpoints to receive Plivo delivery status callbacks. Configure the callback URL in your Plivo Console under message settings or use the url parameter when sending messages via the Send Message API. Your Express app should handle POST requests containing status updates (queued, sent, delivered, failed) and store them in your database using the message UUID.
Can I send the same media file to multiple recipients?
Yes. Upload media to Plivo using Messaging > MMS Media Upload in the console or via the Upload Media API. You'll receive a media_id that you can reuse across multiple messages without re-uploading. This approach is more efficient than using media_urls for frequently sent media.
What's the difference between media_urls and media_ids?
media_urls are publicly accessible URLs that Plivo fetches when sending the MMS. media_ids refer to media files you've pre-uploaded to Plivo's servers. Use media_ids for frequently used media or when you don't have public hosting. Both methods support the same file size limits (2 MB per file, 5 MB total).
How do I test MMS sending locally in development?
Run your Express server locally with node app.js, then use curl or Postman to send POST requests to http://localhost:3000/send-mms. Ensure your Plivo credentials are in .env and recipient numbers are verified in sandbox (for trial accounts). Check the Plivo Console logs for detailed delivery information.
Why is my MMS failing with error code 120?
Error code 120 indicates your message exceeds the 5 MB total size limit. Check that each attachment is under 2 MB and the combined size of all attachments plus text is under 5 MB. Consider compressing images or videos before sending, or split content across multiple messages.
Can toll-free numbers send MMS with Plivo?
Yes. Plivo added MMS support for toll-free numbers in July 2020. However, as of January 31, 2024, unverified toll-free numbers may have messages blocked. Verify MMS capability and toll-free verification status in the Plivo Console under Phone Numbers > Your Numbers before sending.