Frequently Asked Questions
Use Node.js with Express.js to create an API endpoint and integrate the Plivo Node.js SDK. This endpoint receives recipient numbers and the message, then uses Plivo to send the SMS messages concurrently. This setup is ideal for marketing campaigns, notifications, and alerts, automating the process of reaching your target audience.
Plivo is a cloud communications platform that provides the necessary APIs for sending SMS messages. The Node.js SDK interacts with these APIs, making it possible to send individual or bulk SMS messages programmatically. It handles the complexities of message delivery and provides tools for managing your SMS campaigns.
Dotenv is crucial for storing API keys and other credentials securely. It loads environment variables from a .env file, keeping sensitive information out of your codebase and version control. Ensure PLIVO_AUTH_ID, PLIVO_AUTH_TOKEN, and PLIVO_SENDER_ID are properly set in your .env file and loaded using dotenv.config() at application startup.
Promise.allSettled is essential when sending bulk SMS messages because it ensures that all send attempts are made, even if some fail. Unlike Promise.all, which rejects on the first error, Promise.allSettled waits for all promises to either fulfill or reject, providing a complete report of successes and failures. This is crucial for understanding the results of a bulk SMS campaign.
Alphanumeric Sender IDs might be possible for countries outside the US and Canada. However, for sending SMS to the US and Canada, you must use a Plivo-rented, SMS-enabled phone number due to regulations and carrier restrictions. Check Plivo's SMS API Coverage page for country-specific rules regarding sender IDs.
Create a POST route in your Express app (e.g., /api/campaigns) that receives a JSON payload with an array of recipient phone numbers ("recipients") and the message body ("message"). The route handler should validate the input, call the SMS sending service, and return a report of the send attempts. This endpoint serves as the entry point for initiating your SMS campaigns.
Express.js provides the framework for creating the API endpoint that receives campaign requests. It handles routing, middleware (like body parsing for JSON payloads), and error handling. Express simplifies the process of building a web server and managing API interactions, making it the foundation of our SMS campaign application.
For production applications, use dedicated validation libraries such as 'joi' or 'express-validator' to ensure phone numbers adhere to E.164 format. This helps prevent sending errors due to invalid recipient data. 'express-validator' offers specific validators like isMobilePhone('any', { strictMode: true }) which can further enhance your validation process.
Use a structured logging library like Winston or Pino, logging in JSON format for easier analysis by log management systems. Log essential information like timestamps, request details, Plivo message UUIDs, and errors. This helps in debugging issues, tracking messages, and monitoring the health of your SMS service. Ensure sensitive information isn't logged.
Robust error handling is essential to manage issues like network problems, invalid phone numbers, and Plivo API errors (like rate limiting). Implementing try-catch blocks, using Promise.allSettled, and potentially adding retry mechanisms with exponential backoff ensures that issues are handled gracefully without crashing the application and that you get a complete picture of campaign results.
Consider a relational database schema with tables for contacts (phone numbers, subscription status), campaigns (message, schedule), and campaign_sends (linking campaigns to contacts and storing send status, Plivo message UUIDs). This structure facilitates tracking message delivery, managing contacts, and analyzing campaign performance.
Use the 'express-rate-limit' middleware to prevent API abuse and protect your Plivo account balance. This middleware lets you limit the number of requests from a specific IP address within a time window. It's crucial for preventing unexpected charges and maintaining the stability of your SMS service.
Store your Plivo Auth ID, Auth Token, and sender ID in a .env file, ensuring this file has restricted permissions and is never committed to version control. Utilize dotenv.config() to load these variables into process.env at application start, keeping sensitive information separate from your codebase.
Plivo requires phone numbers in E.164 format (e.g., +14155551234) for accurate message delivery. Ensure your application validates and normalizes phone numbers to this format, using validation libraries like 'express-validator' and its isMobilePhone validator, potentially adding a custom check for the leading '+' character, for improved reliability.
Use libraries like 'async-retry' or 'p-retry' to implement application-level retries with exponential backoff for transient errors (e.g., network issues, rate limiting). Be mindful of Plivo's API error codes and retry only recoverable errors, avoiding retrying on invalid numbers or insufficient funds. This enhances resilience and improves message deliverability.
> ⚠️ IMPORTANT FILENAME NOTICE: This article file is named "plivo-node-js-next-js-nextauth-marketing-campaigns.md" but contains Express.js content, NOT Next.js or NextAuth.js content. The guide implements a traditional Express.js REST API server. If you need Next.js App Router with NextAuth v5 (Auth.js) integration, you'll need substantial modifications including Next.js Route Handlers, server actions, and NextAuth v5 configuration. This notice will remain until the filename or content is corrected. > > ---
Build Bulk SMS Marketing Campaigns with Plivo, Node.js, and Express.js
This guide provides a complete walkthrough for building a backend system that sends bulk SMS marketing messages using Node.js, Express, and the Plivo Communications API. You'll learn everything from initial project setup to deployment considerations, focusing on creating a robust and scalable foundation.
By the end of this tutorial, you'll have a functional Express application with an API endpoint that accepts a list of phone numbers and a message body, then uses Plivo to send SMS messages concurrently for efficient campaign execution. This solves the common need for businesses to programmatically reach their audience via SMS for marketing, notifications, or alerts.
Project Overview and Goals
Goal: Create a simple yet robust Node.js service that sends SMS messages in bulk via an API endpoint, leveraging Plivo for SMS delivery.
Problem Solved: Automates the process of sending marketing or notification SMS messages to a list of recipients, handling concurrency and basic error logging.
Technologies:
.env
file intoprocess.env
. Essential for managing sensitive credentials.System Architecture:
The system follows this basic flow:
POST
request to the/api/campaigns
endpoint of the Node.js/Express App.Expected Outcome:
POST /api/campaigns
) that accepts JSON payload:{ "recipients": ["+1…", "+1…"], "message": "Your message here" }
.Prerequisites:
ngrok
(Optional, but recommended for testing incoming messages if needed later, e.g., for handling replies or delivery reports via webhooks, which is beyond the scope of this initial guide): Install ngrok.Understanding SMS Marketing Compliance (2025 Requirements)
Before implementing your SMS marketing system, you must understand and comply with current regulations. Non-compliance can result in fines of $500–$1,500 per violation and class-action lawsuits.
TCPA Compliance Requirements (Updated April 2025)
The Telephone Consumer Protection Act (TCPA) governs SMS marketing in the United States. New rules effective April 11, 2025 expanded compliance requirements:
1. Express Written Consent:
2. Expanded Opt-Out Recognition:
3. Time Restrictions:
4. Required Documentation:
10DLC Registration Requirements
A2P 10DLC (Application-to-Person 10-Digit Long Code) registration is mandatory for all businesses sending SMS at scale to US recipients:
What You Must Do:
$4) + recurring campaign fees ($10/month per campaign)Consequences of Non-Registration:
Registration Timeline: Allow 1 – 2 weeks for approval. Start this process before implementing your system.
See Plivo's 10DLC Registration Guide for complete instructions.
1. Setting up the Project
Initialize your 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: Create a
package.json
file to manage project dependencies and scripts.(The
-y
flag accepts the default settings.)Install Dependencies: Install Express for the web server, Plivo's Node.js SDK to interact with their API, and
dotenv
for managing environment variables.(Note: Modern Express versions include body-parsing capabilities, so you don't need
body-parser
separately).Create Project Structure: A good structure helps maintainability. Create some basic directories and files.
src/
: Contains your main application logic.config/
: For configuration files (like Plivo client setup).routes/
: Defines API endpoints.services/
: Contains business logic (like sending SMS)..env
: Stores environment variables (API keys, etc.). Never commit this file to Git..gitignore
: Specifies intentionally untracked files that Git should ignore.Configure
.gitignore
: Addnode_modules
and.env
to your.gitignore
file to prevent committing dependencies and sensitive credentials.Set up Environment Variables (
.env
): You need your Plivo Auth ID, Auth Token, and a Plivo phone number (or Sender ID where applicable).Phone Numbers
→Buy Numbers
. Search for and purchase an SMS-enabled number suitable for your region (required for sending to US/Canada). If you're sending outside US/Canada, you might use an Alphanumeric Sender ID (see Caveats section)..env
: Open the.env
file and add your credentials:Replace the placeholder values with your actual credentials and number.
Why
dotenv
? It keeps sensitive information like API keys out of your codebase, making it more secure and easier to manage different configurations for development, staging, and production environments.2. Implementing Core Functionality
Implement the core logic for sending SMS messages via Plivo.
Configure Plivo Client: Centralize the Plivo client initialization.
Why centralize? This ensures you initialize the client only once and makes it easily accessible throughout the application via
require('../config/plivo')
.Create SMS Sending Service: This service contains the function responsible for sending a single SMS and the bulk sending logic.
Why
Promise.allSettled
? For bulk operations, you often want to attempt all actions even if some fail.Promise.all
would reject immediately on the first error.Promise.allSettled
waits for all promises to either fulfill or reject, giving you a complete picture of the outcomes. Map the results to provide a clear success/failure report. Whyasync/await
? It makes asynchronous code (like API calls) look and behave a bit more like synchronous code, improving readability compared to nested.then()
calls.3. Building the API Layer
Create the Express route that receives campaign requests and triggers the SMS service.
Create Campaign Route: This file defines the endpoint for initiating SMS campaigns.
recipients
andmessage
from the request body (req.body
).joi
orexpress-validator
) is recommended for production.sendBulkSms
service function.Set up Express App: Configure the main Express application to use middleware and mount the router.
express
and your campaign router.express.json()
middleware is crucial for parsing the JSON payload sent to your API./health
endpoint is added for basic monitoring./api/campaigns
.Create Server Entry Point: This file starts the actual HTTP server.
Add Start Script: Modify your
package.json
to add a convenient start script.Run the Application:
You should see output indicating the server is running on port 3000.
4. Integrating with Plivo (Deep Dive)
You've already set up the client, but here are the key integration points:
PLIVO_AUTH_ID
andPLIVO_AUTH_TOKEN
are mandatory. They authenticate your application with Plivo's API..env
and access viaprocess.env
. Never hardcode them in your source code. Ensuredotenv.config()
is called once at your application's entry point (src/app.js
in this case).PLIVO_SENDER_ID
): This is the "From" number or ID shown to the recipient.+14155551234
) is required for sending to US/Canada. Must be a Plivo number you own/rented."MyBrand"
). See the "Caveats" section. Check Plivo's SMS API Coverage page for country-specific rules..env
asPLIVO_SENDER_ID
.5. Error Handling, Logging, and Retry Mechanisms
Our current setup includes basic error handling and logging. Let's refine it.
smsService
catches errors during the Plivo API call (sendSingleSms
) and logs them with recipient info.sendBulkSms
usesPromise.allSettled
and compiles a detailed report, distinguishing successes from failures.routes/campaign.js
) catches errors during request processing (validation, service calls) and returns appropriate HTTP status codes (400 for bad requests, 500 for server errors).app.js
catches any unhandled exceptions.Currently using
console.log
andconsole.error
. For production, use a dedicated logging library likewinston
orpino
.Setup (Example with Winston):
Create a logger configuration (e.g.,
config/logger.js
):Replace
console.log/error
calls withlogger.info()
,logger.warn()
,logger.error()
.Log Analysis: JSON logs are easier to parse by log management systems (like Datadog, Splunk, ELK stack). Log unique identifiers (like
messageUuid
from Plivo) to trace requests.Plivo handles some level of retries internally for deliverability.
For transient network errors or specific Plivo API errors (e.g., rate limits -
429 Too Many Requests
), you might implement application-level retries.Strategy: Use exponential backoff (wait longer between retries).
Example Concept (in
sendSingleSms
):Recommendation: While the above illustrates the concept, using established libraries like
async-retry
orp-retry
is strongly recommended for production code. They handle edge cases and configuration more robustly.Caution: Be careful not to retry non-recoverable errors (e.g., invalid number
400
, insufficient funds402
). Check Plivo's API error codes and retry logic documentation. Only retry errors that are likely temporary.6. Database Schema and Data Layer (Conceptual)
While this guide focuses on sending, a real marketing platform needs data persistence.
Need: Store contacts/subscribers, campaign details (message, target list, schedule), send status (
messageUuid
, delivered, failed), and potentially track responses or unsubscribes.Schema Example (Conceptual - e.g., using PostgreSQL):
(An Entity Relationship Diagram would visually represent these relationships).
Data Access: Use an ORM (like Sequelize, Prisma, TypeORM) or a query builder (like Knex.js) to interact with the database from Node.js. This involves setting up database connections, defining models/schemas in code, and writing queries/mutations.
Implementation:
pg
,sequelize
, etc.)..env
).campaign_sends
records before sending.campaign_sends
withplivo_message_uuid
and status after sending attempts.campaign_sends
status (delivered
,failed
, etc.).7. Adding Security Features
Security is paramount, especially when handling user data and API keys.
Input Validation:
Already implemented basic checks in
routes/campaign.js
.Enhancement: Use robust libraries like
joi
orexpress-validator
for complex validation (e.g., ensuring phone numbers match E.164 format, checking message length).Example (using
express-validator
):Sanitization: While less critical for SMS text content itself (as Plivo handles encoding), sanitize any user input that might be stored in a database or displayed elsewhere to prevent XSS if data is ever rendered in HTML. Libraries like
dompurify
(if rendering) or simple replacements can help.Authentication/Authorization: Our current API is open. In production, you'd need to protect it:
Rate Limiting: Prevent abuse and protect your Plivo account balance/API limits.
Implementation: Use middleware like
express-rate-limit
.Secure Credential Storage: We are using
.env
, which is good. Ensure the.env
file has strict file permissions on the server and is never checked into version control. Use environment variables provided by your hosting platform for production.Helmet: Use the
helmet
middleware for setting various security-related HTTP headers (likeContent-Security-Policy
,Strict-Transport-Security
).8. Handling Special Cases
Real-world SMS involves nuances:
+14155551234
). Your validation should enforce this (seeexpress-validator
example above).Frequently Asked Questions (FAQ)
How do I send bulk SMS marketing campaigns with Plivo and Express.js?
Create an Express.js application with a
/api/campaigns
POST endpoint that accepts a recipients array and message string. Use Plivo's Node.js SDK withPromise.allSettled()
to send SMS messages concurrently to multiple recipients. Install dependencies withnpm install express plivo dotenv
, configure your Plivo Auth ID and Auth Token in environment variables, and implement error handling to track successful and failed deliveries for each recipient in your campaign.What is 10DLC registration and why is it required for SMS marketing?
A2P 10DLC (Application-to-Person 10-Digit Long Code) registration is mandatory for all businesses sending SMS at scale to US recipients. Register your brand and campaigns through The Campaign Registry (TCR) via your Plivo account. Without 10DLC registration, you'll face carrier surcharges of $0.0080 – $0.0100 per message, reduced throughput limits (3 messages/second vs. 60+ when registered), and potential message blocking by AT&T, T-Mobile, and Verizon. Allow 1 – 2 weeks for approval and budget ~$4 for brand registration plus ~$10/month per campaign.
What are the TCPA compliance requirements for SMS marketing in 2025?
New TCPA rules effective April 11, 2025 require: (1) Prior express written consent before sending marketing messages, (2) Expanded opt-out recognition beyond "STOP" including "UNSUBSCRIBE", "CANCEL", "END", "QUIT", and informal messages like "Leave me alone", (3) Processing text-based opt-outs immediately with max one confirmation within 5 minutes, (4) Honoring other opt-out methods within 10 business days, (5) Sending messages only between 8:00 AM – 9:00 PM recipient local time, and (6) Maintaining SMS Terms & Conditions and Privacy Policy pages. Non-compliance can result in fines of $500 – $1,500 per violation plus class-action lawsuits.
Which Node.js version should I use for a Plivo SMS application in 2025?
Use Node.js v20 LTS "Iron" (Maintenance LTS through April 2026) or v22 LTS "Jod" (Active LTS through October 2025, Maintenance LTS through April 2027). Node.js v18 reached End of Life on April 30, 2025 and no longer receives security updates. Node.js v22 is recommended for new projects as it provides Active LTS support throughout 2025 with the latest features and performance improvements.
How do I implement error handling for bulk SMS campaigns with Plivo?
Use
Promise.allSettled()
instead ofPromise.all()
to ensure all SMS send attempts complete even if some fail. Wrap each Plivomessages.create()
call in a try-catch block, log recipient-specific errors withconsole.error()
, and return a detailed report object containingtotalAttempted
,successCount
,failedCount
, and adetails
array with status for each recipient. For production applications, implement exponential backoff retry logic for transient errors like rate limits (HTTP 429), use Winston or Pino for structured logging, and avoid retrying non-recoverable errors like invalid numbers (HTTP 400) or insufficient funds (HTTP 402).What is E.164 phone number format and why does Plivo require it?
E.164 is the international standard for phone number formatting: a plus sign (+) followed by country code and subscriber number with no spaces, hyphens, or parentheses (e.g.,
+14155551234
for US,+442071234567
for UK). Plivo requires E.164 format to correctly route SMS messages internationally and identify the destination carrier. Implement validation usingexpress-validator
withisMobilePhone('any', { strictMode: true })
and a custom validator to ensure numbers start with "+". Sending non-E.164 formatted numbers will result in API errors or message delivery failures.How much does it cost to send SMS with Plivo?
Plivo offers pay-as-you-go pricing starting at $0.005 per message for receive SMS (free) and send SMS varies by destination country. US SMS typically costs $0.0075 – $0.0110 per message for registered 10DLC traffic. Unregistered traffic incurs additional carrier surcharges: $0.0080 (T-Mobile), $0.0100 (AT&T and Verizon). Volume discounts are available with committed spend agreements starting at $750/month with annual contracts. Check Plivo's SMS Pricing page for specific rates by country and 10DLC documentation for registration fees.
How do I set up Express.js middleware for a Plivo SMS API?
Configure Express.js middleware in this order: (1) Call
dotenv.config()
first to load environment variables, (2) Useexpress.json()
andexpress.urlencoded({ extended: true })
for parsing request bodies, (3) Add logging middleware to track incoming requests, (4) Implementexpress-rate-limit
to prevent API abuse (e.g., 100 requests per 15 minutes per IP), (5) Addhelmet()
for security headers, (6) Mount your campaign routes withapp.use('/api/campaigns', campaignRoutes)
, and (7) Add error handling middleware last to catch unhandled errors. Test the/health
endpoint to verify middleware configuration before sending SMS.What SMS opt-out keywords must I support for TCPA compliance?
Support these opt-out keywords (case-insensitive): STOP, STOPALL, UNSUBSCRIBE, CANCEL, END, and QUIT. The 2025 TCPA rules also require honoring informal opt-out messages like "Leave me alone", "No more", "Remove me", plus opt-outs via email, voicemail, and other channels. Process text-based opt-outs immediately – you may send one confirmation message within 5 minutes stating the opt-out was successful, then never send marketing messages to that number again. Maintain an opt-out database table and check it before sending any campaign. Honor non-text opt-outs within 10 business days maximum.
How do I store Plivo credentials securely in Express.js?
Store Plivo Auth ID, Auth Token, and Sender ID in a
.env
file at your project root. Add.env
to.gitignore
to prevent committing credentials to version control. Load variables withdotenv.config()
called once at your application entry point (src/app.js
). Access credentials viaprocess.env.PLIVO_AUTH_ID
andprocess.env.PLIVO_AUTH_TOKEN
. For production deployments, use your hosting platform's environment variable system (Heroku Config Vars, AWS Systems Manager Parameter Store, Docker secrets). Never hardcode credentials in source code. Set strict file permissions on.env
(chmod 600) and implement credential rotation policies for production systems.What database schema should I use for SMS marketing campaigns?
Implement three core tables: (1)
contacts
table withcontact_id
,phone_number
(E.164 format, unique),first_name
,last_name
,subscribed_at
,is_active
, and optional tags/groups, (2)campaigns
table withcampaign_id
,name
,message_body
,created_at
,scheduled_at
,status
(draft/sending/completed/failed), and (3)campaign_sends
table withsend_id
,campaign_id
(foreign key),contact_id
(foreign key),plivo_message_uuid
,status
(queued/sent/delivered/failed/undelivered),status_updated_at
,error_message
,sent_at
. Add indexes oncampaign_sends.status
andcampaign_sends.plivo_message_uuid
for faster lookups. Use an ORM like Prisma, Sequelize, or TypeORM to manage relationships and implement webhook handlers to receive Plivo delivery reports and update campaign_sends status.How long does 10DLC registration take with Plivo?
10DLC registration typically takes 1 – 2 weeks for approval after submitting complete documentation. The process involves: (1) Brand registration with The Campaign Registry (TCR) requiring your legal business name, EIN, business website with compliant SMS terms/privacy policy, and industry classification – usually approved within 1 – 3 business days, (2) Campaign registration describing your messaging use case (Marketing Promotions, Account Notifications, etc.) – typically approved within 1 – 7 business days, and (3) Carrier vetting which varies by carrier tier and trust score. Start the registration process before implementing your SMS system to avoid delays. High-volume businesses may qualify for Standard or Premium tiers with faster approval and higher throughput limits.