Frequently Asked Questions
Use the Vonage Messages API with Node.js and Express. The provided code example demonstrates setting up a server and sending messages via an API endpoint using the '@vonage/server-sdk' and '@vonage/messages' libraries. You'll need a Vonage API account and application set up to use the API.
The Vonage Messages API is a unified platform that allows sending messages across various channels like SMS, WhatsApp, and more. It is used in this tutorial with the 'vonage/server-sdk' and 'vonage/messages' libraries to send SMS in bulk efficiently.
The tutorial recommends the 'p-queue' library to manage API request concurrency. This helps avoid exceeding Vonage's rate limits and ensures reliable sending. Configure concurrency, interval, and request cap in your environment variables (e.g. VONAGE_CONCURRENCY) and the p-queue configuration accordingly.
JWT (JSON Web Tokens) provide a secure way to authenticate with the Vonage Messages API. The tutorial uses an application ID and private key (stored securely and never committed to version control) for JWT authentication, eliminating the need to expose API secrets directly.
Vonage provides delivery receipts (DLRs) via webhooks. Set up a status URL (e.g., 'YOUR_NGROK_HTTPS_URL/api/sms/status') in your Vonage application settings. The code example provides a 'handleStatusWebhook' function to process these status updates.
A2P 10DLC is a US regulation for Application-to-Person messaging via 10-digit long codes. The tutorial mentions this as a consideration for bulk SMS sending in the US, emphasizing the importance of complying with carrier rules when setting up your sending logic and respecting rate limits.
ngrok creates a public, secure tunnel to your locally running server. This is needed for Vonage webhooks (like delivery receipts) to reach your local development environment during testing as Vonage can't send requests directly to 'localhost'.
Download the 'private.key' file generated when creating a Vonage application. Store this file securely (outside version control, e.g., in the project's root directory) and reference its path in your .env file as VONAGE_PRIVATE_KEY_PATH. The provided example code reads this key to initialize the Vonage client.
When dealing with substantial recipient lists or needing detailed message logging. Prisma simplifies database interaction with PostgreSQL, allowing efficient management and tracking of SMS sending attempts and delivery statuses as shown in the tutorial's optional section.
The tutorial demonstrates (optionally) using PostgreSQL and Prisma. Prisma models are defined for Recipients (including their subscription status and list affiliation) and MessageLogs, offering a clear way to organize and query message sending history related to recipients.
The tutorial recommends a structured approach with controllers (e.g. smsController.js), routes (smsRoutes.js), and services (vonageService.js). This organization promotes maintainability and separates different aspects of the application's logic. Use npm packages like 'dotenv' for managing environment variables and optional packages like 'nodemon' and 'p-queue' for enhanced development and message sending respectively.
p-queue is a promise-based queue library that allows control over concurrent operations. The tutorial highlights its use for respecting Vonage API rate limits, crucial for handling bursts of SMS messages without exceeding limits, using env vars like VONAGE_CONCURRENCY.
Yes, the tutorial demonstrates database integration using PostgreSQL and Prisma (optional). This enables storing recipients, managing lists, logging messages, and tracking delivery status more robustly, simplifying querying and data management in bulk operations.
Use tools like 'curl' or Postman to send POST requests to your API endpoint (e.g., 'http://localhost:3000/api/sms/bulk'). Provide sample JSON data with recipient numbers (E.164 format) and the message text in the request body as shown in the tutorial examples. Monitor your terminal for server logs and use ngrok to expose local endpoints for webhook testing.
Developer Guide: Building a Production-Ready Bulk SMS System with Node.js, Express, and Vonage
Learn how to build a robust system that sends bulk SMS messages using Node.js, Express, and the Vonage Messages API. This comprehensive tutorial covers everything from initial project setup to handling rate limits, implementing JWT authentication, managing webhooks, and integrating with PostgreSQL using Prisma.
Whether you're sending marketing campaigns, appointment reminders, or transactional notifications, this guide will help you reliably send SMS messages to hundreds or thousands of recipients while navigating API rate limits, carrier regulations (like A2P 10DLC in the US), and tracking delivery status.
What You'll Build: A Node.js/Express application with an API endpoint that accepts a list of recipients and a message, then efficiently sends SMS via Vonage while managing concurrency, handling errors, and tracking delivery receipts.
Technologies You'll Use:
@vonage/server-sdkand@vonage/messages..envfile intoprocess.env.System Architecture:
Final Outcome: A functional Node.js application that can:
What You'll Need:
ngrokinstalled (Download here).npm install -g @vonage/cli.1. Setting Up Your Node.js Project for Bulk SMS
Initialize your Node.js project and install the necessary dependencies to send SMS messages with Vonage.
Create Project Directory:
Initialize npm:
This creates a
package.jsonfile.Install Core Dependencies:
express: Web framework.@vonage/server-sdk: Official Vonage SDK for Node.js (core client).@vonage/messages: Part of the SDK for constructing message objects.dotenv: Loads environment variables from.env.Install Development/Optional Dependencies:
Create Project Structure:
vonage-bulk-sms/node_modules/src/controllers/smsController.jsroutes/smsRoutes.jsservices/vonageService.jsutils/logger.jsprismaClient.js(Optional: if using Prisma)server.jsprisma/(Optional: for database schema)schema.prisma.env.env.example.gitignoreprivate.key(Your downloaded Vonage private key)package.jsonCreate these directories and empty files.
Configure
.gitignore: Create a.gitignorefile in the root directory:Setup Environment Variables (
.env.example): Create a.env.examplefile. Never commit the actual.envfile..envand fill in your actual credentials later. Place your downloadedprivate.keyfile in the project root.Setup Basic Express Server (
src/server.js):Setup Basic Logger (
src/utils/logger.js):Add
startanddevscripts topackage.json:2. Configuring Vonage Messages API for SMS Sending
Configure your Vonage account and integrate the Messages API before writing the core SMS sending logic.
Log in to Vonage: Go to your Vonage API Dashboard.
Create a Vonage Application: The Messages API requires a Vonage Application. This application acts as a container for configuration, including webhook URLs and security credentials (public/private key pair for JWT authentication).
private.keyfile will be downloaded. Save this file in your project's root directory. Ensure the path in your.envfile (VONAGE_PRIVATE_KEY_PATH) matches its location (e.g.,./private.key). Also addprivate.keyto your.gitignore.ngrok http YOUR_PORT(e.g.,ngrok http 3000).https://Forwarding URL provided by ngrok.YOUR_NGROK_HTTPS_URL/api/sms/status(you'll create this endpoint later).YOUR_NGROK_HTTPS_URL/api/sms/inbound. For sending only, this can often be left blank or set the same as the status URL, but ideally, handle it even if just with a200 OK..envfile (VONAGE_APPLICATION_ID).Link Your Vonage Number:
14155550100) to your.envfile (VONAGE_NUMBER).Set Default SMS API (Important):
Initialize Vonage Client (
src/services/vonageService.js):.env.sendSingleSmsfor sending one message.sendBulkSmsSequential: Simple loop, inefficient for large volumes.sendBulkSmsConcurrent: Usesp-queuefor rate-limited concurrency - recommended for bulk.delivered,accepted,buffered,expired,failed,rejected, andunknown. Error codes (err-code) range from 0 (success) to 99 (general error), with specific codes indicating temporary issues (retryable) vs permanent failures.13. Building the Express API for Bulk SMS Sending
Now, let's create the Express routes and controller to handle incoming bulk SMS requests and webhook callbacks from Vonage.
Create SMS Controller (
src/controllers/smsController.js):/bulkrequest, validates input, calls the appropriatevonageServicefunction, logs results, and returns a summary.200 OKquickly, otherwise Vonage will retry.Create SMS Routes (
src/routes/smsRoutes.js):POST /api/sms/bulk: Accepts the bulk send request. Includes optionalexpress-rate-limit.POST /api/sms/status: Receives delivery receipts from Vonage.POST /api/sms/inbound: Receives incoming SMS messages from Vonage.Testing the
/bulkendpoint:.envfile is populated with your Vonage Application ID, Private Key Path, and Vonage Number.private.keyfile in the project root.npm run devcurlor Postman:Curl Example:
Expected Response (JSON):
http://localhost:4040) for incoming POST requests to/api/sms/status(these are the delivery reports). Check your server logs to see howhandleStatusWebhookprocessed them.4. (Optional) Integrating PostgreSQL Database with Prisma for SMS Tracking
Managing large recipient lists and tracking message status is easier with a database. Let's integrate PostgreSQL using Prisma ORM.
Install PostgreSQL: Use Docker (recommended) or install natively.
Docker: Create a
docker-compose.yml:docker-compose up -d..envDATABASE_URLaccordingly:DATABASE_URL="postgresql://your_db_user:your_db_password@localhost:5432/vonage_bulk_sms?schema=public"Initialize Prisma:
This creates
prisma/schema.prismaand updates.envwith a placeholderDATABASE_URL. Ensure your actualDATABASE_URLis correct in.env.Define Schema (
prisma/schema.prisma):Apply Schema Migrations:
This creates the tables in your database and generates the Prisma Client library in
node_modules/@prisma/client.Integrate Prisma Client:
Create a Prisma client instance (
src/utils/prismaClient.js):Modify
smsController.jsto use Prisma:References
Footnotes
Vonage Developer Documentation. "SMS Delivery Receipts API Guide." Vonage API Documentation. Accessed October 2025. https://developer.vonage.com/en/messaging/sms/guides/delivery-receipts. Explains delivery receipt status codes (delivered, accepted, buffered, expired, failed, rejected, unknown) and error codes ranging from 0 (success) to 99 (general error), with specific codes indicating temporary vs permanent failures. ↩