This guide provides a step-by-step walkthrough for building a production-ready Node.js application using the Express framework to send Multimedia Messaging Service (MMS) messages via the Vonage Messages API.
We will cover everything from initial project setup and Vonage configuration to implementing the core sending logic, handling errors, securing credentials, and preparing for deployment.
Project Overview and Goals
What We're Building:
A simple Node.js web server using Express that exposes an API endpoint. When this endpoint receives a request containing a recipient phone number, a sender number (your Vonage number), an image URL, and an optional caption, it uses the Vonage Messages API to send an MMS message.
Problem Solved:
This guide enables developers to programmatically send rich media content (images) directly to users' mobile devices within the US, enhancing communication beyond simple text messages. This is crucial for use cases like sending product images, event flyers, visual alerts, or personalized media.
Technologies Used:
- Node.js: A JavaScript runtime environment ideal for building efficient I/O-bound applications like web servers and APIs.
- Express: A minimal and flexible Node.js web application framework that simplifies building APIs and handling HTTP requests.
- Vonage Messages API: A powerful Vonage API that allows sending messages across various channels, including SMS and MMS, using a unified interface. We'll use it specifically for MMS.
@vonage/server-sdk
: The official Vonage Server SDK for Node.js, simplifying interaction with Vonage APIs.dotenv
: A module to load environment variables from a.env
file intoprocess.env
, keeping sensitive credentials out of source code.ngrok
(for development): A tool to expose your local development server to the internet, necessary for receiving webhook callbacks from Vonage (like message status updates).
System Architecture:
A simplified view of the interaction:
+-------------+ +------------------------+ +----------------+ +-----------------+ +-----------------+
| HTTP Client | ----> | Node.js/Express Server | ----> | Vonage SDK | ----> | Vonage Messages | ----> | Recipient Phone |
| (e.g., curl)| | (API Endpoint) | | (@vonage/server| | API | | (US Mobile) |
+-------------+ +------------------------+ +----------------+ +-----------------+ +-----------------+
| ^
| | (Status Webhook)
+---------------------------------------------------------+
(Receives optional status updates via webhook endpoint)
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. (Sign up for Vonage)
- MMS-Capable US Vonage Number: You need a US-based virtual number from Vonage that supports both SMS and MMS. You can purchase one via the Vonage dashboard (
Numbers
>Buy Numbers
). Note: MMS via Vonage is currently restricted to sending from US numbers (10DLC, Toll-Free, Short Code) to US destinations for Application-to-Person (A2P) use cases. ngrok
(Recommended for Development): For exposing your local server to receive status webhooks. (Download ngrok)- Basic understanding of JavaScript, Node.js, REST APIs, and terminal commands.
Final Outcome:
By the end of this guide, you will have a functional Express application capable of sending MMS messages via a secure API endpoint, complete with basic error handling and configuration management using environment variables.
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, then navigate into it.
mkdir vonage-mms-sender cd vonage-mms-sender
-
Initialize Node.js Project: Use
npm
to create apackage.json
file. The-y
flag accepts the default settings.npm init -y
-
Install Dependencies: Install Express, the Vonage Server SDK, and
dotenv
.npm install express @vonage/server-sdk dotenv
express
: Web framework.@vonage/server-sdk
: Vonage API client library.dotenv
: Loads environment variables from a.env
file.
-
Enable ES Modules (Optional but Recommended): To use modern
import
/export
syntax, open yourpackage.json
file and add the following line at the top level:// package.json { ""name"": ""vonage-mms-sender"", ""version"": ""1.0.0"", ""description"": """", ""main"": ""index.js"", ""type"": ""module"", ""scripts"": { ""start"": ""node index.js"", ""dev"": ""node --watch index.js"" }, ""keywords"": [], ""author"": """", ""license"": ""ISC"", ""dependencies"": { ""@vonage/server-sdk"": ""^3.x.x"", ""dotenv"": ""^16.x.x"", ""express"": ""^4.x.x"" } }
(Adjust version numbers based on what
npm install
added). If you prefer CommonJS (require
), omit the""type"": ""module""
line and userequire
syntax throughout the code. This guide will use ES Modules syntax. -
Create Project Files: Create the main application file and the environment file.
touch index.js .env .gitignore
-
Configure
.gitignore
: Addnode_modules
and your.env
file to.gitignore
to prevent committing them to version control. This is crucial for security.# .gitignore # Dependencies node_modules/ # Environment variables .env # Vonage Private Key (if stored in project) private.key *.key # Logs *.log # OS generated files .DS_Store Thumbs.db
-
Project Structure: Your basic structure should now look like this:
vonage-mms-sender/ ├── node_modules/ ├── .env ├── .gitignore ├── index.js └── package.json
This foundational setup provides a clean structure and installs the necessary tools for building our MMS sending application.
2. Implementing Core Functionality (Sending MMS)
Now, let's write the core logic to interact with the Vonage SDK and send an MMS message. We'll encapsulate this in a reusable function.
-
Import Dependencies and Load Environment Variables: Open
index.js
and add the necessary imports. We usedotenv/config
to load variables immediately.// index.js import 'dotenv/config'; // Load .env variables immediately import { Vonage } from '@vonage/server-sdk'; import path from 'path'; // Needed for resolving private key path // --- Environment Variable Validation (Optional but Recommended) --- const requiredEnvVars = [ 'VONAGE_APPLICATION_ID', 'VONAGE_PRIVATE_KEY_PATH', 'VONAGE_MMS_NUMBER', // Your Vonage MMS-capable number ]; const missingEnvVars = requiredEnvVars.filter(varName => !process.env[varName]); if (missingEnvVars.length > 0) { console.error(`Error: Missing required environment variables: ${missingEnvVars.join(', ')}`); console.error('Please check your .env file.'); process.exit(1); // Exit if critical configuration is missing } // --- End Environment Variable Validation --- // --- Vonage Client Initialization --- const vonage = new Vonage({ applicationId: process.env.VONAGE_APPLICATION_ID, privateKey: path.resolve(process.env.VONAGE_PRIVATE_KEY_PATH) // Use path.resolve for robustness }, { // Optional: Custom settings like timeouts or appending user agent // appendUserAgent: 'my-mms-app/1.0.0' }); const messagesClient = vonage.messages; // Access the Messages client // --- End Vonage Client Initialization --- /** * Sends an MMS message using the Vonage Messages API. * * @param {string} to - The recipient phone number (E.164 format, e.g., +14155550100). * @param {string} from - Your Vonage MMS-capable number (E.164 format). * @param {string} imageUrl - Publicly accessible URL of the image to send. * @param {string} [caption] - Optional caption for the image. * @returns {Promise<object>} - Promise resolving with the API response or rejecting with an error. */ async function sendMmsMessage(to, from, imageUrl, caption = '') { console.log(`Attempting to send MMS from ${from} to ${to} with image: ${imageUrl}`); // Input validation (basic) if (!to || !from || !imageUrl) { throw new Error('Missing required parameters: to, from, or imageUrl'); } // Add more robust validation (e.g., E.164 format check, URL validation) in production try { const resp = await messagesClient.send({ message_type: 'image', // Specify message type as image for MMS to: to, from: from, channel: 'mms', // Specify channel as MMS image: { url: imageUrl, caption: caption // Include caption if provided }, // Optional: Client reference for tracking // client_ref: `my-mms-ref-${Date.now()}` }); console.log('MMS Submitted Successfully:'); console.log(`Message UUID: ${resp.message_uuid}`); return resp; // Return the success response } catch (err) { console.error('Error sending MMS:', err.response ? err.response.data : err.message); // Throw a more specific error or the original error throw err; // Re-throw the error for handling upstream } } // --- Placeholder for Express server setup (will add in next step) --- console.log('Core MMS sending logic initialized.'); // --- End Placeholder --- // Example usage (for direct testing, uncomment and ensure TEST_RECIPIENT_NUMBER is set in .env) /* if (process.env.TEST_RECIPIENT_NUMBER) { sendMmsMessage( process.env.TEST_RECIPIENT_NUMBER, process.env.VONAGE_MMS_NUMBER, 'https://placekitten.com/200/300', // Example image URL 'Hello from Vonage MMS!' ).catch(err => console.error('Standalone test failed:', err)); } */
-
Explanation:
- We import necessary modules, including
dotenv/config
to load environment variables right away. - Basic environment variable validation is added to catch configuration errors early.
- We initialize the
Vonage
client using theapplicationId
andprivateKey
path obtained from environment variables.path.resolve
ensures the path works correctly regardless of where the script is run from. - We access the
messages
client specifically (vonage.messages
). - The
sendMmsMessage
function takesto
,from
,imageUrl
, and an optionalcaption
. - Inside the function, basic validation checks for required parameters.
- We call
messagesClient.send()
with the specific structure required for MMS:message_type: 'image'
channel: 'mms'
image: { url: ..., caption: ... }
- We use
async/await
for cleaner asynchronous code. - A
try...catch
block handles potential errors during the API call, logging details and re-throwing the error. - Logging provides visibility into the sending attempt and success/failure.
- A commented-out example shows how you could test this function directly if needed.
- We import necessary modules, including
This core function encapsulates the interaction with Vonage for sending MMS, making it easy to integrate into our API layer.
3. Building the API Layer with Express
Now, let's create an Express server and define an API endpoint to trigger our sendMmsMessage
function.
-
Set up Express Server: Add the following code to
index.js
, replacing the placeholder comments.// index.js // ... (Keep imports, validation, Vonage init, and sendMmsMessage function from Step 2) ... import express from 'express'; // --- Express App Setup --- const app = express(); const PORT = process.env.PORT || 3000; // Use port from .env or default to 3000 // Middleware app.use(express.json()); // Parse JSON request bodies app.use(express.urlencoded({ extended: true })); // Parse URL-encoded request bodies // Basic logging middleware (optional) app.use((req, res, next) => { console.log(`${new Date().toISOString()} - ${req.method} ${req.path}`); next(); }); // --- End Express App Setup --- // --- API Endpoints --- // Health check endpoint app.get('/health', (req, res) => { res.status(200).json({ status: 'ok', timestamp: new Date().toISOString() }); }); // POST endpoint to send MMS app.post('/send-mms', async (req, res) => { const { to, imageUrl, caption } = req.body; const from = process.env.VONAGE_MMS_NUMBER; // Use the configured Vonage number // --- Request Validation --- if (!to || !imageUrl) { console.error('Validation Error: Missing ""to"" or ""imageUrl"" in request body'); return res.status(400).json({ success: false, message: 'Missing required fields: ""to"" and ""imageUrl"".' }); } // Basic phone number format check (improve as needed) // Note: This regex is basic and checks for a plausible E.164-like format, // but doesn't guarantee the number is actually valid or routable. // For production, consider a more robust library like 'libphonenumber-js'. if (!/^\+?[1-9]\d{1,14}$/.test(to)) { console.error(`Validation Error: Invalid 'to' number format: ${to}`); return res.status(400).json({ success: false, message: 'Invalid ""to"" phone number format. Please use E.164 format (e.g., +14155550100).' }); } // Basic URL format check (improve as needed) try { new URL(imageUrl); } catch (_) { console.error(`Validation Error: Invalid 'imageUrl' format: ${imageUrl}`); return res.status(400).json({ success: false, message: 'Invalid ""imageUrl"" format. Please provide a valid URL.' }); } // --- End Request Validation --- try { const result = await sendMmsMessage(to, from, imageUrl, caption); console.log(`MMS request processed successfully for ${to}. Message UUID: ${result.message_uuid}`); res.status(202).json({ // 202 Accepted: Request received, processing initiated success: true, message: 'MMS sending request accepted.', message_uuid: result.message_uuid }); } catch (error) { console.error(`API Error sending MMS to ${to}:`, error.message); // Provide a generic error message to the client for security res.status(500).json({ success: false, message: 'Failed to send MMS due to an internal server error.' // Optionally include an error code or reference for tracking // error_ref: 'some-unique-id' }); } }); // --- Webhook Endpoint for Status Updates --- // This endpoint will receive delivery receipts from Vonage app.post('/webhooks/status', (req, res) => { console.log('--- Status Webhook Received ---'); console.log('Body:', JSON.stringify(req.body, null, 2)); // Log the full status payload // Add logic here to process the status update (e.g., update database) // Example: Check for 'delivered', 'failed', 'rejected' status const { message_uuid, status, timestamp, error } = req.body; if (message_uuid && status) { console.log(`Status for ${message_uuid}: ${status} at ${timestamp}`); if (status === 'failed' || status === 'rejected') { console.error(`MMS Delivery Failed/Rejected: ${message_uuid}`, error || 'No error details provided'); } } res.status(200).send('OK'); // Important: Respond with 200 OK quickly }); // --- End Webhook Endpoint --- // --- End API Endpoints --- // --- Start Server --- app.listen(PORT, () => { console.log(`Server listening on port ${PORT}`); console.log(`API Endpoint: POST http://localhost:${PORT}/send-mms`); console.log(`Status Webhook: POST http://localhost:${PORT}/webhooks/status`); console.log(`Health Check: GET http://localhost:${PORT}/health`); }); // --- End Start Server ---
-
Explanation:
- We import
express
and create an app instance. - We define the
PORT
using an environment variable or defaulting to 3000. - Essential middleware (
express.json
,express.urlencoded
) is added to parse incoming request bodies. - A simple logging middleware shows basic request information.
- A
/health
endpoint is added for basic service monitoring. - The
/send-mms
endpoint is aPOST
route:- It extracts
to
,imageUrl
, andcaption
from thereq.body
. - It retrieves the
from
number directly from the environment variable. - Request Validation: It performs checks for required fields and basic format validation for the phone number (with added note about limitations) and URL. Send appropriate 400 Bad Request responses on failure.
- It calls our
sendMmsMessage
function within atry...catch
block. - Success Response: On success, it returns a
202 Accepted
status (as sending is asynchronous) along with themessage_uuid
. - Error Response: On failure, it logs the detailed error internally and returns a generic
500 Internal Server Error
response to the client.
- It extracts
- A
/webhooks/status
endpoint is added to receive delivery status updates from Vonage. It logs the incoming payload and sends back a200 OK
immediately. This endpoint is crucial for tracking message delivery. - Finally,
app.listen
starts the server.
- We import
-
Testing the API Endpoint:
- You'll need your Vonage credentials set up first (see next section).
- Run the server:
npm start
ornpm run dev
. - Use
curl
or a tool like Postman to send a POST request:
curl -X POST http://localhost:3000/send-mms \ -H ""Content-Type: application/json"" \ -d '{ ""to"": ""+14155550100"", ""imageUrl"": ""https://placekitten.com/g/300/200"", ""caption"": ""Test MMS from Express!"" }'
- Replace
+14155550100
with a valid US test number (whitelisted if on trial). - Expected Success Response (JSON):
{ ""success"": true, ""message"": ""MMS sending request accepted."", ""message_uuid"": ""some-unique-message-identifier"" }
- Expected Error Response (e.g., missing field):
{ ""success"": false, ""message"": ""Missing required fields: \""to\"" and \""imageUrl\""."" }
This API layer provides a structured way to interact with your MMS sending logic via HTTP requests.
4. Integrating with Vonage (Configuration & Credentials)
Proper configuration is key to connecting your application with Vonage.
-
Vonage API Account: Ensure you have a Vonage account.
-
Purchase/Verify MMS Number:
- Navigate to your Vonage API Dashboard.
- Go to
Numbers
>Buy numbers
. - Search for numbers in the ""United States"".
- Ensure the number has ""SMS"" and ""MMS"" capabilities listed.
- Purchase the number. Note down this number in E.164 format (e.g.,
+12015550123
).
-
Create a Vonage Application: The Messages API uses Applications and public/private key pairs for authentication when sending.
- In the Dashboard, go to
Applications
>Create a new application
. - Give your application a name (e.g., ""My Express MMS App"").
- Click ""Generate public and private key"". Immediately save the
private.key
file that downloads. Store this securely and do not commit it to Git. A good practice is to place it outside your project directory or in a secure location referenced by your environment variables. For simplicity in this guide, you could place it in the project root, but ensure it's in.gitignore
. - Enable the ""Messages"" capability.
- Configure Webhooks: You need to provide URLs for Vonage to send status updates and potentially inbound messages (though we aren't handling inbound MMS in this guide).
- Status URL: This is where Vonage sends delivery receipts (
DLRs
). Use your/webhooks/status
endpoint. During local development, you needngrok
:- Run
ngrok http 3000
(assuming your server runs on port 3000). - Copy the
https
Forwarding URL provided by ngrok (e.g.,https://<unique-id>.ngrok.io
). - Enter
<your-ngrok-url>/webhooks/status
into the ""Status URL"" field (e.g.,https://<unique-id>.ngrok.io/webhooks/status
). Set the method toPOST
.
- Run
- Inbound URL: Even if not used now, it's often required. You can reuse the Status URL or point it to a different endpoint if you plan to receive MMS/SMS later. Enter
<your-ngrok-url>/webhooks/inbound
(or reuse status) and set method toPOST
.
- Status URL: This is where Vonage sends delivery receipts (
- Click ""Generate new application"".
- On the next page, note down the Application ID.
- Link Your Number: Scroll down to ""Link virtual numbers"" and link the MMS-capable US number you purchased earlier to this application.
- In the Dashboard, go to
-
Configure Environment Variables (
.env
): Create or open the.env
file in your project root and add the following, replacing the placeholder values:# .env # Vonage Credentials # Found in Application settings after creating an application VONAGE_APPLICATION_ID=""YOUR_APPLICATION_ID"" # Path to the private key file you downloaded when creating the application # Example: ./private.key (if in project root) or /path/to/secure/storage/private.key VONAGE_PRIVATE_KEY_PATH=""./private.key"" # MAKE SURE THIS IS IN .gitignore # Your Vonage MMS-capable number (E.164 format) # Purchased from the Vonage dashboard and linked to the application VONAGE_MMS_NUMBER=""+12015550123"" # --- Optional / Development --- # Port for the Express server PORT=3000 # Test recipient number (whitelisted if on Vonage trial account) # Used ONLY for the commented-out standalone test block in Section 2 of index.js # TEST_RECIPIENT_NUMBER=""+14155550100""
VONAGE_APPLICATION_ID
: The ID generated when you created the Vonage application.VONAGE_PRIVATE_KEY_PATH
: The file path to theprivate.key
file you saved. Ensure this path is correct relative to where you runnode index.js
.VONAGE_MMS_NUMBER
: Your purchased US Vonage number capable of sending MMS, in E.164 format.PORT
: The port your Express server will listen on.TEST_RECIPIENT_NUMBER
: Only used if you uncomment the test block at the end of Section 2. Needs to be a number whitelisted on your Vonage trial account if applicable.- Security: Remember, the
.env
file and theprivate.key
file contain sensitive credentials. Never commit them to version control. Use your.gitignore
file properly.
-
Vonage Trial Account Restrictions: If your Vonage account is new and still in trial mode (you haven't added payment details and made a payment), you can typically only send messages to phone numbers you have verified and added to your Vonage dashboard's ""test numbers"" list. Navigate to your Dashboard > Account > Settings > Test Numbers to add and verify them.
With these steps, your application is configured to authenticate with Vonage using your application credentials and send messages from your designated Vonage number. The status webhook configuration enables you to receive feedback on message delivery.
5. Implementing Error Handling, Logging, and Retry Mechanisms
Robust applications need proper error handling and logging.
-
Error Handling (Improved):
- Specific Errors: Our current
sendMmsMessage
function catches errors from the Vonage SDK. The SDK might throw errors for various reasons (invalid credentials, network issues, invalid parameters, API errors from Vonage). The error object often contains valuable details inerr.response.data
orerr.message
. - API Endpoint Errors: Our
/send-mms
endpoint handles errors fromsendMmsMessage
and validation errors. It correctly logs detailed errors internally while returning user-friendly messages (e.g., 500 Internal Server Error) to the client, preventing potential information leakage. - Status Webhook Errors: Failures in processing the status webhook should be logged, but the endpoint must still return
200 OK
quickly to Vonage to prevent unnecessary retries from their side. Handle processing asynchronously if it's complex.
- Specific Errors: Our current
-
Logging:
- Current Logging: We have basic
console.log
andconsole.error
statements. This is sufficient for development but not ideal for production. - Production Logging: Consider using a dedicated logging library like
winston
orpino
. These offer:- Log Levels: (debug, info, warn, error) to control verbosity.
- Structured Logging: Outputting logs in JSON format for easier parsing by log management systems (e.g., Datadog, Splunk, ELK stack).
- Transports: Sending logs to files, databases, or external services.
- Example (Conceptual
pino
integration):// --- Add near top of index.js --- import pino from 'pino'; const logger = pino({ level: process.env.LOG_LEVEL || 'info' }); // --- Replace console.log/error with logger --- // Example in sendMmsMessage catch block: // logger.error({ err: err.response?.data || err.message, to, from, imageUrl }, 'Error sending MMS'); // Example in API success: // logger.info({ to, message_uuid: result.message_uuid }, 'MMS request processed successfully'); // Example in Status Webhook: // logger.info({ body: req.body }, 'Status Webhook Received');
- Current Logging: We have basic
-
Retry Mechanisms:
- Vonage Delivery Retries: Vonage automatically handles retries for delivering the message to the carrier/handset if temporary issues occur. You monitor this via the Status Webhook.
- API Call Retries: Your call from Express to the Vonage API might fail due to transient network issues or temporary Vonage hiccups (e.g., 5xx errors from Vonage). You could implement a retry strategy here, potentially with exponential backoff. Libraries like
async-retry
can help. - Caution: Be careful retrying API calls that might have partially succeeded or have side effects. Check Vonage documentation for idempotency guarantees or use the
client_ref
parameter if supported for tracking. Retrying on validation errors (4xx) is generally pointless. - Simple Retry Example (Conceptual):
// Using a library like 'async-retry' import retry from 'async-retry'; // Assuming 'logger' is initialized as shown previously import pino from 'pino'; const logger = pino({ level: process.env.LOG_LEVEL || 'info' }); async function sendMmsWithRetry(to, from, imageUrl, caption) { return retry(async (bail, attempt) => { logger.info(`Attempt ${attempt} to send MMS to ${to}`); try { // Assume sendMmsMessage function exists as defined earlier return await sendMmsMessage(to, from, imageUrl, caption); } catch (err) { // Don't retry on client errors (4xx) // Use optional chaining ?. to safely access nested properties if (err.response?.status >= 400 && err.response?.status < 500) { logger.warn(`Non-retryable error sending MMS (status ${err.response.status}). Bailing.`); bail(err); // Stop retrying return; // Needed to prevent fall-through } // For other errors (network_ 5xx)_ throw to trigger retry logger.warn(`Retryable error sending MMS: ${err.message}. Retrying...`); throw err; // Re-throw the error to signal retry is needed } }_ { retries: 3_ // Number of retries factor: 2_ // Exponential backoff factor minTimeout: 1000_ // Minimum delay ms onRetry: (error_ attempt) => { logger.warn(`Retrying MMS send to ${to} (Attempt ${attempt}) after error: ${error.message}`); } }); } // In the API endpoint, call sendMmsWithRetry instead of sendMmsMessage // try { // const result = await sendMmsWithRetry(to, from, imageUrl, caption); // // ... rest of success handling // } catch (error) { // // ... error handling (log final failure, return 500) // }
Choose logging and retry strategies appropriate for your application's scale and reliability requirements. Start simple and enhance as needed.
6. Creating a Database Schema and Data Layer (Optional)
While not strictly required for just sending MMS, storing message information is common in real-world applications for tracking, reporting, and debugging.
-
Why Store Data?
- Keep a record of sent messages (recipient, time, content reference).
- Track message status updates received via webhook (delivered, failed, etc.).
- Correlate sending requests with delivery outcomes.
- Enable reporting and analytics.
-
Potential Schema (Conceptual - e.g., PostgreSQL with Prisma):
// schema.prisma datasource db { provider = ""postgresql"" // or mysql, sqlite url = env(""DATABASE_URL"") } generator client { provider = ""prisma-client-js"" } model MmsMessage { id String @id @default(cuid()) // Unique internal ID messageUuid String @unique @map(""message_uuid"") // Vonage Message UUID recipient String sender String imageUrl String @map(""image_url"") caption String? status String @default(""submitted"") // e.g., submitted, delivered, failed, rejected clientRef String? @unique @map(""client_ref"") // Optional client reference submittedAt DateTime @default(now()) @map(""submitted_at"") lastUpdatedAt DateTime @updatedAt @map(""last_updated_at"") errorCode String? @map(""error_code"") // From status webhook on failure errorReason String? @map(""error_reason"") // From status webhook on failure @@index([status]) @@index([submittedAt]) }
-
Implementation Steps (If Adding Database):
- Choose a database (PostgreSQL, MySQL, MongoDB, etc.).
- Select an ORM/ODM (like Prisma, Sequelize, Mongoose).
- Define your schema.
- Set up database connection logic.
- Modify the API endpoint (
/send-mms
) to create a record in the database before or after callingsendMmsMessage
. Store themessage_uuid
returned by Vonage. - Modify the webhook handler (
/webhooks/status
) to find the corresponding message record usingmessage_uuid
and update itsstatus
,lastUpdatedAt
, and potentiallyerrorCode
/errorReason
.