Frequently Asked Questions
Set up a Node.js project with Fastify, the Plivo Node.js SDK, and dotenv. Create routes in Fastify to handle incoming SMS requests. Configure the Plivo client with your credentials, then use the client's API within your Fastify route to send messages based on incoming requests. Ensure your destination numbers are verified in your Plivo account if using a trial version.
The Plivo sender number should be in E.164 format, for example, +12025551234. This international standard ensures consistent formatting for phone numbers and is required by Plivo for sending SMS. The plus sign '+' followed by the country code and the number is required.
Fastify's schema validation automatically validates incoming requests, reducing boilerplate code for manual checks and improving reliability. This built-in feature uses JSON Schema to define expected request parameters. Schema validation ensures your API receives correctly formatted data and strengthens security by preventing injection attacks.
Always use environment variables to store sensitive information like your Plivo Auth ID, Auth Token, and sender number. Place these in a `.env` file, and load it using `dotenv`. Never directly embed credentials in your code to prevent security vulnerabilities.
Alphanumeric sender IDs are subject to specific regulations depending on the destination country. While some countries permit their usage (potentially requiring pre-registration), countries like the US and Canada usually require a Plivo long code or Toll-Free number for sending SMS.
Wrap the Plivo API call in a try...catch block within your Fastify route handler to handle potential errors during the API call. Log detailed error messages and return appropriate HTTP status codes along with informative JSON error responses.
The `.env` file stores sensitive credentials, including the Plivo Auth ID, Auth Token, and sender number. This file should never be committed to version control and should be added to the `.gitignore` file to keep credentials private. The `dotenv` library is used to load environment variables from `.env` into your application.
Use npm or yarn to install the necessary packages: `npm install fastify plivo dotenv`. Fastify is the web framework, `plivo` is the Plivo Node.js SDK, and `dotenv` loads environment variables from your `.env` file.
A typical project structure includes directories for routes (`src/routes`), configuration (`src/config`), and the main server file (`src/server.js`). The routes directory contains files defining API endpoints. The configuration directory keeps Plivo setup logic.
Standard SMS messages using the GSM-7 character set allow up to 160 characters per segment. Messages with Unicode characters (like emojis) switch to UCS-2 encoding, limiting segments to 70 characters. Plivo automatically handles this encoding and concatenation of longer messages.
Error handling, through try...catch blocks and robust logging, is crucial for managing issues such as network problems, incorrect Plivo credentials, invalid numbers, and rate limits. Logging helps diagnose and fix problems quickly.
Use tools like `curl` or Postman to send test requests to the `/api/sms/send` endpoint. Verify that the destination number receives the SMS and that your Fastify server logs the request and response information correctly.
Secure your API by using schema validation for all inputs, storing API keys as environment variables, implementing rate limiting using libraries like `fastify-rate-limit`, and always using HTTPS in production.
Performance optimizations include using Fastify's built-in efficiency, leveraging async/await for non-blocking operations, efficient logging, and load testing to identify potential bottlenecks under stress.
Implement health checks, monitor key metrics like request latency, error rates, and resource utilization. Use logging and error tracking tools and set up alerts based on critical thresholds. Create dashboards to visualize key metrics and service health.
This guide provides a step-by-step walkthrough for building a Node.js application using the Fastify framework to send SMS messages via the Plivo API. We will cover project setup, core implementation, error handling, security considerations, and deployment basics.
By the end of this guide, you will have a functional Fastify API endpoint capable of accepting requests and triggering SMS messages through Plivo, along with the foundational knowledge to expand upon it.
Project Overview and Goals
Goal: To create a simple, robust, and scalable API endpoint using Fastify that sends SMS messages via the Plivo communication platform.
Problem Solved: Provides a backend service that abstracts the Plivo SMS sending functionality, enabling other services or frontend applications to send SMS messages easily through a standard REST API call without needing direct access to Plivo credentials or SDKs.
Technologies:
.env
file intoprocess.env
, crucial for managing sensitive credentials securely.System Architecture:
Prerequisites:
`Phone Numbers`
section of the Plivo console. This will be your sender number (src
). Note specific regulations for sender IDs in different countries; a Plivo number is generally required for sending to the US and Canada.`Phone Numbers`
>`Sandbox Numbers`
before you can send messages to them.Final Outcome: A running Fastify server with a single API endpoint (
POST /sms/send
) that accepts a destination number and message text, sends the SMS via Plivo, and returns a confirmation or error.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 your project, then navigate into it.
Initialize Node.js Project: Initialize the project using npm, creating a
package.json
file. The-y
flag accepts default settings.Install Dependencies: Install Fastify, the Plivo Node.js SDK, and
dotenv
.Set Up Project Structure: Create a basic structure for organization.
src/server.js
: Main application entry point, Fastify server setup.src/routes/sms.js
: Defines the routes related to SMS functionality.src/config/plivo.js
: Initializes and configures the Plivo client..env
: Stores sensitive credentials (Plivo Auth ID, Token, Number). Never commit this file to version control..gitignore
: Specifies intentionally untracked files that Git should ignore.Configure
.gitignore
: Addnode_modules
and.env
to your.gitignore
file to prevent them from being checked into Git..gitignore
Configure Environment Variables (
.env
): Open the.env
file and add your Plivo credentials and phone number. Replace the placeholder values with your actual credentials found in the Plivo console..env
PLIVO_AUTH_ID
: Your Plivo account identifier.PLIVO_AUTH_TOKEN
: Your Plivo account secret token.PLIVO_SENDER_NUMBER
: The SMS-enabled Plivo phone number you purchased, in E.164 format.2. Implementing Core Functionality (Sending SMS)
Now, let's write the code to initialize the Plivo client and set up the Fastify server.
Configure Plivo Client: Set up the Plivo client instance using the environment variables.
src/config/plivo.js
dotenv
here? We load environment variables early to ensure the Plivo client can be initialized correctly.Create the SMS Sending Route: Define the Fastify route that will handle the SMS sending request.
src/routes/sms.js
async/await
? Simplifies handling asynchronous operations like the Plivo API call.libphonenumber-js
offers more robust validation.try...catch
? Essential for handling potential errors during the API call to Plivo (network issues, invalid credentials, API errors, etc.).Set Up the Fastify Server: Configure and start the Fastify server, registering the SMS routes.
src/server.js
logger: true
? Enables request/response logging and allows usingfastify.log
for custom logs.register
withprefix
? Organizes API routes under a common base path (e.g.,/api/sms/send
).0.0.0.0
? Makes the server accessible from outside its container/machine in development or production (localhost/127.0.0.1 only allows local connections)./health
endpoint is standard practice for monitoring services and load balancers.Add Start Script to
package.json
: Add a script to easily start your server.package.json (additions)
3. Building a Complete API Layer
Our core API endpoint (
POST /api/sms/send
) is already set up. Let's document and demonstrate how to test it.API Endpoint Documentation:
POST
/api/sms/send
to
(string, required): The destination phone number in E.164 format (e.g.,+12025551234
).text
(string, required): The content of the SMS message. Max length depends on encoding (GSM-7 or UCS-2).message
(string): Confirmation message (e.g.,"SMS sent successfully!"
).message_uuid
(array of strings): An array containing the unique identifier assigned by Plivo to the message request.Testing with
curl
:Start the Server:
You should see output indicating the server is listening on port 3000 (or your configured
PORT
).Send a Request: Open another terminal window and run the following
curl
command. Replace+1DESTINATIONNUMBER
with a verified phone number (if using a trial account) in E.164 format.Check Response: You should receive a JSON response like the success example above, and the destination phone should receive the SMS shortly after. Check your server logs (
npm start
terminal) for detailed request/response information and potential errors.4. Integrating with Necessary Third-Party Services (Plivo)
We've already integrated Plivo, but let's reiterate the key configuration steps.
Obtain Credentials:
`Phone Numbers`
>`Your Numbers`
. If you don't have one, click`Buy Number`
, search for SMS-enabled numbers in your desired region, and purchase one. Copy the number in E.164 format.`Phone Numbers`
>`Sandbox Numbers`
to add and verify destination numbers you want to send messages to during trial.Secure Credential Storage:
.env
file in the project root..env
is listed in your.gitignore
file to prevent accidentally committing secrets to version control.Environment Variables Explained:
.env
Fallback Mechanisms (Conceptual): For this basic guide, we don't implement automatic fallback. In a production system, if Plivo experiences downtime, you might consider:
5. Implementing Error Handling, Logging, and Retry Mechanisms
We've incorporated basic error handling and logging.
try...catch
blocks around external API calls (Plivo). Catch errors, log them with details (fastify.log.error
), and return appropriate HTTP status codes (4xx for client errors, 5xx for server/Plivo errors) and informative JSON error messages to the client. Map Plivo errors to relevant HTTP statuses where possible.logger: true
) provides efficient JSON-based logging for requests, responses, and errors. Custom logs (fastify.log.info
,fastify.log.error
) add context. In production, logs should be collected and forwarded to a centralized logging system (e.g., Datadog, ELK stack, Splunk).async-retry
or build custom logic within yourcatch
block. For this guide's scope, we only log the error.Testing Error Scenarios:
to
ortext
field, or with an invalid phone number format (e.g.,12345
). Expect a 400 error from Fastify validation or your custom check.PLIVO_AUTH_ID
orPLIVO_AUTH_TOKEN
in.env
and restart the server. Send a valid request. Expect a 401 Unauthorized error (or similar) from the Plivo API, which your error handler should catch and return as a 4xx or 5xx error.PLIVO_SENDER_NUMBER
. Expect an error from Plivo.6. Creating a Database Schema and Data Layer
Not Applicable: This specific microservice focuses solely on the stateless action of sending an SMS via an external API. It does not require its own database to store state related to the messages (Plivo handles the message persistence and status tracking).
If you needed to track requests, log message attempts internally, or associate messages with users in your system, you would add a database (e.g., PostgreSQL, MongoDB) and a data access layer (e.g., using an ORM like Prisma or Sequelize, or a MongoDB driver).
7. Adding Security Features
Input Validation: Implemented using Fastify's schema validation (
sendSmsSchema
). This prevents malformed requests and basic injection attempts in theto
andtext
fields. Sanitize or strictly validate any user input that might be used in logs or other contexts.Secure Credential Handling: Using
.env
and.gitignore
prevents exposure of Plivo API keys. In production, use environment variables provided by the deployment platform or a dedicated secrets management system (e.g., HashiCorp Vault, AWS Secrets Manager).Rate Limiting: Protect against brute-force attacks or abuse by limiting the number of requests per IP address or user. Use the
fastify-rate-limit
plugin.npm install fastify-rate-limit
server.js
:Security Headers: Use a plugin like
@fastify/helmet
to set various HTTP headers (likeX-Frame-Options
,Strict-Transport-Security
, etc.) to protect against common web vulnerabilities.npm install @fastify/helmet
server.js
:HTTPS: Always run your API over HTTPS in production using a reverse proxy like Nginx or your cloud provider's load balancer to handle SSL termination.
8. Handling Special Cases Relevant to the Domain
+
followed by country code and number, no spaces or dashes) as required by Plivo.src
). Alphanumeric sender IDs are often blocked.`MyCompany`
), which may need pre-registration. Check Plivo's documentation for country-specific regulations. Our code uses thePLIVO_SENDER_NUMBER
which works for US/Canada.9. Implementing Performance Optimizations
async/await
ensures Node.js's event loop is not blocked during the Plivo API call.k6
,autocannon
, orwrk
to simulate traffic and identify bottlenecks under load. Monitor CPU, memory, and event loop lag during tests.0x
to analyze CPU usage and identify performance bottlenecks within your code.10. Adding Monitoring, Observability, and Analytics
/health
endpoint provides a basic mechanism for load balancers or monitoring systems (like UptimeRobot, Nagios, Datadog Synthetics) to check if the service is running.prom-client
for Prometheus integration or platform-specific agents (Datadog, New Relic).11. Troubleshooting and Caveats
Error: Plivo Auth ID or Auth Token not found...
: EnsurePLIVO_AUTH_ID
andPLIVO_AUTH_TOKEN
are correctly set in your.env
file and the file is being loaded (require('dotenv').config();
).401 Unauthorized
(from Plivo): Incorrect Auth ID or Auth Token. Double-check values in.env
against the Plivo console.Invalid 'src' parameter
/Invalid 'dst' parameter
(from Plivo): Phone numbers are likely not in E.164 format or are otherwise invalid. Ensure numbers start with+
and country code. CheckPLIVO_SENDER_NUMBER
in.env
and theto
number in the request.Message Sending disallowed to Sandbox Number
(from Plivo): You are using a trial account and trying to send to a number not verified in`Sandbox Numbers`
on the Plivo console. Add and verify the destination number.Message Sender 'src' number not owned by you or is invalid
(from Plivo): ThePLIVO_SENDER_NUMBER
in.env
is incorrect or not associated with your Plivo account.FST_ERR_VALIDATION
(400 Bad Request): The request body doesn't match the schema defined insrc/routes/sms.js
(e.g., missingto
ortext
, or they are not strings).ENOTFOUND
/ETIMEDOUT
: Network issues connecting from your server to the Plivo API. Check server connectivity, firewalls, and Plivo's service status page.package.json
. Check the respective libraries' documentation for compatibility notes if issues arise.12. Deployment and CI/CD
Basic Deployment (Conceptual):
npm install --production
can skip devDependencies).PLIVO_AUTH_ID
,PLIVO_AUTH_TOKEN
,PLIVO_SENDER_NUMBER
,PORT
,NODE_ENV=production
) on the target server or container environment. Do not deploy the.env
file directly; use the platform's environment variable management.node src/server.js
).CI/CD Pipeline (Conceptual):
A typical pipeline using services like GitHub Actions, GitLab CI, or Jenkins:
npm ci
(usespackage-lock.json
for deterministic installs).