Frequently Asked Questions
Set up an Express server, install the Infobip API, Axios, and Dotenv. Create an endpoint that accepts the recipient's number and message text. Use Axios to send a POST request to the Infobip API with the necessary headers and message body. Don't forget to securely manage API keys with Dotenv.
An Infobip delivery report webhook is a mechanism that allows your application to receive real-time updates on the status of sent SMS messages. Infobip sends POST requests to a specified URL in your application whenever the delivery status of a message changes. This setup enables automatic tracking without needing to poll the Infobip API.
Node.js, with its non-blocking, event-driven architecture, and Express.js, a lightweight and flexible framework, provide a suitable environment for handling real-time callbacks efficiently. The combination makes it easier to build a server capable of receiving and processing concurrent delivery report updates without blocking other operations.
Configure the Infobip webhook immediately after setting up your /delivery-report
endpoint. This ensures your application is ready to receive delivery reports as soon as you start sending SMS messages. Make sure the endpoint URL is publicly accessible, especially during local development using tools like ngrok.
Create a dedicated endpoint (e.g., /delivery-report
) in your Express app. Configure this URL as the webhook in your Infobip account settings. Infobip will send POST requests to this endpoint with delivery status updates. Ensure your endpoint always returns a 2xx HTTP status code, even if processing fails, to prevent Infobip retries.
Wrap the logic within your /delivery-report
endpoint in a try-catch block to handle potential errors during report processing. Always send a 200 OK response back to Infobip, even if an error occurs, to prevent retry attempts. Log any errors that occur during processing for debugging and analysis.
The messageId
is a unique identifier assigned by Infobip to each SMS message sent through their API. It is crucial for tracking the delivery status of individual messages as it's included in the delivery reports sent to your webhook. This ID allows correlating delivery updates with specific messages initiated by your application.
Acknowledging Infobip callbacks with a 2xx HTTP status code, preferably 200 OK, is crucial to prevent Infobip from repeatedly sending the same delivery report. Without proper acknowledgment, Infobip assumes the report wasn't received and will retry at increasing intervals, potentially overwhelming your server.
The guide uses Node.js with Express for the backend, the Infobip API for sending SMS and configuring webhooks, Axios for making HTTP requests, and Dotenv for managing environment variables. These technologies provide a foundation for building a robust SMS application capable of receiving real-time delivery status updates.
Create a project directory, initialize npm with npm init -y
, and install necessary packages like express
, axios
, and dotenv
using npm install
. Configure environment variables (API key, base URL) in a .env
file. Set up a basic Express server and define routes for sending SMS and receiving delivery reports.
ngrok creates a secure tunnel that exposes your locally running application to the public internet. This is essential for receiving webhooks from Infobip during development, as Infobip needs a publicly accessible URL to send delivery reports to. Use ngrok to provide Infobip with a temporary public URL to your local server.
Use a tool like ngrok to expose your local server. Configure the ngrok URL as your webhook endpoint in Infobip. Then, send a test SMS through your application. Infobip will send the delivery report to your ngrok URL, which forwards it to your local server. You can also simulate callbacks using curl.
Log into your Infobip account portal. The API key and base URL are typically located in the Developers or API Keys section. Create a new API key or use an existing one. The base URL is specific to your account and is essential for directing API requests to the correct instance.
For sending messages, implement retry logic in your application. If the initial request to the Infobip API fails, implement exponential backoff – wait for increasing durations before retrying. Don't retry for client-side errors (4xx). For callbacks, Infobip handles automatic retries, so ensure your endpoint returns a 200 OK response quickly.
This guide provides a step-by-step walkthrough for building a Node.js application using the Express framework to send SMS messages via the Infobip API and receive real-time delivery status updates through webhooks (callbacks).
You will learn how to set up a project, send messages, configure Infobip webhooks, create an endpoint to receive status updates, handle potential errors, and deploy the application. This enables you to track the delivery status of every message sent, crucial for applications requiring reliable communication and reporting.
Project Goals:
Technologies Used:
System Architecture:
(System Architecture Diagram Placeholder: Ideally, replace this text with an actual diagram image showing the flow: User/Service -> Node.js App -> Infobip API (for sending SMS), and then Infobip Platform -> Node.js App (for delivery report callback).)
Prerequisites:
ngrok
for local development).Final Outcome:
By the end of this guide, you will have a running Node.js Express application capable of:
/delivery-report
) containing the delivery status of sent messages.Setting up the Project
Let's start by creating our project directory, initializing Node.js, and installing necessary dependencies.
Create Project Directory
Open your terminal or command prompt and create a new directory for the project.
Initialize Node.js Project
Initialize the project using npm. You can accept the defaults or customize them.
This creates a
package.json
file.Install Dependencies
We need
express
for the web server,axios
to make HTTP requests to Infobip, anddotenv
to manage environment variables. Note that modern Express versions (4.16.0+) include built-in middleware for parsing JSON and URL-encoded bodies, sobody-parser
is often no longer needed as a separate dependency.(Optional) Install Nodemon for Development:
nodemon
automatically restarts the server upon file changes, speeding up development.If you installed
nodemon
, update thescripts
section in yourpackage.json
:Project Structure
Create the basic files and folders.
Your initial structure should look like this:
Configure Environment Variables
We need to store sensitive information like API keys securely.
.env
: This file will hold your actual secrets (API Key, Base URL). Do not commit this file to version control..env.example
: A template showing required variables. Commit this file..gitignore
: Ensures.env
andnode_modules
are not tracked by Git.Add the following to your
.gitignore
:Add the following variable names to
.env.example
:Now, populate your actual
.env
file with your credentials. See the "Obtaining API Credentials" section for detailed instructions on obtaining your Infobip API Key and Base URL.Purpose of Configuration:
.env
/dotenv
: Keeps sensitive credentials out of the codebase, adhering to security best practices. Different environments (development, production) can have different.env
files.nodemon
: Improves developer experience by automatically restarting the server on code changes.Implementing Core Functionality
Now, let's write the code for our Express server, including sending SMS and preparing the endpoint for delivery reports.
Basic Express Server Setup
Open
server.js
and set up a minimal Express application.Implementing SMS Sending
We'll adapt the logic from the Infobip Node.js blog post to create an API endpoint
/send-sms
.Add the following code inside
server.js
where// --- Routes will go here ---
is indicated:Why this approach?
buildUrl
,buildHeaders
,buildRequestBody
) keep the main route handler clean.async/await
makes handling the promise returned byaxios.post
straightforward.try...catch
block specifically checks forerror.response
(errors from Infobip),error.request
(network issues), and other general errors.tracking
object in the request body tells Infobip we want delivery reports for this message. The specifictype
orprocessKey
can help categorize reports later.express.json()
instead of the externalbody-parser
package for simplicity and modern practice.Implementing the Delivery Report Endpoint
This endpoint (
/delivery-report
) will receivePOST
requests from Infobip containing status updates.Add the following code inside
server.js
where// --- Delivery Report Endpoint will go here ---
is indicated:Why this approach?
results
array from Infobip's payload.200 OK
response back to Infobip. This is highlighted due to its importance in preventing unnecessary retries from Infobip.try...catch
around the report processing loop to handle potential errors without crashing the server or preventing the200 OK
response.messageStore
. In a real application, this would involve database operations.Building a Complete API Layer
Our API layer currently consists of:
POST /send-sms
: Triggers sending an SMS.POST /delivery-report
: Receives delivery status updates from Infobip.GET /message-status
: (Optional debugging endpoint) View stored statuses.Testing with
curl
:Send SMS: (Make sure your server is running:
npm run dev
ornpm start
)Note: Replace
+12345678900
with your test number (must be verified on Infobip free trial).Check Status (Optional Debugging):
Simulate Infobip Callback (Advanced): You would typically rely on Infobip sending the callback, but you could simulate it:
Note: Use a
messageId
from a previous/send-sms
response. After simulation, check/message-status
again or watch the server logs.Authentication/Authorization:
This basic example lacks robust API authentication. For production:
/send-sms
: Protect this endpoint with API keys, JWT tokens, or other mechanisms suitable for your application's security model. Ensure only authorized clients can trigger messages./delivery-report
: This endpoint needs to be public for Infobip to reach it. Security relies on:crypto
) to verify a signature sent in the request header (e.g.,X-Infobip-Signature
). This is the most reliable method to ensure the request genuinely originated from Infobip and prevent malicious POSTs to your callback URL.Integrating with Infobip
Obtaining API Credentials
.env
file asINFOBIP_API_KEY
.xxxxx.api.infobip.com
.https://
)..env
file asINFOBIP_BASE_URL
.Configuring the Delivery Report Webhook
This tells Infobip where to send the delivery status updates.
/delivery-report
endpoint.ngrok
.npm run dev
ornpm start
). Let's assume it's on port 3000.ngrok http 3000
ngrok
will provide a public HTTPS URL (e.g.,https://<random-id>.ngrok-free.app
or similar).https://<random-id>.ngrok-free.app/delivery-report
https://your-app-domain.com/delivery-report
).Environment Variables Recap
INFOBIP_API_KEY
: Your secret key for authenticating API requests to Infobip. Found in Infobip portal > Developers > API Keys.INFOBIP_BASE_URL
: Your unique domain for accessing the Infobip API. Found near your API Key in the portal. Format:xxxxx.api.infobip.com
.PORT
: The local port your Express server listens on (e.g., 3000). Used byserver.js
.Fallback Mechanisms: Infobip handles retries for webhook delivery if your endpoint is temporarily unavailable (as discussed under the 'Implementing the Delivery Report Endpoint' section). For sending SMS, implement retries with exponential backoff in your client-side logic calling
/send-sms
if the initial request fails due to network issues or temporary Infobip unavailability (5xx errors).Error Handling, Logging, and Retry Mechanisms
Error Handling Strategy
/send-sms
Endpoint:to
,text
). Return400 Bad Request
for invalid input.try...catch
.error.response
), network errors (error.request
), and other server errors./delivery-report
Endpoint:req.body.results
array).try...catch
to prevent crashes if a report has an unexpected format or processing fails.200 OK
status to Infobip even if internal processing fails, unless the request format itself is completely unrecognizable. This acknowledges receipt and stops Infobip's retries. Log internal processing errors for later investigation.Logging
console.log
,console.warn
,console.error
. Suitable for development and simple cases.Winston
orPino
.console.log
etc. withlogger.info
,logger.error
, etc. inserver.js
(after importing the logger).Retry Mechanisms
/send-sms
): Retries should be implemented by the client calling your/send-sms
endpoint. If the client receives a 5xx error (indicating a server or temporary Infobip issue), it can retry using exponential backoff (e.g., wait 1s, then 2s, then 4s...). Avoid retrying on 4xx errors./delivery-report
): Infobip handles retries automatically if your endpoint doesn't respond with a 2xx status code. Your primary responsibility is to ensure your endpoint is reliable and acknowledges receipt promptly with a200 OK
.Testing Error Scenarios:
/send-sms
with missingto
ortext
fields (expect 400).INFOBIP_API_KEY
in.env
and send an SMS (expect 401/500 with Infobip auth error)./delivery-report
usingcurl
(expect 200 response but a warning in server logs).Creating a Database Schema and Data Layer (Conceptual)
The current in-memory
messageStore
is unsuitable for production as it loses data on server restart and doesn't scale.Conceptual Schema (e.g., SQL):
Data Access Layer (Conceptual using an ORM like Prisma or Sequelize):
npm install @prisma/client
,npm install prisma --save-dev
ornpm install sequelize pg pg-hstore
). Initialize it (npx prisma init
,npx sequelize init
).schema.prisma
, Sequelize models).npx prisma migrate dev
,npx sequelize db:migrate
).messageStore
object with an instance of your ORM client (e.g.,const { PrismaClient } = require('@prisma/client'); const prisma = new PrismaClient();
)./send-sms
: After successfully getting a response from Infobip, use the ORM'screate
method to insert a new record intosms_messages
, storing themessageId
,to
, initialstatus
, etc./delivery-report
: For each report, use the ORM'supdate
method (with awhere
clause oninfobip_message_id
) to update the status fields (status_group
,status_name
,error_name
,done_at
, etc.) andlast_updated_at
. Handle cases where themessageId
might not exist in your database (e.g., log a warning).This provides a persistent and scalable way to track message statuses. Remember to add proper database connection management, error handling for database operations, and potentially connection pooling for production environments.