code examples
code examples
Building Production-Ready Two-Way SMS: Fastify & Infobip Guide
A step-by-step tutorial for receiving and replying to SMS messages using Node.js, Fastify, and the Infobip API.
Project Overview and Goals
This guide details how to build a robust Node.js application using the Fastify framework to handle inbound SMS messages via Infobip webhooks and enable automated replies, creating a functional two-way messaging system.
What We'll Build:
A Fastify server that:
- Listens for incoming HTTP POST requests (webhooks) from Infobip containing SMS message data.
- Securely validates and processes these incoming messages.
- Logs message details for tracking and debugging.
- Optionally sends an automated SMS reply back to the original sender via the Infobip API.
Problem Solved:
Many applications need to react to SMS messages sent by users – for customer support, automated information retrieval, receiving commands, or triggering workflows. This guide provides the foundation for building such systems, enabling programmatic interaction via SMS.
Technologies Used:
- Node.js: A JavaScript runtime environment for building server-side applications.
- Fastify: A high-performance, low-overhead web framework for Node.js, chosen for its speed, extensibility, and developer-friendly features.
- Infobip API & SDK: Provides the communication infrastructure for sending and receiving SMS messages. We'll use their webhook system for inbound messages and the official Node.js SDK (
@infobip-api/sdk) for outbound replies. dotenv: A zero-dependency module to load environment variables from a.envfile intoprocess.env.
System Architecture:
Note: This diagram relies on monospace fonts. For optimal display across all platforms, consider replacing this with an actual image diagram and providing descriptive alt text.
+-------------+ +-----------------+ +----------------------+ +---------------------+ +-------------+
| User's Phone| ----> | Infobip Network | ----> | Infobip Webhook Call | ----> | Your Fastify App | ----> | User's Phone|
| (Sends SMS) | | (Receives SMS) | | (HTTP POST to URL) | | (Processes & Replies)| | (Receives Reply)|
+-------------+ +-----------------+ +----------------------+ +---------------------+ +-------------+
|
| [Optional Reply]
V
+----------------+
| Infobip API Call |
| (Send SMS) |
+----------------+Prerequisites:
- An active Infobip account with API access.
- A provisioned phone number within your Infobip account capable of sending/receiving SMS.
- Node.js (v18 or later recommended) and npm (or yarn) installed on your development machine.
- Basic understanding of JavaScript, Node.js, REST APIs, and webhooks.
- A tool to expose your local server to the internet for testing webhooks (e.g.,
ngrok).
Final Outcome:
A running Fastify application capable of receiving SMS messages sent to your Infobip number and logging them. Optionally, it can send an automated reply.
1. Setting Up the Project
Let's initialize our Node.js project and install the necessary dependencies.
1.1 Create Project Directory:
Open your terminal and create a new directory for the project.
mkdir fastify-infobip-sms
cd fastify-infobip-sms1.2 Initialize Node.js Project:
Initialize the project using npm. You can accept the defaults or customize as needed.
npm init -yThis creates a package.json file.
1.3 Install Dependencies:
We need Fastify for the web server, the Infobip SDK for interacting with their API, and dotenv for managing environment variables.
npm install fastify @infobip-api/sdk dotenv1.4 Install Development Dependencies (Optional but Recommended):
For a better development experience, install nodemon to automatically restart the server on file changes.
npm install --save-dev nodemon1.5 Configure package.json Scripts:
Add scripts to your package.json for running the server easily.
// package.json
{
// ... other properties
"main": "src/server.js", // Specify entry point
"scripts": {
"start": "node src/server.js",
"dev": "nodemon src/server.js", // Use nodemon for development
"test": "echo \"Error: no test specified\" && exit 1"
},
// ... other properties
}Note: The "main": "src/server.js" line points to a file (src/server.js) that we create in the next step. This is standard practice but be aware the file doesn't exist immediately after this package.json edit.
1.6 Create Project Structure:
Organize your code for better maintainability.
mkdir src
mkdir src/routes
mkdir src/config
touch src/server.js
touch src/routes/infobipWebhook.js
touch src/config/environment.js
touch .env
touch .env.example
touch .gitignoresrc/: Contains all source code.src/routes/: Holds route handlers.src/config/: For configuration files.src/server.js: The main application entry point..env: Stores sensitive credentials (API keys, etc.). Never commit this file..env.example: A template showing required environment variables. Commit this file..gitignore: Specifies intentionally untracked files that Git should ignore.
1.7 Configure .gitignore:
Add node_modules and .env to your .gitignore file to prevent committing them.
# .gitignore
node_modules/
.env
*.log1.8 Set Up Environment Variables:
Define the necessary environment variables in .env.example and .env.
# .env.example
# Infobip Credentials
INFOBIP_API_KEY=YOUR_INFOBIP_API_KEY
INFOBIP_BASE_URL=YOUR_INFOBIP_BASE_URL # e.g., xyz.api.infobip.com
INFOBIP_WEBHOOK_SECRET=YOUR_OPTIONAL_SHARED_SECRET # Optional, for added security if supported/used
# Server Configuration
PORT=3000
HOST=0.0.0.0 # Listen on all available network interfacesImportant: Copy .env.example to .env and fill in your actual Infobip API Key and Base URL in the .env file. You can find these in your Infobip account dashboard (usually under API Keys). The INFOBIP_WEBHOOK_SECRET is optional; use it only if you configure a corresponding mechanism in Infobip (see Section 6).
1.9 Load Environment Variables:
Create a simple module to load and export environment variables.
// src/config/environment.js
require('dotenv').config(); // Load variables from .env
const environment = {
infobip: {
apiKey: process.env.INFOBIP_API_KEY,
baseUrl: process.env.INFOBIP_BASE_URL,
webhookSecret: process.env.INFOBIP_WEBHOOK_SECRET, // Can be undefined
},
server: {
port: parseInt(process.env.PORT || '3000', 10),
host: process.env.HOST || '0.0.0.0',
},
};
// Basic validation
if (!environment.infobip.apiKey || !environment.infobip.baseUrl) {
console.error(
'FATAL ERROR: INFOBIP_API_KEY and INFOBIP_BASE_URL must be defined in the .env file'
);
process.exit(1);
}
module.exports = environment;1.10 Basic Fastify Server Setup:
Initialize the Fastify server in src/server.js.
// src/server.js
const fastify = require('fastify')({
logger: true, // Enable built-in Pino logger
});
const config = require('./config/environment');
const infobipWebhookRoutes = require('./routes/infobipWebhook');
// --- Register Plugins and Routes ---
// Register the webhook routes
fastify.register(infobipWebhookRoutes, { prefix: '/webhook' });
// --- Default Root Route ---
fastify.get('/', async (request, reply) => {
return { status: 'ok', timestamp: new Date().toISOString() };
});
// --- Health Check Route ---
fastify.get('/health', async (request, reply) => {
return { status: 'healthy' };
});
// --- Start Server ---
const start = async () => {
try {
await fastify.listen({ port: config.server.port, host: config.server.host });
fastify.log.info(`Server listening on ${fastify.server.address().port}`);
} catch (err) {
fastify.log.error(err);
process.exit(1);
}
};
start();
// Export the app instance if needed for testing (alternative to builder function)
// module.exports = fastify;
// Or refactor into a builder function for cleaner testing (see Section 9.2 note)Now you have a basic Fastify server structure ready. You can test it by running npm run dev. You should see log output indicating the server has started. Accessing http://localhost:3000/ in your browser should return {"status":"ok", ...}.
2. Implementing the Inbound Webhook
The core of receiving SMS messages is handling the HTTP POST request Infobip sends to your application (the webhook).
2.1 Define the Webhook Route Handler:
In src/routes/infobipWebhook.js, create the Fastify route handler that will listen for POST requests at /webhook/infobip.
// src/routes/infobipWebhook.js
const config = require('../config/environment');
// Import Infobip SDK later when needed for replies
// const { Infobip, AuthType } = require('@infobip-api/sdk');
async function infobipWebhookRoutes(fastify, options) {
// Optional: Instantiate Infobip client here if needed within this plugin scope
// const infobipClient = new Infobip({ /* ... */ });
fastify.post('/infobip', async (request, reply) => {
fastify.log.info('Received Infobip webhook request');
fastify.log.debug({ body: request.body }, 'Webhook payload');
// --- Security Check ---
// **IMPORTANT:** Verify if/how Infobip supports securing webhooks.
// Common methods include Basic Authentication or a custom signature header.
// Consult the Infobip documentation for the *specific mechanism* they provide.
// The example below uses a hypothetical shared secret header. Adapt as needed.
if (config.infobip.webhookSecret) {
const receivedSecret = request.headers['x-webhook-secret']; // Example header - CHECK INFOBIP DOCS
if (receivedSecret !== config.infobip.webhookSecret) {
fastify.log.warn('Invalid or missing webhook secret received');
return reply.code(401).send({ error: 'Unauthorized' });
}
}
// Add checks for Basic Auth (request.headers.authorization) if configured in Infobip.
// --- Process Incoming Message ---
try {
// **IMPORTANT:** Infobip payload structure can vary.
// Always check the *specific webhook configuration* in your Infobip portal
// and the official Infobip documentation for the expected payload format.
// The common structure involves a 'results' array.
const results = request.body.results;
if (!results || !Array.isArray(results) || results.length === 0) {
fastify.log.warn('Webhook payload missing or invalid results array');
return reply.code(400).send({ error: 'Invalid payload format' });
}
// Process each message in the payload (often just one)
for (const message of results) {
// **IMPORTANT:** Field names like 'receivedAt', 'text', 'from', 'to', 'messageId'
// depend on your Infobip webhook configuration. Verify these in the Infobip docs
// or by inspecting an actual payload received from Infobip.
const messageId = message.messageId;
const from = message.from;
const to = message.to; // Your Infobip number
const text = message.text;
const receivedAt = message.receivedAt; // Example field name
if (!messageId || !from || !text) {
fastify.log.warn({ message }, 'Skipping message with missing fields');
continue; // Skip this message, process others if any
}
fastify.log.info(
`Processing message ${messageId} from ${from}: ""${text}""`
);
// --- TODO: Implement your business logic here ---
// Examples:
// 1. Store the message in a database
// 2. Trigger a workflow based on keywords in 'text'
// 3. Send an automated reply (see Section 4)
// --- Add Reply Logic Here (See Section 4) ---
} // End for loop
// --- Acknowledge Receipt ---
// Crucially, respond quickly to Infobip to prevent timeouts/retries
reply.code(200).send({ status: 'received' });
} catch (error) {
fastify.log.error(
{ err: error },
'Error processing Infobip webhook payload'
);
// Send a generic error response. Avoid leaking internal details.
reply.code(500).send({ error: 'Internal Server Error' });
}
});
}
module.exports = infobipWebhookRoutes;Explanation:
- Route Definition: We define a
POSTroute at/infobip(prefixed with/webhook, making the full path/webhook/infobip). - Logging: We log the incoming request body for debugging. Adjust log levels (
info,debug) as needed. - Security Check: Includes a placeholder for validating a secret. Crucially, it emphasizes checking Infobip documentation for their actual supported security mechanisms (Basic Auth, signatures, etc.) and adapting the code accordingly.
- Payload Parsing: Checks for the
resultsarray. Adds strong emphasis (multiple bolded notes) that the payload structure and field names (results,messageId,from,text,receivedAt) MUST be verified against the specific Infobip configuration and documentation. - Data Extraction & Validation: Extracts fields based on the assumed common structure, with added warnings about verification. Basic checks ensure required fields are present.
- Business Logic Placeholder:
TODOmarks where application-specific logic goes. - Acknowledgement: Sends
200 OKpromptly. - Error Handling:
try...catchlogs errors and sends500.
3. Integrating with Infobip
Now, we need to tell Infobip where to send the incoming SMS messages.
3.1 Expose Your Local Server (Development Only):
Infobip needs a publicly accessible URL to send webhooks. During development, you can use ngrok.
-
Download and install ngrok: https://ngrok.com/download
-
Authenticate ngrok if you haven't already (follow their instructions).
-
Start your Fastify server:
npm run dev(it should be running on port 3000). -
In a new terminal window, run:
bashngrok http 3000 -
ngrokwill display output similar to this:Forwarding https://<unique-id>.ngrok-free.app -> http://localhost:3000Copy the
https://<unique-id>.ngrok-free.appURL. This is your public URL. Remember that freengrokURLs are temporary and change every time you restartngrok. For stable testing or production, you need a permanent URL (see Section 8).
3.2 Configure Infobip Webhook:
- Log in to your Infobip account portal (https://portal.infobip.com/).
- Navigate to the section for managing your numbers or SMS settings (e.g., "Apps", "Numbers", "Channels -> SMS"). Look for incoming message settings or webhook configurations.
- Find the phone number you want to use.
- Locate the option to configure "Incoming Messages", "Forward to URL", or "Webhook URL".
- Enter your public webhook URL:
https://<unique-id>.ngrok-free.app/webhook/infobip(use your actual ngrok URL). - Security (Optional but Recommended): Configure webhook security in Infobip (e.g., Basic Authentication, specific headers/signatures if offered) and ensure your application code (Section 2.1) validates it correctly.
- Save the configuration.
3.3 Verify API Key and Base URL:
Double-check that the INFOBIP_API_KEY and INFOBIP_BASE_URL in your .env file are correct. These are needed for sending replies (Section 4).
- API Key: Find in "API Keys" or "Developer Tools" in Infobip.
- Base URL: Specific to your account (e.g.,
yoursubdomain.api.infobip.com), usually shown near the API key.
4. Adding Two-Way Reply Functionality
Let's make the application reply to incoming messages.
4.1 Instantiate Infobip SDK Client and Send Reply:
Update src/routes/infobipWebhook.js to use the SDK.
// src/routes/infobipWebhook.js
const config = require('../config/environment');
const { Infobip, AuthType } = require('@infobip-api/sdk'); // Import SDK
async function infobipWebhookRoutes(fastify, options) {
// Instantiate Infobip client within the plugin scope
const infobipClient = new Infobip({
baseUrl: config.infobip.baseUrl,
apiKey: config.infobip.apiKey,
authType: AuthType.ApiKey, // Use API Key authentication
});
fastify.post('/infobip', async (request, reply) => {
// ... (logging and security checks from Section 2.1) ...
try {
const results = request.body.results;
// ... (payload validation from Section 2.1, including checking Infobip docs) ...
for (const message of results) {
// Verify field names based on Infobip docs/payload
const messageId = message.messageId;
const from = message.from; // Sender's number (recipient of our reply)
const to = message.to; // Your Infobip number (sender of our reply)
const text = message.text;
// ... (field validation) ...
fastify.log.info(
`Processing message ${messageId} from ${from}: ""${text}""`
);
// --- Send Automated Reply ---
try {
const replyText = `Thanks for your message: ""${text.substring(0, 50)}${text.length > 50 ? '...' : ''}""`;
fastify.log.info(`Sending reply to ${from}`);
// Use the SDK's send method
const infobipResponse = await infobipClient.channels.sms.send({
messages: [
{
destinations: [{ to: from }], // Send reply to the original sender
// **IMPORTANT**: Specifying 'from' is highly recommended for consistency.
// Use your Infobip number ('to' from the incoming message) or a registered
// Alphanumeric Sender ID (e.g., 'MyBrand').
// Alphanumeric Sender ID rules are country-specific. Check Infobip docs.
from: to,
text: replyText,
},
],
});
// Log the result from Infobip API
// **Note:** Verify `infobipResponse.data` is the correct path to response details
// in the specific SDK version you are using. Log `infobipResponse` itself
// during testing if unsure.
fastify.log.info(
{ response: infobipResponse.data },
'Infobip reply API response'
);
} catch (sendError) {
fastify.log.error(
{ err: sendError, recipient: from },
'Failed to send SMS reply via Infobip API'
);
// Decide if this failure should cause the webhook to return 500. Usually not.
}
// --- End Send Reply ---
} // End for loop
reply.code(200).send({ status: 'received' });
} catch (error) {
// ... (general error handling from Section 2.1) ...
reply.code(500).send({ error: 'Internal Server Error' });
}
});
}
module.exports = infobipWebhookRoutes;Explanation:
- Import & Instantiate: Imports
Infobip,AuthTypeand createsinfobipClient. - Send Reply Logic:
- Calls
infobipClient.channels.sms.send(). destinations: Settothe original sender (from).from: Updated explanation: Emphasizes that specifyingfrom(your Infobip number or Alphanumeric Sender ID) is highly recommended or required. Notes Alphanumeric Sender ID rules are country-specific and require checking docs.text: Reply content.
- Calls
- Response Logging: Logs
infobipResponse.data. Adds a note advising verification of thedataproperty based on the SDK version. - Reply Error Handling: Specific
try...catchfor sending, logging errors but generally still returning200 OKfor the webhook receipt.
5. Error Handling and Logging
Robust error handling and clear logging are crucial for production systems.
Error Handling Strategy:
- Webhook Processing: Wrap main logic in
try...catch. Log errors (fastify.log.error). Return appropriate HTTP status codes (500,400,401). - Reply Sending: Wrap SDK calls in separate
try...catch. Log send errors specifically. Usually return200to the webhook even if the reply fails, handling reply failures asynchronously if needed. - Fastify Errors: Utilize Fastify's built-in error handling and logging. Consider custom error handlers (
fastify.setErrorHandler()) for advanced scenarios.
Logging:
- Fastify Logger (Pino): Enabled (
logger: true) for structured JSON logging. - Log Levels: Use
info,warn,error,debugappropriately. Control level via environment variables in production. - Context: Include relevant data (messageId, recipient, error objects) in logs.
- Log Analysis: Use centralized logging systems (Datadog, ELK, Splunk) in production.
Retry Mechanisms:
- Webhook Retries (Infobip): Infobip retries on non-
2xxresponses. Your app should respond quickly and be idempotent (handle duplicate messages safely, e.g., by checkingmessageIdagainst recent history). - Reply Retries (Your App): Implement custom retry logic (e.g., background job queue like BullMQ) for critical replies if the Infobip API call fails transiently.
6. Security Considerations
Securing your webhook endpoint is vital.
- Webhook Secret / Authentication:
- Highly Recommended: Use Infobip's security features (Basic Auth, Signature Validation - check their docs).
- Implement validation in your route handler (Section 2.1). Store secrets securely (environment variables).
- HTTPS: Always use HTTPS.
ngrokprovides this locally. Production requires TLS termination (hosting, load balancer). - Input Validation:
- Validate webhook payload structure rigorously.
- Sanitize/validate SMS
textcontent if used in databases, commands, or displayed elsewhere to prevent injection attacks (XSS, SQLi).
- Rate Limiting: Protect against DoS/abuse using
@fastify/rate-limit.- Install:
npm install @fastify/rate-limit - Register in
server.js:javascript// src/server.js // ... other imports const rateLimit = require('@fastify/rate-limit'); // ... inside start() or before registering routes if using async register await fastify.register(rateLimit, { max: 100, // Example: Max requests per window per IP timeWindow: '1 minute' }); // ... register routes - Adjust limits appropriately.
- Install:
- Least Privilege: Use Infobip API keys with minimum required permissions.
- Dependency Updates: Keep dependencies updated (
npm audit).
7. Troubleshooting and Caveats
Common issues and things to watch out for:
- Webhook Not Received: Check URL (Infobip vs. actual), server status, firewalls,
ngrokstatus (temporary URLs!). - 401 Unauthorized: Mismatched secrets/credentials (Infobip config vs.
.env/app validation). - 400 Bad Request: Payload structure mismatch (check Infobip docs/config vs. your parsing logic in Section 2.1). Log the received
request.body. - 500 Internal Server Error: Check server logs (
fastify.log.error) for exceptions. - Reply Sending Fails: Check API Key/Base URL, Infobip balance/permissions, 'from'/'to' numbers (validity, Sender ID rules), Infobip status page.
- Infobip Free Trial Limitations: Often restricted to sending only to your verified number.
- Idempotency: Handle potential webhook retries without causing duplicate actions.
- Payload Variations: Ensure your handler matches the specific Infobip webhook event type/configuration.
8. Deployment Strategies
Moving from local development to production.
8.1 Obtain a Stable Public URL: Use cloud hosting (AWS, Google Cloud, Azure, Heroku, DigitalOcean, Render, Railway), load balancers, or API gateways for a permanent HTTPS endpoint.
8.2 Environment Configuration: Use secure environment variable management provided by your host (NOT .env files in production). Set NODE_ENV=production.
8.3 Process Management: Use pm2 or container orchestration (Docker, Kubernetes) for process management, restarts, and clustering (pm2 start src/server.js -i max).
8.4 Dockerization (Optional): Containerize for consistency.
Dockerfile:dockerfile# Dockerfile FROM node:18-alpine As base WORKDIR /app # Install dependencies only when package files change COPY package*.json ./ RUN npm ci --only=production # Copy application code COPY . . # Expose the port the app runs on EXPOSE 3000 # Define the command to run your app CMD [ ""node"", ""src/server.js"" ].dockerignore: Include.git,.env,node_modules/.- Build/Run:
docker build,docker run(pass environment variables securely).
8.5 CI/CD Pipeline: Automate testing and deployment using GitHub Actions, GitLab CI, Jenkins, etc. (Lint, Test, Build, Deploy).
8.6 Rollback Procedures: Plan for reverting failed deployments (previous Docker image, Git tag).
9. Verification and Testing
Ensure your application works correctly.
9.1 Manual Verification:
- Run app (local
ngrokor deployed). - Configure Infobip webhook URL correctly.
- Send test SMS to Infobip number.
- Check app logs for receipt, processing, and reply logs.
- Check phone for reply SMS.
- Check Infobip portal logs for webhook/SMS status.
9.2 Automated Testing (Recommended):
Implement unit and integration tests.
-
Install Testing Tools:
npm install --save-dev tap(orjest,supertest). -
Unit Tests: Test functions in isolation.
-
Integration Tests (Webhook): Simulate webhook requests using Fastify's
injectorsupertest.- Note on Test Setup: The example below uses Fastify's
inject. This typically works best ifserver.jsis refactored to export an asynchronousbuildfunction that creates and returns the Fastify instance, rather than starting the server immediately. You would then import and call thisbuildfunction in your test file. See Fastify's documentation on testing for details.
javascript// test/webhook.test.js (Example structure) const { test } = require('tap'); // Assuming server.js is refactored to export a build function: // const build = require('../src/app'); // Adjust path if needed test('POST /webhook/infobip should process valid message', async (t) => { // const app = await build(); // Build app instance for testing // t.teardown(() => app.close()); // Close app after test // --- If NOT refactoring server.js, testing becomes more complex --- // You might need to require('../src/server.js') which starts the server, // then find a way to make requests to it (less ideal). // OR mock the Fastify instance and route registration. // Refactoring for testability is recommended. t.comment('Test assumes server.js refactored to export a build function'); t.end(); // Placeholder end for demonstration return; // Skip actual execution in this example /* // Example test logic (if app instance 'app' is available) const mockPayload = { results: [ { /* ... valid message data ... */ } ], // ... other payload fields }; const response = await app.inject({ method: 'POST', url: '/webhook/infobip', payload: mockPayload, // headers: { 'x-webhook-secret': 'your-test-secret' } // If testing secret }); t.equal(response.statusCode, 200, 'should return status 200'); t.same(JSON.parse(response.payload), { status: 'received' }, 'should return correct payload'); // Add more assertions: check logs (requires logger injection/mocking), check mocks */ }); // Add more tests for invalid payloads, security, errors, etc. - Note on Test Setup: The example below uses Fastify's
-
Test Coverage: Use tools like
c8or Istanbul (nyc) to measure coverage.
Verification Checklist:
- Dependencies installed.
- Environment variables configured.
- Server starts.
- Webhook URL configured in Infobip.
- Security mechanism validated (if used).
- App publicly accessible.
- SMS triggers webhook.
- Logs show successful processing.
-
200 OKsent to Infobip. - Reply received (if implemented).
- Infobip logs confirm delivery/sending.
- Invalid requests rejected correctly (400, 401).
- Errors logged and handled.
- Automated tests pass (if implemented).
Complete Code Repository
A complete, working example of the code described in this guide can be found on GitHub.
This repository includes the project structure, package.json, example .env.example, .gitignore, and the source code files.
This guide provides a solid foundation for building a production-ready two-way SMS system using Fastify and Infobip. Remember to consult the official Infobip API documentation for the most up-to-date details on payload formats, authentication methods, and API capabilities. Happy coding!
Frequently Asked Questions
How to set up two-way SMS with Fastify?
Set up a Fastify server to receive incoming SMS messages via Infobip webhooks and send replies using the Infobip API. This involves configuring routes, installing necessary dependencies like `fastify`, `@infobip-api/sdk`, and `dotenv`, and setting up environment variables for your Infobip credentials and server configuration. The server will listen for incoming messages and trigger actions or automated replies.
What is the Infobip webhook URL for?
The Infobip webhook URL is the endpoint on your Fastify server that Infobip will send incoming SMS message data to. It's crucial to configure this correctly in your Infobip account portal and ensure your server is publicly accessible. Using a tool like ngrok during development can expose your local server temporarily for testing.
How to use Infobip API with Fastify?
Integrate the Infobip Node.js SDK (`@infobip-api/sdk`) into your Fastify application to send automated replies to incoming SMS messages. Instantiate the Infobip client with your API key and base URL, then use the `channels.sms.send()` method to send replies via the Infobip API. Make sure to handle potential errors during the API call.
Why does two-way SMS need webhooks?
Webhooks provide a way for Infobip to push real-time notifications to your application whenever an SMS message is received. This eliminates the need for constant polling and enables immediate responses, making it ideal for implementing two-way communication. The webhook acts as a listener for incoming messages.
How to secure Infobip webhook endpoint?
Secure your webhook endpoint by implementing a validation mechanism, such as checking a secret header or utilizing Basic Authentication if Infobip supports it. Consult the Infobip documentation for their specific security recommendations. Additionally, always use HTTPS for all communication and implement input validation to prevent attacks.
What is Fastify used for in two-way SMS?
Fastify serves as the lightweight, high-performance web framework for building your Node.js application. It handles incoming webhook requests from Infobip containing SMS messages and enables routing, logging, and processing of the data. It also manages outgoing reply requests to the Infobip API via the SDK.
How to send automated SMS replies with Infobip?
After receiving a webhook request, use the Infobip Node.js SDK to send automated SMS replies. Extract the sender's phone number from the message data and use `infobipClient.channels.sms.send()` to send a reply. Ensure the 'from' parameter is set to your Infobip number or a registered Alphanumeric Sender ID for deliverability.
What is the role of Node.js in this system?
Node.js provides the JavaScript runtime environment for the entire two-way SMS application. It allows you to execute JavaScript code on the server-side, handling the webhook requests, interacting with the Infobip API, and managing the logic for automated replies.
When should I add rate limiting to my SMS app?
Add rate limiting using `@fastify/rate-limit` as a security measure in production to protect your application from denial-of-service (DoS) attacks or abuse. Configure limits appropriate to your expected traffic, and adjust as needed. Rate limiting helps prevent overload by restricting excessive requests.
How to troubleshoot Infobip webhook not working?
If your Infobip webhook isn't working, double-check the webhook URL configured in your Infobip account matches your server's public URL. Verify your server is running and publicly accessible, check firewall settings, and ensure `ngrok` is still active if using it for local development. Inspect logs for errors.
How to handle Infobip webhook retries?
Infobip might retry sending webhooks if your server returns non-2xx HTTP status codes. Ensure your application is idempotent, meaning it can handle duplicate webhook requests without causing unintended side effects. Check message IDs to avoid processing the same message twice.
Can I use Docker for deploying my Fastify SMS app?
Yes, you can containerize your application with Docker for consistent deployments. Create a Dockerfile that includes the necessary instructions to build and run your Fastify application. Use `docker build` to create an image, then use `docker run` to launch the container. This also simplifies scaling with Kubernetes or other container orchestrators.
How to expose local Fastify server for Infobip webhook?
Use a tool like `ngrok` to temporarily create a public URL that tunnels to your local server during development. This allows Infobip to send webhook requests to your local application. Download, install, and authenticate `ngrok`, then run `ngrok http <your_port>` to create the tunnel.
What are environment variables in this project?
Environment variables store sensitive information like your Infobip API key, base URL, and webhook secret. These are loaded from a `.env` file during development using the `dotenv` package. In production, use secure environment management provided by your hosting platform. Never commit `.env` to version control.