Frequently Asked Questions
Set up a Fastify project with the Infobip SDK, create a /send-sms route, and configure the Infobip client with your API key and base URL. The route handler should extract recipient, sender, and message details from the request body and pass them to the Infobip SDK's send method. This abstracts the API interaction into a service layer within your Fastify app.
Free Infobip accounts can only send SMS messages to the phone number verified during registration. Attempts to send to other numbers will fail. This is a common issue for developers starting with the free trial, so ensure your recipient matches your registered number.
Fastify is a high-performance Node.js web framework known for its speed, extensibility, and excellent developer experience. It provides a robust foundation for building a production-ready SMS service with features like schema validation and easy plugin integration.
Rate limiting is crucial for preventing abuse, controlling costs, and protecting your application from overload. You should implement rate limiting as soon as possible, especially before deploying to production. The fastify-rate-limit plugin makes this easy.
No, using a free trial for production is not recommended due to the limitation of only being able to send to your registered number. Upgrade to a paid Infobip account for full functionality and remove sending restrictions.
The @infobip-api/sdk simplifies interaction with the Infobip API by handling authentication, API requests, and response parsing. It streamlines the SMS sending process within your Fastify application.
Infobip requires international format without the + sign or leading 00. The provided example code uses JSON Schema validation, and stricter validation with libphonenumber-js is recommended for more robust handling of diverse input formats.
Store your Infobip API key and base URL in a .env file and load them using the dotenv package. Ensure .env is added to your .gitignore file to prevent accidental commits. In production, use your deployment environment's secure secret management system.
Implement a try-catch block around the Infobip SDK call within your /send-sms route handler. Parse specific error details from error.response.data and return appropriate error responses to clients. Provide generic error messages for unexpected errors, and log more detailed information for troubleshooting.
Common errors include missing or incorrect API keys/base URLs in the .env file, attempting to send SMS to numbers other than your registered number on a free trial, incorrect phone number formatting, or network issues connecting to the Infobip API. The article covers troubleshooting steps for each.
401 errors usually indicate an invalid or expired API key. Verify that the API key in your .env file matches the active key in your Infobip dashboard and that your base URL is correct.
Consider message encoding if you're sending messages with non-GSM-7 characters (like emojis or certain accented letters). The Infobip API supports Unicode but may have different character limits and cost implications for multi-part messages.
Fastify's Pino logger provides a base. Log key events like requests, successes, and errors with context. In production, configure log levels, forward to a centralized system, and monitor metrics like API latency, error rates, and Infobip response codes.
Use exponential backoff with a library like async-retry. Only retry on specific transient error types (e.g., 503 Service Unavailable, network timeouts) and avoid retrying 4xx errors or successful submissions with uncertain status. Retries are not included in the example code for safety and simplicity.
This guide provides a complete walkthrough for building a production-ready service using Fastify (a high-performance Node.js web framework) to send SMS messages via the Infobip API. We will cover everything from initial project setup to deployment and monitoring best practices.
By the end of this tutorial, you will have a functional Fastify application with an API endpoint capable of sending SMS messages programmatically. This solves common needs like sending notifications, alerts, verification codes, or marketing messages directly from your backend application.
Project Overview and Goals
POST /send-sms
) that accepts a recipient phone number, sender ID, and message text, and uses the Infobip API to send the SMS./send-sms
) that securely and reliably sends SMS messages via Infobip, including basic validation, error handling, and logging.System Architecture
The basic flow is straightforward:
(Note: Rendering of the above diagram depends on the platform's support for Mermaid syntax.)
1. Setting up the Project
Let's initialize our Node.js project and install the necessary dependencies.
Create Project Directory: Open your terminal and create a new directory for the project, then navigate into it.
Initialize npm Project: Run
npm init
and follow the prompts. You can accept the defaults for most questions.This creates a
package.json
file.Install Dependencies: We need Fastify, the Infobip SDK, and
dotenv
for environment variables.fastify
: The core web framework.@infobip-api/sdk
: Simplifies interactions with the Infobip API.dotenv
: Loads environment variables from a.env
file intoprocess.env
.Install Development Dependencies (Optional but Recommended): Tools like
nodemon
help during development by automatically restarting the server on file changes.Configure
package.json
Scripts and Enable ES Modules: Add scripts to yourpackage.json
for easily running and developing your application. Crucially, add""type"": ""module""
to enable theimport
/export
syntax used in the code examples.Create Project Structure: Set up a basic directory structure for organization.
index.js
: The main application entry point.routes/
: Directory to hold route definitions.routes/sms.js
: File specifically for SMS-related routes.config/
: Directory for configuration files.config/infobip.js
: Configuration specific to the Infobip client..env
: Stores sensitive environment variables (API keys_ etc.). Do not commit this file..env.example
: A template showing required environment variables. Commit this file..gitignore
: Specifies intentionally untracked files that Git should ignore.Configure
.gitignore
: Addnode_modules
and.env
to your.gitignore
file to prevent committing them.Set up Environment Variables: Define the required environment variables in
.env.example
and.env
.Copy
.env.example
to.env
and fill in your actual Infobip API Key and Base URL. You can find these in your Infobip account dashboard_ typically under API Keys management. The Base URL is specific to your account.2. Implementing Core Functionality
Now_ let's implement the core logic for sending SMS messages using the Infobip SDK within a Fastify route.
Configure Infobip Client: Create a reusable Infobip client instance.
process.exit(1)
ensures the application fails fast if critical configuration is missing.Create the SMS Sending Route: Define the Fastify route handler that will receive requests and trigger the SMS sending process.
/send-sms
endpoint usingfastify.post
.sendSmsSchema
) to automatically validate the request body. This ensures required fields (to
,from
,text
) are present and meet basic type/format criteria before our handler logic runs. This is crucial for robustness and security.infobipClient.channels.sms.send
with the payload constructed from the request body. The SDK handles the underlying HTTP request, authentication, and URL construction.request.log
for contextual logging (info for success, error for failures).try...catch
block handles potential errors during the API call. It attempts to parse specific Infobip errors fromerror.response.data
for better client feedback, falling back to a generic 500 error.Set up the Main Fastify Application: Configure the main server file to load environment variables, register routes, and start listening.
/api/v1
), includes a basic/health
check endpoint (good practice for monitoring), and starts the server, handling potential startup errors. Rate limiting is commented out but shown as an example of plugin registration.3. Building a Complete API Layer
Our core functionality already includes the API endpoint. Let's refine it based on best practices.
Authentication/Authorization: For this simple example, we assume the API is called internally or protected by an upstream gateway. For external access, you would implement mechanisms like API Key validation (passed via headers), JWT tokens, or OAuth. This would typically involve Fastify hooks or plugins (
fastify-auth
,fastify-jwt
).Request Validation: We already implemented robust request validation using Fastify's schema feature in
routes/sms.js
. This prevents malformed requests from reaching our core logic.API Endpoint Documentation: The schema definition in
routes/sms.js
serves as basic documentation. For more comprehensive documentation, consider integratingfastify-swagger
which can automatically generate an OpenAPI (Swagger) specification from your routes and schemas.Testing with
curl
/ Postman:Request (
curl
): Replace placeholders with your actual data and running server address.YOUR_RECIPIENT_PHONE_NUMBER
must be the phone number you registered with Infobip.YourSenderID
should adhere to Infobip's rules (alphanumeric 3-11 chars, or numeric 3-16).Success Response Example (JSON, Status 200): (Structure based on Infobip API documentation)
Error Response Example (JSON, Status 400 - Validation Error):
Error Response Example (JSON, Status ~500 - Infobip API Error): (Example: Invalid API Key)
(Note: Exact error structure from Infobip might vary slightly)
4. Integrating with Infobip
We've already set up the core integration using the SDK.
.env
file and loaded inconfig/infobip.js
.INFOBIP_API_KEY
: Your secret API key for authentication. Obtain from Infobip Dashboard -> Developers -> API Keys. Treat this like a password.INFOBIP_BASE_URL
: Your account-specific API endpoint URL. Also found on the API Keys page in the Infobip dashboard. Format is usuallyyour-unique-id.api.infobip.com
..env
and adding.env
to.gitignore
prevents accidental commits. In production, use your deployment environment's secret management system (e.g., AWS Secrets Manager, Kubernetes Secrets, Heroku Config Vars).5. Error Handling, Logging, and Retry Mechanisms
try...catch
around external API calls (Infobip).error.response.data
) when available, returning relevant status codes (e.g., 401 Unauthorized, 403 Forbidden, 5xx Service Unavailable) and details.logger: true
) provides efficient JSON logging.info
,warn
,error
) and forward logs to a centralized logging system (e.g., Datadog, ELK stack, Splunk) for analysis and alerting.infobipClient.channels.sms.send
call in a loop with a delay.async-retry
can simplify this.6. Database Schema and Data Layer
This specific service (sending a single SMS on demand) does not inherently require a database.
sms_logs
table).prisma migrate dev
,knex migrate:latest
).messageId
,timestamp
,recipient
).For this guide, we focus solely on the stateless action of sending an SMS.
7. Security Features
routes/sms.js
). This prevents basic injection attacks and ensures data types are correct.DOMPurify
(for HTML) or custom logic might be needed depending on the data. For simple phone numbers and sender IDs, strict validation is often sufficient. However, sanitizing free-form text input (text
) might be considered if it's rendered or processed insecurely by downstream systems, even if Infobip handles it safely. Fastify typically handles basic JSON parsing safely.npm install @fastify/rate-limit
index.js
(as shown in the commented-out example).max
requests andtimeWindow
. Adjust based on expected load and Infobip's limits..env
, environment variables in production).8. Handling Special Cases
447123456789
, not07123456789
or+44...
). Your validation schema or logic should enforce this. Consider using a library likelibphonenumber-js
for robust parsing and validation if accepting varied input formats.9. Performance Optimizations
For a simple API proxy like this, performance is largely dictated by the network latency and the speed of the external API (Infobip).
async/await
correctly to avoid blocking the Node.js event loop.autocannon
(npm install -g autocannon
) to test how many requests per second your endpoint can handle before hitting Infobip limits or resource constraints.0x
to identify CPU bottlenecks if performance issues arise within your own code (unlikely for this simple case).10. Monitoring, Observability, and Analytics
/health
endpoint provides a basic check for monitoring systems (like Kubernetes liveness/readiness probes or uptime checkers)./send-sms
route.pm2
provide some monitoring.status.name
from the response).11. Troubleshooting and Caveats
Error: Infobip API Key or Base URL not found...
: Ensure.env
file exists in the project root, is correctly named, and containsINFOBIP_API_KEY
andINFOBIP_BASE_URL
with valid values. Restart the server after creating/modifying.env
.401 Unauthorized
/{""requestError"": {""serviceException"": {""text"": ""Invalid login details""}}}
: API Key is incorrect or expired. Verify the key in.env
matches the one in the Infobip dashboard. Ensure theINFOBIP_BASE_URL
is also correct for that key.to
number (e.g.,EC_INVALID_DESTINATION_ADDRESS
): Phone number format is likely incorrect. Ensure it's in international format without+
or leading00
(e.g.,447123456789
).EC_MESSAGE_NOT_ALLOWED_ON_FREE_TRIAL
/ Sending Fails Silently: You are using a free trial account and trying to send to a number other than the one registered with Infobip. This is the most common issue for beginners. Verify the recipient number matches your registered number exactly.from
ID (e.g.,EC_INVALID_SENDER
): Sender ID doesn't meet Infobip's format requirements (length, characters) or may be restricted in the destination country.ECONNREFUSED
/ETIMEDOUT
: Network issue connecting to the Infobip API. Check server connectivity, firewalls, and Infobip's service status page.400 Bad Request
with validation message: The request body sent to/send-sms
is missing required fields or has incorrect data types (e.g., sending a number instead of a string). Check thecurl
or client request payload against the schema inroutes/sms.js
.@infobip-api/sdk
. Check their respective documentation for requirements. This guide assumes Node.js v18+ and recent versions of the libraries.12. Deployment and CI/CD
INFOBIP_API_KEY
,INFOBIP_BASE_URL
,PORT
,HOST=0.0.0.0
) via their dashboard/CLI, and deploy. They handle infrastructure, scaling (to an extent), and often TLS termination.Dockerfile
to package your app. Deploy the container to services like AWS ECS/EKS, Google Cloud Run/GKE, or a VM with Docker installed. Requires more infrastructure management.pm2
(npm install -g pm2
,pm2 start index.js
) to run the app reliably. Requires setting up a reverse proxy (Nginx/Caddy) for TLS and load balancing.npm ci --omit=dev
).fly deploy
,heroku deploy
, update Kubernetes deployment).