code examples
code examples
How to Send SMS with Plivo in Node.js: Step-by-Step Tutorial (2025)
Learn how to integrate Plivo SMS API with Node.js Express. Step-by-step tutorial covering authentication, phone number validation, error handling, and deployment. Includes Express 4.x and Plivo SDK 4.x code examples.
Send SMS with Plivo and Node.js Express: Complete Tutorial
This guide provides a step-by-step walkthrough for building a simple yet robust Node.js application using the Express framework to send SMS messages via the Plivo API. We'll cover everything from project setup and configuration to implementing the core sending logic, handling errors, and testing the endpoint.
Learn how to send SMS programmatically using Plivo's messaging API with Node.js and Express. This tutorial demonstrates SMS integration for authentication codes, notifications, alerts, and marketing campaigns.
Estimated Time: 20-30 minutes for complete setup and testing. Add 10-15 minutes if this is your first time working with Plivo or configuring environment variables.
Common Use Cases:
- OTP (One-Time Password) delivery for user authentication
- Appointment reminders and notifications
- Order confirmations and shipping updates
- Alert systems and emergency notifications
- Marketing campaigns and promotional messages
By the end of this tutorial, you will have a functional Express API endpoint capable of accepting requests to send SMS messages. This forms a foundational building block for integrating SMS notifications, alerts, or communication features into larger applications.
Technologies Used:
- Node.js: A JavaScript runtime environment for building server-side applications.
- Express.js: A minimal and flexible Node.js web application framework.
- Plivo: A cloud communications platform providing APIs for SMS, voice, and more.
- dotenv: A module to load environment variables from a
.envfile intoprocess.env.
Version Compatibility Matrix:
| Component | Tested Version | Min Version | Notes |
|---|---|---|---|
| Node.js | v20.x, v22.x | v18.x | v18.x minimum for async/await and ES6+ features |
| Express | 4.18.x | 4.17.0 | Express 5.x in beta; use 4.x for production |
| Plivo SDK | 4.14.x | 4.0.0 | Major API changes in v4.x vs v3.x |
| dotenv | 16.3.x | 16.0.0 | Stable across 16.x versions |
Prerequisites:
Before you start integrating Plivo SMS API with Node.js, ensure you have:
- Node.js and npm (or yarn): Installed on your development machine. You can download them from nodejs.org.
- Recommended: Node.js v20.x (Maintenance LTS - Iron) or v22.x (Active LTS - Jod) as of January 2025
- Minimum: Node.js v18.x or higher for ES6+ support and modern async/await features
- Verify your installation:
bash
node --version # Should output v18.x or higher npm --version # Should output 8.x or higher - Package Manager Choice: This tutorial uses npm (bundled with Node.js). Yarn is an alternative with faster installs and better dependency resolution. Use npm for simplicity; switch to Yarn if you need workspaces or prefer its lockfile format.
- Plivo Account: Sign up for a free Plivo account at plivo.com. For pricing details, see our Plivo SMS pricing guide.
- Plivo Auth ID and Auth Token: Found on your Plivo console dashboard upon logging in at console.plivo.com/dashboard.
- Navigate to: Dashboard → Account section → Copy Auth ID and Auth Token
- A Plivo Phone Number: You need an SMS-enabled Plivo phone number to act as the sender (
src). You can purchase one from the Phone Numbers → Buy Numbers section of the Plivo console.- Important: Sending SMS to the US and Canada requires using a Plivo phone number as the sender ID. Other countries may support alphanumeric sender IDs (check Plivo documentation and local regulations).
- Trial Account Limitation: If using a Plivo trial account, you can only send SMS messages to phone numbers verified in your Plivo console under Phone Numbers → Sandbox Numbers.
- Pricing (as of January 2025, source: Plivo Pricing):
- Phone Number Rental: US local/mobile numbers: $0.50/month; US toll-free: $1.00/month
- SMS Rates (US): Outbound long code: starts at $0.0070/SMS; Toll-free: $0.0072/SMS
- Global rates vary by country: Check Plivo SMS Pricing for specific regions
- Note: Trial accounts receive initial credits; paid accounts use pay-as-you-go billing
Setting Up Your Node.js Project for SMS Integration
Estimated Time: 5-7 minutes
Let's start by creating our project directory and initializing it with npm.
-
Create Project Directory: Open your terminal or command prompt and run:
bashmkdir node-plivo-sms cd node-plivo-sms -
Initialize Node.js Project: This creates a
package.jsonfile to manage dependencies and project metadata.bashnpm init -y- The
-yflag accepts all default prompts automatically. Omit-yfor interactive mode where you can customize project name, version, description, entry point, etc.
- The
-
Install Dependencies: We need Express for the web server, the Plivo Node.js SDK to interact with the API, and
dotenvto manage environment variables securely.bashnpm install express@4.18.2 plivo@4.14.0 dotenv@16.3.1- Pinned vs Latest Versions: This tutorial pins specific versions for reproducibility. For new projects, consider using latest versions:
npm install express plivo dotenv. However, pinned versions ensure compatibility with this guide's code examples and prevent breaking changes from automatic updates. - Why these versions? Express 4.18.2 and Plivo 4.14.0 are stable production releases with extensive documentation. Plivo SDK 4.x introduced async/await support (v3.x used callbacks).
- Pinned vs Latest Versions: This tutorial pins specific versions for reproducibility. For new projects, consider using latest versions:
-
Project Structure: Create the basic files and directories. Your structure should look like this:
node-plivo-sms/ ├── node_modules/ ├── .env ├── .gitignore ├── package.json ├── package-lock.json └── server.jsQuick setup commands:
bashtouch .env .gitignore server.js -
Configure
.gitignore: Create a file named.gitignorein the project root and add the following lines to prevent committing sensitive information and unnecessary files:plaintext# .gitignore # Node dependencies node_modules/ # Environment variables .env # Logs (Optional but good practice) logs/ *.log npm-debug.log* yarn-debug.log* yarn-error.log* # Optional editor directories .idea/ .vscode/ *.swp- Why? The
.envfile will contain your secret API credentials, which should never be committed to version control.node_modulescontains installed dependencies, which can be reinstalled usingnpm install.
- Why? The
Configure Plivo API Credentials and Environment Variables
Securely storing your Plivo credentials is crucial. We'll use environment variables managed by the dotenv package.
-
Create
.envfile: In the root of your project, create a file named.env. -
Add Plivo Credentials: Open the
.envfile and add your Plivo Auth ID, Auth Token, and your Plivo phone number. Obtain these from your Plivo Console:dotenv# Plivo Credentials - Get from https://console.plivo.com/dashboard/ PLIVO_AUTH_ID=YOUR_PLIVO_AUTH_ID PLIVO_AUTH_TOKEN=YOUR_PLIVO_AUTH_TOKEN # Your Plivo phone number (must be SMS enabled) # Use E.164 format (e.g., +14155551234) PLIVO_SENDER_NUMBER=YOUR_PLIVO_PHONE_NUMBER- Replace
YOUR_PLIVO_AUTH_ID,YOUR_PLIVO_AUTH_TOKEN, andYOUR_PLIVO_PHONE_NUMBERwith your actual credentials and number. - Important: Ensure the phone number is in E.164 format (includes the
+and country code). - E.164 Format Specification: The E.164 format is the international telephone numbering standard (ITU-T Recommendation E.164). Learn more about E.164 phone number formatting. It consists of:
- A
+prefix - Country code (1-3 digits)
- Subscriber number (up to 12 digits)
- Maximum total length: 15 digits (excluding the
+symbol) - Examples:
+14155551234(US),+442071234567(UK),+919876543210(India)
- A
- Replace
Production Security Best Practices:
- Never commit
.envfiles: Always add.envto.gitignore - Use platform-specific secret management:
- AWS: AWS Secrets Manager or Systems Manager Parameter Store
- Heroku:
heroku config:set PLIVO_AUTH_ID=xxx - Google Cloud: Secret Manager
- Azure: Key Vault
- Docker: Use
--env-fileflag or Docker secrets for swarm mode
- Rotate credentials regularly: Change Auth Token every 90 days minimum
- Principle of least privilege: Create separate Plivo sub-accounts for different environments (dev, staging, prod)
- Audit access: Monitor API usage in Plivo console for suspicious activity
Implement SMS Sending with Plivo API in Express
What this code accomplishes:
- Loads environment variables and validates Plivo credentials
- Initializes an Express web server with JSON parsing middleware
- Creates a
/send-smsPOST endpoint that acceptstoandtextparameters - Validates phone number format (E.164) and required fields
- Sends SMS via Plivo API with comprehensive error handling
- Returns success/failure responses with detailed error information
Now, let's write the code in server.js to set up the Express server and integrate the Plivo client.
// server.js
'use strict'; // Enforce stricter parsing and error handling
// 1. Load Environment Variables
require('dotenv').config(); // Load variables from .env file into process.env
// 2. Import Dependencies
const express = require('express');
const plivo = require('plivo');
// 3. Initialize Express App
const app = express();
app.use(express.json()); // Middleware to parse JSON request bodies
// 4. Validate Essential Environment Variables
const { PLIVO_AUTH_ID, PLIVO_AUTH_TOKEN, PLIVO_SENDER_NUMBER } = process.env;
if (!PLIVO_AUTH_ID || !PLIVO_AUTH_TOKEN || !PLIVO_SENDER_NUMBER) {
console.error(
'Error: Plivo environment variables (PLIVO_AUTH_ID, PLIVO_AUTH_TOKEN, PLIVO_SENDER_NUMBER) are missing or empty in .env file.'
);
process.exit(1); // Exit if essential config is missing
}
// 5. Initialize Plivo Client
// Ensure you handle potential errors during client initialization if necessary,
// though the SDK typically doesn't throw errors here unless inputs are malformed.
const plivoClient = new plivo.Client(PLIVO_AUTH_ID, PLIVO_AUTH_TOKEN);
// 6. Define the SMS Sending Route
app.post('/send-sms', async (req, res) => {
// --- Basic Input Validation ---
const { to, text } = req.body; // Get destination number and message text from request body
if (!to || !text) {
// Use 400 Bad Request for missing client input
return res.status(400).json({
success: false,
error: 'Missing required fields: `to` and `text` in request body.',
});
}
// Basic validation for 'to' number format (E.164)
// Note: This regex is a basic check. Full E.164 validation is more complex
// and might involve library lookups or more sophisticated patterns.
if (!/^\+[1-9]\d{1,14}$/.test(to)) {
return res.status(400).json({
success: false,
error: 'Invalid `to` phone number format. Use E.164 format (e.g., +14155551234).',
});
}
// --- Send SMS using Plivo ---
console.log(`Attempting to send SMS to: ${to}, Text: ""${text}""`);
try {
const response = await plivoClient.messages.create({
src: PLIVO_SENDER_NUMBER, // Sender ID (Your Plivo Number)
dst: to, // Destination Number (From request)
text: text, // Message Text (From request)
});
console.log('Plivo API Response:', response);
// Check if message was successfully queued (basic check based on presence of message_uuid)
// The exact structure might vary slightly based on SDK version or specific scenarios.
// Refer to Plivo Node SDK documentation for definitive response structure.
if (response && response.message_uuid) {
res.status(200).json({
success: true,
message: 'SMS sent successfully queued.',
message_uuid: response.message_uuid, // Return the message UUID (string expected)
api_id: response.api_id, // Return the API ID
});
} else {
// This case might indicate an issue not caught by an exception (unlikely but possible)
console.error('Plivo response indicates message queuing failed or missing expected fields:', response);
res.status(500).json({
success: false,
error: 'Failed to queue SMS via Plivo (unexpected response structure).',
details: response, // Include Plivo response for debugging
});
}
} catch (error) {
console.error('Error sending SMS via Plivo:', error);
// Provide more specific feedback based on Plivo error if possible
// Plivo errors often have status codes and detailed messages
const statusCode = error.statusCode || 500; // Default to 500 Internal Server Error
const errorMessage = error.message || 'An unexpected error occurred.';
// Plivo error details might be in error.error or nested differently.
// Check Plivo Node SDK documentation for the specific error object structure.
const errorDetails = error.error || {};
res.status(statusCode).json({
success: false,
error: `Plivo API Error: ${errorMessage}`,
details: errorDetails,
});
}
});
// 7. Start the Server
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
console.log(`Plivo Sender Number: ${PLIVO_SENDER_NUMBER}`);
console.log('API Endpoint: POST /send-sms');
console.log('Required Body: { ""to"": ""+1XXXXXXXXXX"", ""text"": ""Your message"" }');
});Code Explanation:
- Load Environment Variables:
require('dotenv').config()loads the variables defined in your.envfile intoprocess.env. This must happen before you access these variables. - Import Dependencies: Imports the
expressframework and theplivoSDK. - Initialize Express App: Creates an instance of the Express application and uses
express.json()middleware to automatically parse incoming requests with JSON payloads (like the one we'll send).- Request Size Limit: By default,
express.json()has a limit of 100kb for request bodies (Express documentation). For larger payloads, configure explicitly:app.use(express.json({ limit: '10mb' })). SMS messages are typically under 5kb, so the default is sufficient.
- Request Size Limit: By default,
- Validate Environment Variables: Checks if the essential Plivo credentials are loaded. If not, it logs an error and exits, preventing the server from starting without proper configuration.
- Initialize Plivo Client: Creates an instance of the Plivo client using your Auth ID and Auth Token from the environment variables.
- Define
/send-smsRoute:- Sets up a
POSTendpoint at/send-sms. - Uses
async/awaitfor handling the asynchronous Plivo API call cleanly. - Input Validation: Extracts
to(destination number) andtext(message content) from the request body (req.body). It performs basic checks to ensure both fields are present and thetonumber roughly matches the E.164 format. - Phone Number Validation: The regex
/^\+[1-9]\d{1,14}$/is a basic structural check. For production applications, use libphonenumber-js for comprehensive validation:javascriptconst { parsePhoneNumber } = require('libphonenumber-js'); try { const phoneNumber = parsePhoneNumber(to); if (!phoneNumber.isValid()) { return res.status(400).json({ error: 'Invalid phone number' }); } } catch (error) { return res.status(400).json({ error: 'Cannot parse phone number' }); } - Plivo API Call: Uses
plivoClient.messages.create()to send the SMS.src: The sender number (your Plivo number from.env).dst: The destination number (from the request).text: The message content (from the request).- Optional Parameters:
url: Webhook URL for delivery status callbacksmethod: HTTP method for webhook (GET or POST)log: Set totrueto log message on Plivo consolepowerpack_uuid: Use Powerpack for number pools- Example:
url: 'https://example.com/sms-status', method: 'POST', log: true
- Success Response: If the API call is successful (doesn't throw an error and returns expected fields like
message_uuid), it logs the Plivo response and sends a 200 OK response back to the client with themessage_uuidandapi_id. - Error Handling: If the Plivo API call fails (e.g., invalid credentials, insufficient funds, invalid number), the
catchblock executes. It logs the detailed error and sends an appropriate HTTP status code (usingerror.statusCodeif available, otherwise 500) and an error message back to the client, potentially including details fromerror.error.
- Sets up a
- Start Server: Starts the Express server, listening for incoming requests on the port specified by the
PORTenvironment variable, or defaulting to 3000.
Common Plivo Error Codes
Source: Plivo Error Codes Documentation
| Error Code | Error Name | Description | Resolution |
|---|---|---|---|
| 10 | Invalid Message | Message rejected by downstream carrier | Contact Plivo support if frequent |
| 20 | Network Error | Carrier network issues | Temporary; retry later |
| 30 | Spam Detected | Carrier spam filter blocked message | Use short codes for bulk; review content |
| 40 | Invalid Source Number | Source number incorrectly formatted or not SMS-enabled | Verify src in E.164 format and SMS capability |
| 50 | Invalid Destination Number | Destination not SMS-enabled or incorrect format | Verify dst in E.164 format |
| 70 | Destination Permanently Unavailable | Phone number inactive | Verify number with user |
| 80 | Destination Temporarily Unavailable | Handset off or out of coverage | Retry later |
| 110 | Message Too Long | Exceeds 1,600 chars (GSM) or 737 (UCS-2) | Split message or reduce length |
| 200 | STOP Opt-out | User opted out via STOP keyword | Remove from campaign; honor opt-out |
| 300 | Failed to Dispatch | Internal Plivo error | Not charged; retry or contact support |
| 420 | Message Expired | Queued >3 hours | Ensure 10DLC registration for US traffic |
| 450 | Country Disabled | Destination country blocked | Enable in console Geo Permissions |
| 900 | Insufficient Credit | Account balance too low | Add credits to account |
| 950 | 10DLC Daily Limit | T-Mobile daily brand limit reached | Resets midnight PT; increase brand limits |
| 1000 | Unknown Error | Unspecified failure | Contact support with message UUIDs |
Authentication Error (401): Invalid PLIVO_AUTH_ID or PLIVO_AUTH_TOKEN. Verify credentials in console.
Test Your SMS Integration Locally
Before starting the server, verify prerequisites:
# Check Node.js and npm versions
node --version # Should be v18.x or higher
npm --version # Should be 8.x or higher
# Verify dependencies are installed
ls node_modules | grep -E "(express|plivo|dotenv)"
# Verify .env file exists and contains credentials
cat .env | grep -E "(PLIVO_AUTH_ID|PLIVO_AUTH_TOKEN|PLIVO_SENDER_NUMBER)"Now, let's run the server and test the endpoint.
-
Start the Server: Open your terminal in the project directory (
node-plivo-sms) and run:bashnode server.jsYou should see output like:
Server running on port 3000 Plivo Sender Number: +1XXXXXXXXXX API Endpoint: POST /send-sms Required Body: { ""to"": ""+1YYYYYYYYYY"", ""text"": ""Your message"" }If server fails to start:
- "Cannot find module": Run
npm installto reinstall dependencies - "Environment variables missing": Verify
.envfile exists and contains all three required variables - "EADDRINUSE" (port already in use): Another process is using port 3000. Either:
- Kill the process:
lsof -ti:3000 | xargs kill(Mac/Linux) - Use a different port:
PORT=3001 node server.js
- Kill the process:
- "Auth ID/Token invalid": Verify credentials are correct in
.env(no extra spaces or quotes)
- "Cannot find module": Run
-
Test with
curl: Open a new terminal window (leaving the server running) and usecurl(or a tool like Postman) to send a POST request to your endpoint.- Replace
+1YYYYYYYYYYwith a valid destination phone number (remember the trial account restrictions: use a verified sandbox number if applicable). - Replace
""Hello from Node and Plivo!""with your desired message text.
bashcurl -X POST http://localhost:3000/send-sms \ -H ""Content-Type: application/json"" \ -d '{ ""to"": ""+1YYYYYYYYYY"", ""text"": ""Hello from Node and Plivo!"" }' - Replace
-
Check Response:
-
Successful Request: If everything works,
curlshould output something like (UUIDs and IDs will vary):json{ ""success"": true, ""message"": ""SMS sent successfully queued."", ""message_uuid"": ""some-unique-message-uuid-string"", ""api_id"": ""some-unique-api-id-string"" }Typical Delivery Time: SMS messages are typically delivered within 3-10 seconds for domestic routes (e.g., US to US). International messages may take 10-60 seconds depending on carrier routing. Messages queued during carrier maintenance may take longer.
Check the server logs for the
Plivo API Response. You should also receive the SMS on the destination phone shortly after. -
Failed Request (e.g., Validation Error): If you send an invalid request (e.g., missing
tofield):json{ ""success"": false, ""error"": ""Missing required fields: `to` and `text` in request body."" } -
Failed Request (e.g., Plivo API Error): If Plivo rejects the request (e.g., invalid Auth ID):
json{ ""success"": false, ""error"": ""Plivo API Error: Authentication credentials invalid. Check your Auth ID and Auth Token."", ""details"": {} // Plivo might provide more details here depending on the error }Check the server logs for the detailed
Error sending SMS via Plivo.
-
-
Verify SMS Delivery: Check the destination phone for the incoming SMS message. You can also check delivery status in the Plivo console:
- Navigate to Messaging → Logs → SMS Logs
- Filter by time range and view detailed status (queued, sent, delivered, failed)
- Click on a message UUID to see full delivery report including carrier responses
Troubleshooting Common Plivo SMS API Issues
Diagnostic Checklist
Step 1: Verify Environment
- Node.js version ≥ v18.x (
node --version) - All dependencies installed (
npm list --depth=0) -
.envfile exists with all three variables - No syntax errors in
server.js(node --check server.js)
Step 2: Test Connectivity
- Server starts without errors
- Can reach
http://localhost:3000(or configured port) - Network allows outbound HTTPS to
api.plivo.com
Step 3: Verify Credentials
- Auth ID and Auth Token match Plivo console exactly
- Sender number is SMS-enabled and owned by your account
- Sender number is in E.164 format with
+prefix
Step 4: Check Plivo Account
- Account has sufficient credits (check console dashboard)
- Destination country is enabled in Geo Permissions
- For trial accounts: destination number is added to Sandbox Numbers
- No rate limit warnings in console
Common Issues and Solutions
-
Authentication Errors (401 Unauthorized): Double-check your
PLIVO_AUTH_IDandPLIVO_AUTH_TOKENin the.envfile. Ensure they are copied correctly from the Plivo console and that the.envfile is being loaded (no typos inrequire('dotenv').config()). -
Invalid Sender ID: Ensure
PLIVO_SENDER_NUMBERis a valid, SMS-enabled Plivo number you own, formatted in E.164. If sending outside the US/Canada, you might need to register an Alphanumeric Sender ID with Plivo support depending on the destination country's regulations. Check Plivo's SMS API coverage page for country-specific rules. -
Invalid Destination Number (
to): Ensure thetonumber in your request body is in E.164 format (+followed by country code and number). -
Trial Account Restrictions: Remember you can only send to verified sandbox numbers on a trial account. Add numbers under Phone Numbers → Sandbox Numbers in the Plivo console.
-
Insufficient Funds: If you're using a paid account, ensure you have enough credits.
- Check balance via console: Navigate to Account → Overview → Account Balance
- Check balance programmatically:
javascript
const balance = await plivoClient.account.getBalance(); console.log(`Current balance: ${balance.cashCredits} credits`); - Low balance alerts: Configure in Account → Alerts to receive notifications at custom thresholds
-
Rate Limiting: Plivo enforces rate limits on API requests. For high-volume sending, implement proper queuing and potentially exponential backoff in your application logic (beyond the scope of this basic guide).
- API Rate Limits (source: Plivo Account Limits):
- Non-call APIs (including SMS): 300 requests per 5 seconds (default)
- MMS APIs: 100 simultaneous requests
- Exceeded limit response: HTTP 429 "Too Many Requests"
- Request limit increase: Contact Plivo sales; requires minimum commitment
- Best practice: Implement exponential backoff when receiving 429 errors
- API Rate Limits (source: Plivo Account Limits):
-
Encoding: Plivo handles GSM and Unicode characters (including emojis). Be aware that messages with Unicode characters have a lower character limit per SMS segment (70 vs. 160 for GSM). Long messages are automatically concatenated. See Plivo's Encoding and Concatenation guide.
- GSM-7 Encoding: Single segment = 160 characters, concatenated segments = 153 characters each
- Unicode (UCS-2/UTF-16): Single segment = 70 characters, concatenated segments = 67 characters each
- Character Types: GSM-7 supports basic Latin characters; Unicode required for emojis, non-Latin scripts, and special symbols
- Message limits: Maximum 1,600 characters (GSM) or 737 characters (Unicode) total length
-
Network Issues: Ensure your server can reach Plivo's API endpoints (
api.plivo.com). Firewalls or network configurations could block outgoing connections.- Test API connectivity without sending SMS:
Then test with:javascript
// Add this test endpoint to server.js app.get('/test-plivo', async (req, res) => { try { const balance = await plivoClient.account.getBalance(); res.json({ success: true, connection: 'OK', balance: balance.cashCredits }); } catch (error) { res.status(500).json({ success: false, error: error.message }); } });curl http://localhost:3000/test-plivo
- Test API connectivity without sending SMS:
-
SDK Response/Error Structure: The exact fields returned by the Plivo SDK upon success (
response.message_uuid,response.api_id) or the structure of theerrorobject in thecatchblock might change between SDK versions. Always refer to the official Plivo Node SDK documentation for the version you are using.
Deploy Your Node.js SMS Application to Production
While this guide focuses on local development, here are key points for deploying this application:
-
Environment Variables: Never commit your
.envfile. Production environments provide mechanisms to securely set environment variables directly on the platform. ConfigurePLIVO_AUTH_ID,PLIVO_AUTH_TOKEN, andPLIVO_SENDER_NUMBERin your hosting provider's settings.Platform-specific examples:
bash# Heroku heroku config:set PLIVO_AUTH_ID=MA... PLIVO_AUTH_TOKEN=xxx... PLIVO_SENDER_NUMBER=+1... # AWS Elastic Beanstalk eb setenv PLIVO_AUTH_ID=MA... PLIVO_AUTH_TOKEN=xxx... PLIVO_SENDER_NUMBER=+1... # Google Cloud Run gcloud run services update SERVICE_NAME \ --set-env-vars PLIVO_AUTH_ID=MA...,PLIVO_AUTH_TOKEN=xxx...,PLIVO_SENDER_NUMBER=+1... # Docker docker run -e PLIVO_AUTH_ID=MA... -e PLIVO_AUTH_TOKEN=xxx... -e PLIVO_SENDER_NUMBER=+1... my-app -
PORTVariable: Most hosting platforms automatically assign aPORTenvironment variable. The codeconst PORT = process.env.PORT || 3000;correctly uses the assigned port or falls back to 3000. -
Process Management: Use a process manager like
pm2or rely on your platform's tools (e.g., Heroku Dynos, Docker containers) to keep your Node.js application running reliably and restart it if it crashes.PM2 Example:
bash# Install PM2 npm install -g pm2 # Start application pm2 start server.js --name plivo-sms # Configure auto-restart on reboot pm2 startup pm2 save # Create ecosystem.config.js for advanced configuration: module.exports = { apps: [{ name: 'plivo-sms', script: 'server.js', instances: 2, // Use 2 CPU cores exec_mode: 'cluster', env: { NODE_ENV: 'production' } }] }; # Start with config pm2 start ecosystem.config.jsSource: PM2 Documentation
-
Logging: Implement more robust logging (e.g., using Winston or Pino) to capture detailed information in production, especially errors, and potentially send logs to a centralized logging service.
-
Security: Add rate limiting (e.g., using
express-rate-limit) to your API endpoint to prevent abuse. Consider adding API key authentication if this endpoint will be exposed publicly or used by multiple clients.CORS Configuration for Frontend Integration:
javascript// Install: npm install cors const cors = require('cors'); // Allow specific origin app.use(cors({ origin: 'https://yourdomain.com', methods: ['POST'], credentials: true })); // Or allow all origins (development only) app.use(cors());HTTPS/SSL Requirements:
- Production applications must use HTTPS to encrypt API credentials in transit
- Webhook URLs for delivery callbacks must be HTTPS (HTTP will be rejected)
- Certificate options:
- Free: Let's Encrypt with automated renewal
- Cloud platforms: AWS ACM, Google-managed certs (included with Cloud Run/App Engine)
- Heroku: Automatic SSL for custom domains on paid dynos
- Local HTTPS testing: Use
mkcertor self-signed certificates for development
Conclusion and Next Steps
You have successfully built a basic Node.js Express application capable of sending SMS messages using the Plivo API. You learned how to set up the project, manage credentials securely, implement the sending logic with error handling, and test the API endpoint.
Further Enhancements:
- Receiving SMS: Implement a webhook endpoint using Express to receive incoming SMS messages sent to your Plivo number. For two-way messaging, see our Plivo inbound messaging tutorial.
- Status Callbacks: Configure a
urlorlogparameter in themessages.createcall or Plivo Application settings to receive status updates (e.g., delivered, failed) for sent messages. - More Robust Validation: Implement more comprehensive validation for phone numbers (potentially using a dedicated library like
libphonenumber-js) and message content. - Web Interface: Build a simple frontend (using HTML, CSS, and JavaScript or a framework like React/Vue/Angular) to interact with your API.
- Database Integration: Store message logs, user data, or application state in a database.
- Bulk Sending: Adapt the logic to handle sending messages to multiple recipients efficiently, potentially using
Promise.allfor better concurrency while respecting Plivo rate limits.
Monitoring and Analytics:
- Plivo Console Analytics: View message volume, delivery rates, and error trends at Messaging → Analytics
- Custom Monitoring: Implement application-level tracking with tools like:
- DataDog, New Relic, or Application Insights for APM
- Prometheus + Grafana for self-hosted metrics
- CloudWatch (AWS), Stackdriver (GCP), or Azure Monitor for cloud-native monitoring
- Key Metrics to Track:
- Message success rate (delivered / total sent)
- Average delivery time
- Error code distribution
- API response times
- Account balance trends
This foundation enables you to integrate powerful SMS communication features into your Node.js applications effectively and securely.
Frequently Asked Questions
How to send SMS with Node.js and Express?
This guide provides a step-by-step process for sending SMS messages from a Node.js application using the Express framework and Plivo API. It involves setting up a project, installing dependencies like Express and Plivo, configuring environment variables, and implementing the send SMS logic within an Express route. You'll create an endpoint that accepts the destination number and message text to trigger SMS sending via Plivo.
What is Plivo used for in this tutorial?
Plivo is a cloud communications platform that provides APIs for various communication services including sending and receiving SMS messages. In this tutorial, Plivo's SMS API is utilized to send text messages from your Node.js application. You'll need a Plivo account, Auth ID, Auth Token, and a Plivo phone number to use the API.
Why use dotenv for Plivo credentials?
Dotenv helps manage environment variables securely, loading credentials from a .env file into process.env. This prevents your sensitive API keys from being exposed in your codebase or committed to version control. It is crucial for keeping your Plivo Auth ID and Auth Token secret.
When should I validate Plivo environment variables?
Environment variables should be validated at the start of your application, before using them. In the server.js file, the code checks for PLIVO_AUTH_ID, PLIVO_AUTH_TOKEN, and PLIVO_SENDER_NUMBER right after loading the .env file. If these are not present, the server exits with an error.
How to set up Plivo sender number in Node.js?
Your Plivo sender number is configured using an environment variable. Set a PLIVO_SENDER_NUMBER variable in your .env file with your Plivo phone number (in E.164 format). This number must be an SMS-enabled number purchased through your Plivo account.
What is the format for the /send-sms endpoint request?
The /send-sms endpoint expects a POST request with a JSON body containing two fields: 'to' and 'text'. The 'to' field should contain the recipient's phone number in E.164 format (e.g., +14155551234). The 'text' field should contain the SMS message content as a string.
How to handle errors when sending SMS with Plivo?
The example code includes comprehensive error handling. It validates input parameters and catches errors during the Plivo API call. If an error occurs, it logs the error details and returns an appropriate error response to the client, including the HTTP status code and error message from Plivo.
Can I use an alphanumeric sender ID with Plivo?
Alphanumeric sender IDs are supported by Plivo but primarily for sending outside the US and Canada. Using one depends on local regulations for the recipient's country, and might involve registration with Plivo. For US/Canada SMS, you need a Plivo phone number as the sender ID.
How to test Plivo SMS integration locally?
After starting your Node server, use a tool like curl or Postman to send POST requests to http://localhost:3000/send-sms. Replace placeholders in the example request with the recipient's phone number and your desired message. Check your server logs and the recipient's phone to confirm message delivery.
What are Plivo trial account limitations?
With a Plivo trial account, you can only send messages to phone numbers verified as sandbox numbers in your Plivo console under Phone Numbers -> Sandbox Numbers. This is important for testing and verifying your integration.
How to handle SMS character limits with Plivo?
Plivo supports GSM and Unicode. GSM allows 160 characters, but Unicode messages (including emojis) have a lower limit of 70 characters per segment. Plivo automatically concatenates longer messages into multiple segments.
How to set up environment variables in production?
When deploying to production environments like Heroku or AWS, do not commit your .env file. Instead, utilize the platform's specific mechanisms to set your PLIVO_AUTH_ID, PLIVO_AUTH_TOKEN, and PLIVO_SENDER_NUMBER directly within the environment.
Why use a process manager with Node.js and Plivo?
A process manager like PM2 helps ensure your Node.js application runs continuously and restarts automatically in case of failures. This is essential for the reliability of your SMS sending service in production.