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 Infobip API. We will cover project setup, core implementation using the Infobip Node.js SDK, API endpoint creation, configuration, error handling, and deployment considerations.
By the end of this tutorial, you will have a functional Express API endpoint capable of accepting requests and sending MMS messages containing text and media (like images) to specified recipients through Infobip. This solves the common need for applications to engage users with richer media content beyond simple SMS.
Project Overview and Goals
Goal: To create a simple backend service that exposes an API endpoint for sending MMS messages.
Problem Solved: Enables applications to programmatically send rich media messages (images, potentially video/audio depending on Infobip/carrier support) alongside text, enhancing user communication and engagement compared to plain SMS.
Technologies:
- Node.js: A JavaScript runtime environment for building server-side applications. Chosen for its event-driven, non-blocking I/O model, suitable for API development, and large ecosystem (npm).
- Express: A minimal and flexible Node.js web application framework. Chosen for its simplicity in setting up routes, middleware, and handling HTTP requests/responses.
- Infobip API & Node.js SDK (
@infobip-api/sdk
): Provides the communication bridge to Infobip's platform for sending MMS messages. The SDK simplifies interaction compared to raw HTTP requests. - dotenv: A module to load environment variables from a
.env
file intoprocess.env
, keeping sensitive credentials out of source code.
System Architecture:
+-------------+ +---------------------+ +---------------------+ +---------------+
| | HTTP | | SDK Call| | API | |
| HTTP Client |------>| Express Application |------>| Infobip Node.js SDK |------>| Infobip Cloud |
| (e.g. cURL)| | (API Endpoint) | | | | (MMS Gateway) |
+-------------+ +---------------------+ +---------------------+ +---------------+
| ^ |
| Request (Number, | Response (Success/Error) | Send MMS
| Media URL, Text) | v
+---------------------+ +--------------+
| User Handset |
+--------------+
Prerequisites:
- A free or paid Infobip account.
- Node.js and npm (or yarn) installed on your development machine.
- Basic understanding of JavaScript, Node.js, Express, and REST APIs.
- A mobile phone number registered and verified with your Infobip account (especially for free trial accounts, which often have sending restrictions).
- A publicly accessible URL hosting the media file (e.g., an image) you want to send.
Final Outcome: A running Node.js Express server with a single API endpoint (/send-mms
) that accepts a destination phone number, a media URL, and optional text, then uses the Infobip SDK to dispatch the MMS message.
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 infobip-mms-sender cd infobip-mms-sender
-
Initialize npm Project: This command creates a
package.json
file, which tracks project metadata and dependencies. You can accept the defaults or customize them.npm init -y
-
Install Dependencies: We need Express for the web server, the Infobip SDK for API interaction, and
dotenv
for managing environment variables.npm install express @infobip-api/sdk dotenv
express
: The web framework.@infobip-api/sdk
: The official Infobip SDK for Node.js.dotenv
: Loads environment variables from a.env
file.
-
Create Project Structure: Create the basic files and directories.
Example commands:
# On Linux/macOS touch server.js .env .env.example .gitignore # On Windows (Command Prompt) type nul > server.js type nul > .env type nul > .env.example type nul > .gitignore # On Windows (PowerShell) New-Item server.js -ItemType File New-Item .env -ItemType File New-Item .env.example -ItemType File New-Item .gitignore -ItemType File
server.js
: Our main application file containing the Express server logic..env
: Stores sensitive credentials (API Key, Base URL). This file should NOT be committed to version control..env.example
: A template showing required environment variables. This should be committed..gitignore
: Specifies intentionally untracked files that Git should ignore (like.env
andnode_modules
).
-
Configure
.gitignore
: Add the following lines to your.gitignore
file to prevent committing sensitive data and unnecessary files:# .gitignore # Dependencies node_modules/ # Environment variables .env # Logs logs/ *.log npm-debug.log* yarn-debug.log* yarn-error.log* # Optional macOS files .DS_Store
-
Set up Environment Variable Examples: Add the following structure to
.env.example
:# .env.example # Infobip Credentials INFOBIP_API_KEY=YOUR_INFOBIP_API_KEY INFOBIP_BASE_URL=YOUR_INFOBIP_BASE_URL # Server Configuration PORT=3000
-
Populate
.env
: Copy.env.example
to.env
and replace the placeholder values with your actual Infobip credentials (obtained in Section 4).# .env (DO NOT COMMIT THIS FILE) # Infobip Credentials INFOBIP_API_KEY=abcdef1234567890abcdef1234567890-abcdef12-abcd-1234-abcd-abcdef123456 INFOBIP_BASE_URL=xyz123.api.infobip.com # Server Configuration PORT=3000
INFOBIP_API_KEY
: Your unique key for authenticating API requests.INFOBIP_BASE_URL
: The specific API domain assigned to your Infobip account.PORT
: The port number your Express server will listen on.
2. Implementing Core Functionality (MMS Sending Logic)
We'll encapsulate the logic for interacting with the Infobip SDK within a dedicated function.
-
Edit
server.js
: Openserver.js
and start by requiring the necessary modules and configuringdotenv
.// server.js require('dotenv').config(); // Load environment variables from .env file const express = require('express'); const { Infobip, AuthType } = require('@infobip-api/sdk'); const app = express(); app.use(express.json()); // Middleware to parse JSON request bodies const PORT = process.env.PORT || 3000; const INFOBIP_API_KEY = process.env.INFOBIP_API_KEY; const INFOBIP_BASE_URL = process.env.INFOBIP_BASE_URL; // --- Input Validation --- if (!INFOBIP_API_KEY || !INFOBIP_BASE_URL) { console.error('Error: Infobip API Key or Base URL not found in environment variables.'); process.exit(1); // Exit if essential config is missing } // --- Initialize Infobip Client --- let infobipClient; try { infobipClient = new Infobip({ baseUrl: INFOBIP_BASE_URL, apiKey: INFOBIP_API_KEY, authType: AuthType.ApiKey, }); console.log('Infobip client initialized.'); } catch (initError) { console.error('Error initializing Infobip client:', initError); process.exit(1); } // --- MMS Sending Function --- // (To be added next) // --- API Endpoint --- // (To be added in Section 3) // --- Start Server --- app.listen(PORT, () => { console.log(`Server running on port ${PORT}`); });
- We load environment variables first using
dotenv
. - We import Express and the necessary components from the Infobip SDK.
- We enable Express's JSON body parser.
- We retrieve configuration from
process.env
. - Crucially, we add validation to ensure API credentials are loaded, preventing runtime errors later.
- We initialize the
infobipClient
once, providing the Base URL, API Key, and specifying the authentication type (ApiKey
), wrapped in a try-catch for initialization errors.
- We load environment variables first using
-
Create the
sendMmsMessage
Function: Add the following function withinserver.js
(before the API endpoint section). This function takes the recipient number, media URL, and optional text, then constructs and sends the request using the Infobip SDK.// server.js // ... (previous code) ... // --- MMS Sending Function --- async function sendMmsMessage(toNumber, mediaUrl, messageText = '') { console.log(`Attempting to send MMS to ${toNumber} with media ${mediaUrl}`); // Basic validation if (!toNumber || !mediaUrl) { throw new Error('Recipient number (toNumber) and media URL (mediaUrl) are required.'); } // Construct the MMS payload. // Always consult the latest Infobip API documentation for the definitive MMS payload structure. const payload = { messages: [ { destinations: [{ to: toNumber }], // 'from' might be required depending on your Infobip number setup // from: 'YourInfobipNumber', content: { mediaUrl: mediaUrl, // URL of the publicly accessible media text: messageText, // Optional text part of the message }, // Optional: Specify MMS template ID if using templates // templateid: 'YOUR_MMS_TEMPLATE_ID', // Optional: Add subject for MMS head: { subject: 'MMS from Your App' // Example subject } } ], // Optional: deliveryTimeWindow, notifyUrl, etc. }; try { // Use the appropriate SDK method for sending messages. // Verify the correct method (e.g., sms.send or a dedicated mms.send) in the SDK version you are using. // Infobip often uses the SMS channel endpoint for multiple message types based on payload content. const response = await infobipClient.channels.sms.send(payload); console.log('Infobip API Response:', JSON.stringify(response.data, null, 2)); return response.data; // Return the success response body } catch (error) { console.error('Error sending MMS via Infobip:', error.response ? JSON.stringify(error.response.data, null, 2) : error.message); // Re-throw a structured error for the API layer to handle const errorMessage = error.response?.data?.requestError?.serviceException?.text || error.message || 'Unknown error sending MMS'; const status = error.response?.status || 500; throw { status, message: errorMessage, details: error.response?.data }; } } // --- API Endpoint --- // (To be added in Section 3) // ... (rest of the code) ...
- The function is
async
because SDK calls are asynchronous (return Promises). - It performs basic validation for required parameters.
- Payload Construction: We define a
content
object containingmediaUrl
andtext
, and an optionalhead
for the subject. You must verify the exact structure required by the Infobip API/SDK. - SDK Call: We use
infobipClient.channels.sms.send(payload)
. Infobip's unified APIs often handle different message types via the same endpoint based on payload. Verify the correct method in your SDK version's documentation. - Error Handling: We wrap the SDK call in a
try...catch
block, logging details and re-throwing a structured error for the API layer.
- The function is
3. Building a Complete API Layer
Now, let's create the Express route that will use our sendMmsMessage
function.
-
Add API Endpoint in
server.js
: Place this code between thesendMmsMessage
function and theapp.listen
call.// server.js // ... (previous code, including sendMmsMessage function) ... // --- API Endpoint --- app.post('/send-mms', async (req, res) => { const { to, mediaUrl, text } = req.body; // --- Request Validation --- if (!to) { return res.status(400).json({ error: 'Missing required field: to (destination phone number)' }); } if (!mediaUrl) { return res.status(400).json({ error: 'Missing required field: mediaUrl (URL of the media file)' }); } // Basic validation for number format (E.164 recommended) // A more robust validation library (like libphonenumber-js) is advised for production if (!/^\+?[1-9]\d{1,14}$/.test(to)) { return res.status(400).json({ error: 'Invalid phone number format. Use E.164 format (e.g., +14155552671).' }); } // Basic URL validation try { new URL(mediaUrl); } catch (_) { return res.status(400).json({ error: 'Invalid mediaUrl format.' }); } try { const result = await sendMmsMessage(to, mediaUrl, text); // Send success response based on Infobip's result res.status(200).json({ success: true, data: result }); } catch (error) { // Handle errors thrown from sendMmsMessage console.error(`API Error sending MMS to ${to}:`, error); const statusCode = error.status || 500; res.status(statusCode).json({ success: false, error: error.message || 'Failed to send MMS', details: error.details }); } }); // ... (app.listen call) ...
- We define a
POST
route at/send-mms
. - It extracts
to
,mediaUrl
, and optionaltext
from the JSON request body (req.body
). - Request Validation: We perform server-side validation for required fields and basic format checks (phone number, URL). Invalid requests are rejected with a
400 Bad Request
. Robust validation is crucial. - It calls our
sendMmsMessage
function with the validated data. - If
sendMmsMessage
succeeds, it sends a200 OK
response. - If
sendMmsMessage
throws an error, it catches the error, logs it, and sends an appropriate HTTP error response.
- We define a
-
Testing with cURL: Make sure your server is running (
node server.js
). Open another terminal and usecurl
to test the endpoint. Replace placeholders with your verified phone number and a valid, publicly accessible image URL.curl -X POST http://localhost:3000/send-mms \ -H ""Content-Type: application/json"" \ -d '{ ""to"": ""+14155552671"", ""mediaUrl"": ""https://www.infobip.com/wp-content/uploads/2021/09/shape-2-1.png"", ""text"": ""Check out this cool image! Sent via Node.js and Infobip."" }'
Expected Success Response (Example):
{ ""success"": true, ""data"": { ""messages"": [ { ""to"": ""+14155552671"", ""status"": { ""groupId"": 1, ""groupName"": ""PENDING"", ""id"": 26, ""name"": ""PENDING_ACCEPTED"", ""description"": ""Message accepted, pending delivery."" }, ""messageId"": ""some-unique-message-id-from-infobip"" } ], ""bulkId"": ""some-unique-bulk-id-from-infobip"" } }
Expected Error Response (Example - Invalid API Key):
{ ""success"": false, ""error"": ""Invalid login details"", ""details"": { ""requestError"": { ""serviceException"": { ""messageId"": ""UNAUTHORIZED"", ""text"": ""Invalid login details"" } } } }
(Response status code would be 401 Unauthorized)
4. Integrating with Infobip (Credentials)
Securely handling your Infobip credentials is vital.
-
Obtain API Key and Base URL:
- Log in to your Infobip account portal.
- Navigate to the Homepage or Dashboard. Your Base URL (e.g.,
xxxxx.api.infobip.com
) is usually displayed prominently here. - Go to Developers -> API Keys (or a similar section).
- Click Create API Key (or similar). Give your key a descriptive name (e.g.,
NodeJS MMS App
). - Copy the generated API Key immediately. You typically won't be able to see it again after closing the creation dialog.
- Ensure the API key has the necessary permissions to send messages via the appropriate channels (SMS/MMS).
-
Store Credentials Securely:
- As done in Step 1.7, open your local
.env
file (which is not committed to Git). - Paste your actual
INFOBIP_API_KEY
andINFOBIP_BASE_URL
values.
# .env (DO NOT COMMIT) INFOBIP_API_KEY=paste_your_actual_api_key_here INFOBIP_BASE_URL=paste_your_actual_base_url_here PORT=3000
- As done in Step 1.7, open your local
-
Code Integration (
dotenv
):- The line
require('dotenv').config();
at the very top ofserver.js
loads these variables intoprocess.env
. - The code then accesses them via
process.env.INFOBIP_API_KEY
andprocess.env.INFOBIP_BASE_URL
. This keeps credentials out of the source code itself.
- The line
5. Error Handling, Logging, and Retry Mechanisms
Robust error handling and logging are essential for production systems.
-
Error Handling Strategy:
- Validation Errors: The API endpoint (
/send-mms
) performs initial checks for required fields and basic format validation, returning400 Bad Request
errors immediately. - SDK/API Errors: The
sendMmsMessage
function wraps the Infobip SDK call in atry...catch
. It catches errors from the SDK (network issues, API errors) and parses the response to extract meaningful error messages and status codes provided by Infobip. It then re-throws a structured error. - API Layer Catch-All: The
async (req, res)
handler in the API endpoint has its owntry...catch
to handle errors thrown bysendMmsMessage
or any other unexpected issues, ensuring a JSON error response is always sent to the client instead of crashing the server.
- Validation Errors: The API endpoint (
-
Logging:
- Basic Logging: We are using
console.log
for informational messages (server start, initialization, attempt messages) andconsole.error
for errors. - Production Logging: For production, replace
console.log
/console.error
with a dedicated logging library likewinston
orpino
. This enables:- Different log levels (info, warn, error, debug).
- Structured logging (JSON format) for easier parsing by log management systems.
- Outputting logs to files, databases, or external services (like Datadog, Splunk).
- Example Logging Points:
- Log incoming requests (method, URL, source IP - be mindful of PII).
- Log successful MMS dispatches with the
messageId
andbulkId
. - Log detailed errors, including the full error object from Infobip when available.
- Basic Logging: We are using
-
Retry Mechanisms:
- Why Retry? Transient network issues or temporary Infobip service unavailability might cause requests to fail. Retrying can improve reliability.
- Implementation: Retries are not implemented in this basic example. For production, you could implement a retry strategy within the
catch
block of thesendMmsMessage
function:- Check if the error is retryable (e.g., network errors, specific 5xx status codes from Infobip like
503 Service Unavailable
). Do not retry client errors (4xx). - Implement exponential backoff: Wait increasingly longer durations between retries (e.g., 1s, 2s, 4s, 8s) to avoid overwhelming the service.
- Limit the number of retries (e.g., 3 attempts).
- Libraries like
axios-retry
(if using axios directly) orasync-retry
can help manage this logic. Since we use the SDK, manual implementation or checking if the SDK has built-in retry options is needed.
- Check if the error is retryable (e.g., network errors, specific 5xx status codes from Infobip like
-
Testing Error Scenarios:
- Send requests with missing fields (
to
,mediaUrl
). - Send requests with invalid data (incorrect phone format, invalid URL).
- Temporarily modify
.env
with an invalidINFOBIP_API_KEY
to test authentication errors. - If possible, simulate network issues (though harder without specific tools).
- Send to a non-existent or blocked number (if Infobip provides specific errors for these).
- Send requests with missing fields (
6. Database Schema and Data Layer
This specific application (a simple MMS sending proxy) does not require a database. It acts as a stateless gateway to the Infobip API.
If Persistence Were Needed:
-
Use Case: You might want to store a record of sent messages, their status (using
messageId
and potentially Delivery Reports - see Infobip docs), recipient details, timestamps, and associated application data. -
Schema Example (e.g., PostgreSQL/MySQL):
CREATE TABLE mms_log ( id SERIAL PRIMARY KEY, infobip_message_id VARCHAR(255) UNIQUE, -- From Infobip response infobip_bulk_id VARCHAR(255), -- From Infobip response recipient_number VARCHAR(20) NOT NULL, media_url TEXT NOT NULL, message_text TEXT, status VARCHAR(50) DEFAULT 'PENDING', -- e.g., PENDING, SENT, DELIVERED, FAILED submitted_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, last_updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, error_message TEXT -- Store error if sending failed initially ); -- Index for querying by messageId or recipient CREATE INDEX idx_mms_log_message_id ON mms_log(infobip_message_id); CREATE INDEX idx_mms_log_recipient ON mms_log(recipient_number);
-
Data Layer: Use an Object-Relational Mapper (ORM) like Prisma, Sequelize, or TypeORM, or a query builder like Knex.js to interact with the database within your Node.js application. You would insert a record before or after calling the Infobip API and potentially update the
status
later based on delivery reports (which requires setting up a webhook endpoint to receive status updates from Infobip).
For this guide's scope, we omit database integration.
7. Adding Security Features
Security is paramount, especially when dealing with external APIs and user data.
-
Input Validation and Sanitization:
- Validation: As implemented in Section 3, always validate incoming request data (
req.body
). Ensure required fields exist, check data types, and validate formats (phone numbers, URLs). Use libraries likejoi
orexpress-validator
for more complex validation rules. - Sanitization: While less critical for this specific app where we mostly pass data to Infobip, sanitize any input that might be stored or reflected back to users to prevent Cross-Site Scripting (XSS). For URLs and phone numbers passed to Infobip, rely on Infobip's handling, but ensure your own logging or storage doesn't introduce vulnerabilities.
- Validation: As implemented in Section 3, always validate incoming request data (
-
Protection Against Common Vulnerabilities:
-
API Key Security: Never hardcode API keys. Use environment variables (
.env
) and ensure.env
is in.gitignore
. Use tools likehelmet
middleware for Express to set various security-related HTTP headers (e.g.,X-Frame-Options
,Strict-Transport-Security
).npm install helmet
// server.js const helmet = require('helmet'); // ... app.use(helmet()); // Add recommended security headers // ...
-
Preventing Abuse: Implement measures to stop malicious actors from using your endpoint excessively.
-
-
Rate Limiting:
-
Prevent brute-force attacks and abuse by limiting the number of requests a client can make in a given time window. Use middleware like
express-rate-limit
.npm install express-rate-limit
// server.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 standardHeaders: true, // Return rate limit info in the `RateLimit-*` headers legacyHeaders: false, // Disable the `X-RateLimit-*` headers message: 'Too many requests from this IP, please try again after 15 minutes' }); app.use('/send-mms', apiLimiter); // Apply limiter specifically to the MMS endpoint // ... (rest of the API endpoint setup)
-
-
Authentication/Authorization (Optional):
- Currently, the endpoint is open. In a real application, you'd protect it.
- Methods: API Keys (specific to your users), JWT (JSON Web Tokens), OAuth2.
- Implement middleware to check for valid authentication credentials before allowing access to the
/send-mms
route.
-
Media URL Security:
- Ensure the
mediaUrl
points to a trusted source or implement checks if necessary. Be aware that your server will effectively instruct Infobip to fetch content from this URL.
- Ensure the
8. Handling Special Cases
Real-world scenarios often involve edge cases.
-
Phone Number Formatting:
- E.164 Standard: Infobip strongly recommends (and often requires) the E.164 format for phone numbers (e.g.,
+14155552671
). Include the+
and country code. - Validation: Use robust libraries like
libphonenumber-js
for parsing and validating numbers from various formats if your input source isn't strictly E.164.
- E.164 Standard: Infobip strongly recommends (and often requires) the E.164 format for phone numbers (e.g.,
-
Media URL Accessibility & Format:
- Public Access: The
mediaUrl
must be publicly accessible without requiring authentication, cookies, or complex redirects, so Infobip's servers can fetch it. - Supported Formats: Infobip supports common image formats (JPEG, PNG, GIF) and video/audio formats (check their documentation for specifics like MP4 H.264/AAC). Sending unsupported formats will likely fail.
- Content Size Limits: MMS messages have size limits (often around 300KB-1MB, varying by carrier). Ensure your media files are within acceptable limits. Infobip might resize images, but starting with optimized files is best. Refer to Infobip's MMS documentation for recommendations.
- Public Access: The
-
Character Encoding:
- For the
text
part, use UTF-8 encoding, which is standard and supports a wide range of characters. The Infobip SDK/API generally handles this correctly.
- For the
-
Infobip Free Trial Limitations:
- As noted previously, free trial accounts often restrict sending to the phone number used during registration. Ensure you test with that number initially. Paid accounts remove this limitation.
-
Destination Carrier Limitations:
- Not all mobile carriers or handsets fully support MMS, or they might have stricter size limits or format restrictions. Delivery can fail due to downstream limitations beyond Infobip's control. Check Infobip's documentation or support for country/carrier-specific information if deliverability issues arise.
9. Implementing Performance Optimizations
For this simple proxy service, performance bottlenecks are unlikely within the Node.js application itself. The main latency will come from the network roundtrip to the Infobip API and Infobip's internal processing.
- SDK Client Initialization: We correctly initialize the
infobipClient
once when the application starts, avoiding the overhead of creating a new client for every request. - Asynchronous Operations: Node.js and the
async/await
pattern handle the asynchronous nature of the API call efficiently without blocking the server. - Payload Size: Keep the request payload to Infobip minimal. Only include necessary fields.
- Caching: Caching is not applicable here, as each request is unique and triggers a real-time send operation.
- Load Testing: If handling high volume, use tools like
k6
,Artillery
, orJMeter
to simulate traffic against your/send-mms
endpoint and monitor response times and resource usage (CPU, memory) of your Node.js process. This helps determine scaling needs. - Node.js Clustering: For multi-core servers, use Node.js's built-in
cluster
module or a process manager likepm2
in cluster mode to run multiple instances of your application, distributing the load across CPU cores.
10. Monitoring, Observability, and Analytics
Monitoring ensures your service is healthy and performing as expected.
-
Health Checks:
- Add a simple health check endpoint that monitoring services can ping.
// server.js // ... app.get('/health', (req, res) => { // Basic check: server is running // Could add checks for Infobip connectivity if needed (e.g., a lightweight API call) res.status(200).json({ status: 'UP', timestamp: new Date().toISOString() }); }); // ...
-
Performance Metrics:
- Use Application Performance Monitoring (APM) tools (Datadog, New Relic, Dynatrace) or Node.js-specific libraries (
prom-client
for Prometheus) to track:- Request latency (average, p95, p99 for
/send-mms
). - Request rate (requests per second).
- Error rates (percentage of 4xx and 5xx responses).
- Node.js process metrics (CPU usage, memory usage, event loop lag).
- Request latency (average, p95, p99 for
- Use Application Performance Monitoring (APM) tools (Datadog, New Relic, Dynatrace) or Node.js-specific libraries (
-
Error Tracking:
- Integrate services like Sentry or Bugsnag. These automatically capture unhandled exceptions and errors logged via supported logging libraries, providing stack traces, request context, and alerting.
-
Logging (Revisited):
- Ensure logs (preferably structured JSON) are aggregated into a central system (ELK stack, Splunk, Datadog Logs, Loki) for searching, analysis, and dashboarding.
-
Key Metrics Dashboard:
- Create dashboards in your monitoring/log management tool showing:
- MMS Sent Rate (count of successful 200 responses from
/send-mms
). - MMS Error Rate (count of 4xx/5xx responses from
/send-mms
). - API Latency (for
/send-mms
). - Infobip API Error Breakdown (based on parsing error messages/codes from Infobip).
- Server resource usage.
- MMS Sent Rate (count of successful 200 responses from
- Create dashboards in your monitoring/log management tool showing:
-
Alerting:
- Set up alerts based on thresholds:
- High error rate (> 5% of requests failing).
- Increased latency (> 1 second average response time).
- Server down (health check failing).
- High resource usage (CPU > 80%, low available memory).
- Set up alerts based on thresholds:
11. Troubleshooting and Caveats
Common issues and things to watch out for:
-
Error: Invalid login details (
UNAUTHORIZED
)- Cause: Incorrect
INFOBIP_API_KEY
orINFOBIP_BASE_URL
in.env
. API key might lack permissions. - Solution: Verify credentials in
.env
match those from the Infobip portal exactly. Check API key permissions in Infobip. Ensure.env
is being loaded correctly (e.g.,require('dotenv').config()
is called early).
- Cause: Incorrect
-
Error: Bad request / Invalid destination address
- Cause: Phone number (
to
) format is incorrect. It might be missing the country code or+
, or contain invalid characters. - Solution: Ensure numbers are passed in E.164 format (e.g.,
+14155552671
). Implement stricter validation (considerlibphonenumber-js
).
- Cause: Phone number (
-
Error: Cannot fetch media / Invalid media URL
- Cause: The
mediaUrl
is inaccessible (private, requires login, typo), invalid, or points to an unsupported file type/size. - Solution: Verify the URL is public and correct. Check supported media types and size limits in Infobip docs. Test the URL in an incognito browser window or using
curl
.
- Cause: The
-
Error: ServiceException / Internal Server Error from Infobip (5xx)
- Cause: Temporary issue on Infobip's side.
- Solution: Implement retry logic (Section 5) for transient errors. Check Infobip's status page. Contact Infobip support if persistent.
-
Messages Sent but Not Received:
- Cause: Free trial limitations (sending only to registered number). Carrier filtering/blocking. Invalid or inactive destination number. Handset issues (MMS disabled, incompatible phone).
- Solution: Confirm you're using the registered number if on a free trial. Check Infobip delivery reports (requires webhook setup) for status details. Verify the destination number is active and capable of receiving MMS. Test with different media types/sizes.