Frequently Asked Questions
Use the Vonage Messages API with the @vonage/server-sdk in your Node.js application. The send-sms.js example demonstrates how to initialize the Vonage client and use the vonage.messages.send() method to send text messages. Ensure your Vonage application is set up correctly with the necessary API credentials.
A Vonage Application acts as a container that connects your Vonage API keys, private key, virtual numbers, and webhook URLs. It's essential for sending SMS messages and receiving inbound messages and delivery receipts. Create one through the Vonage API Dashboard.
First, run ngrok to create a public URL for your local server. Then, in your Vonage Application settings, set the Inbound URL to your ngrok URL + /webhooks/inbound and the Status URL to your ngrok URL + /webhooks/status. This tells Vonage where to send incoming messages and delivery updates.
A 200 OK response from your webhook endpoint acknowledges to Vonage that you've successfully received the webhook. If Vonage doesn't receive this acknowledgment, it will retry sending the webhook multiple times to avoid data loss.
The private.key file is crucial for authenticating your application with Vonage. It is generated when you create a Vonage Application and should be kept secure, never committed to version control.
Set up a webhook endpoint (e.g., /webhooks/status) in your Express server. Vonage will send POST requests to this URL with delivery status updates, including 'submitted', 'delivered', 'failed', or 'rejected'. Your endpoint should parse this data and update your application's internal state accordingly.
Configure the /webhooks/inbound endpoint on your server and link it to your Vonage Application and virtual number. When someone sends an SMS to your Vonage number, Vonage will send the message data to your inbound webhook URL.
The Messages API is Vonage's recommended API for sending and receiving SMS messages. It's more versatile than the older SMS API and offers richer features, including unified handling of different message types.
The delivery receipt webhook includes the message_uuid, status (e.g., delivered, failed), timestamp, and any error codes/reasons if the delivery failed. Log this information for debugging and monitoring.
Yes, it is highly recommended to use environment variables (.env file for development, system environment variables for production) to store sensitive credentials like API keys and secrets. This prevents accidental exposure in your codebase.
Implement a try...catch block around the vonage.messages.send() call to handle potential errors during the API request. Log detailed error information, including any Vonage-specific error responses, and implement retry logic if necessary.
ngrok provides a public URL that tunnels to your local development server. This is necessary for Vonage to send webhook requests to your local machine during development and testing.
Use a structured logging library like Winston or Pino for better organization, different log levels (info, error, warning), and easier log management in a production environment.
Start your Express server and ngrok. Run the send-sms.js script to send a test SMS and observe the logs in your server console and the ngrok web interface for delivery status updates and webhook requests. Also, send an SMS to your Vonage number to test the inbound webhook.
.gitignore
Learn how to implement SMS delivery status tracking and webhook callbacks using the Vonage Messages API with Node.js. This comprehensive guide covers sending SMS messages, receiving delivery receipts (DLR), and handling inbound message webhooks for real-time SMS communication tracking.
What You'll Build
By the end of this tutorial, you will have a production-ready Node.js application that:
This implementation is essential for applications requiring SMS delivery confirmation, including:
Understanding Vonage SMS Delivery Status and Webhooks
When you send an SMS message through the Vonage Messages API, you receive an immediate HTTP response confirming the message was submitted to the carrier network. However, this doesn't guarantee the message reached the recipient's device. To track actual delivery, you need to implement delivery receipt (DLR) webhooks that receive real-time status updates as your message progresses through the carrier network.
This tutorial builds a robust Node.js backend that integrates Vonage's webhook system for complete SMS delivery tracking and two-way messaging capabilities.
Technologies Used:
@vonage/server-sdk
: The official Vonage Node.js SDK for interacting with Vonage APIs.dotenv
: A module to load environment variables from a.env
file for secure configuration management.ngrok
: A tool to expose local development servers to the internet, necessary for testing Vonage webhooks.System Architecture:
Prerequisites:
ngrok
installed and authenticated (Download ngrok). A free account is sufficient.Final Outcome:
You will have two main components:
send-sms.js
) to send an SMS message via Vonage and capture the unique message UUID for tracking.server.js
) with webhook endpoints for receiving delivery status updates and inbound messages from Vonage.Setting Up Your Node.js Project for Vonage SMS Webhooks
Let's create the project structure and install the necessary dependencies for handling Vonage SMS delivery status callbacks.
1. Create Project Directory:
Open your terminal and create a new directory for your project_ then navigate into it.
2. Initialize Node.js Project:
Initialize a
package.json
file.(This accepts default settings. Feel free to omit
-y
to customize.)3. Install Dependencies:
We need the Express framework_ the Vonage SDK_ and
dotenv
for managing environment variables.express
: Web framework for handling webhook requests.@vonage/server-sdk
: To interact with the Vonage APIs.dotenv
: To load credentials securely from a.env
file.4. Create Project Files:
Create the main files we'll be working with.
.env
: Stores sensitive credentials (API keys_ application ID_ etc.).server.js
: Runs the Express server to listen for webhooks.send-sms.js
: Contains the logic to send an SMS message..gitignore
: Specifies files/directories that Git should ignore (like.env
andnode_modules
).5. Configure
.gitignore
:Add the following lines to your
.gitignore
file to prevent committing sensitive information and unnecessary files:6. Set Up Environment Variables (
.env
):Open the
.env
file and prepare it for your Vonage credentials. We'll fill these in later..env
? Storing credentials directly in code is insecure. Using environment variables loaded from.env
(which is gitignored) keeps secrets out of your source control.dotenv
makes this easy in development. In production, you'd typically set these variables directly in your hosting environment.Configuring Vonage Webhooks for SMS Delivery Status
To receive delivery status callbacks and inbound messages, you must configure webhook URLs in your Vonage Application. Vonage will send HTTP POST requests to these endpoints whenever message events occur (delivery status changes, incoming messages).
1. Set Default SMS API to Messages API:
2. Run
ngrok
:Before creating the Vonage Application, you need a publicly accessible URL for your local server's webhooks.
ngrok
provides this. Open a new terminal window and run:(Replace
3000
if you chose a different port in.env
)ngrok
will display output similar to this:Copy the
https://<random-string>.ngrok-free.app
URL. This is your public base URL. Keep this terminal window running.3. Create a Vonage Application:
Node SMS Callbacks App
).private.key
. Save this file in your project's root directory (the same place asserver.js
). This key is used by the SDK to authenticate requests for this application.ngrok
Forwarding URL and append/webhooks/inbound
. Example:https://<random-string>.ngrok-free.app/webhooks/inbound
ngrok
Forwarding URL and append/webhooks/status
. Example:https://<random-string>.ngrok-free.app/webhooks/status
4. Link Your Vonage Number:
5. Update
.env
File:Now, open your
.env
file and fill in the values you obtained:Ensure
VONAGE_PRIVATE_KEY_PATH
correctly points to where you saved theprivate.key
file.Sending SMS Messages with Node.js and Tracking Message UUIDs
Every SMS sent through the Vonage Messages API receives a unique
message_uuid
identifier. This UUID is critical for tracking delivery status updates, as Vonage includes it in webhook callbacks to match status updates with the original message.File:
send-sms.js
Explanation:
.env
variables and the Node.jsfs
module.process.env
.fs.readFileSync
. Includes error handling if the file is missing or unreadable.Vonage
instance, passing the API key, secret, application ID, and the content of the private key.sendSms
Function:async
function to handle the asynchronous API call.vonage.messages.send()
which is the correct method for the Messages API.message_type
,text
,to
,from
, andchannel
.try...catch
block for error handling.messageUuid
from the successful response (resp.messageUuid
) - this UUID is essential for correlating delivery status updates.sendSms
function to initiate the process.Building Express Webhook Endpoints for SMS Delivery Status
Create Express.js endpoints to receive Vonage webhook callbacks. You'll need two separate endpoints: one for delivery status updates (
/webhooks/status
) and one for inbound messages (/webhooks/inbound
).File:
server.js
Explanation:
require('dotenv').config();
loads the variables from.env
.const app = express();
creates the Express application.app.use(express.json());
: Parses incoming requests with JSON payloads (which Vonage uses for webhooks).app.use(express.urlencoded({ extended: true }));
: Parses incoming requests with URL-encoded payloads.app.post('/webhooks/inbound', ...)
: Defines a handler for POST requests to the/webhooks/inbound
path. It logs relevant information from the request body (req.body
).app.post('/webhooks/status', ...)
: Defines a handler for POST requests to the/webhooks/status
path. It logs the delivery status information including themessage_uuid
to correlate with sent messages.res.status(200).end();
: This is critical. Vonage expects a200 OK
response quickly to acknowledge receipt. Failure to send this promptly will cause Vonage to retry the webhook.app.listen(PORT, ...)
starts the server on the specified port.Implementing Proper Error Handling and Logging
The current code includes basic
console.log
statements. For production, you'd want more robust logging and error handling.Error Handling (
send-sms.js
):The
try...catch
block in the updatedsend-sms.js
already handles errors during the API call more robustly. You can enhance this further:Logging (
server.js
):Replace
console.log
with a dedicated logging library likewinston
orpino
for structured logging, different log levels (info, warn, error), and log rotation.Retry Mechanisms (Vonage):
200 OK
. Ensure your webhook endpoints respond quickly. Offload time-consuming processing..catch
block insend-sms.js
if necessary (e.g., for transient network errors), potentially using exponential backoff.Database Schema and Data Layer (Conceptual)
This guide focuses on the core integration. In a real application, you would store message details and status updates in a database.
Conceptual Schema (e.g., PostgreSQL):
Data Layer Implementation:
vonage.messages.send()
succeeds, insert a record withdirection='outbound'
,status='submitted'
, and themessage_uuid
.message_uuid
and update itsstatus
,vonage_status_timestamp
, etc.direction='inbound'
,status='delivered'
, and details from the payload.Adding Security Features
.env
and.gitignore
. Use environment variables or secrets management in production. Never commit secrets.X-Vonage-Signature
header in incoming webhook requests.VONAGE_API_SECRET
and compare it to the header value.@vonage/server-sdk
may offer utilities, but manual implementation might be needed. Implementing this is crucial for production security.ngrok
provides HTTPS. Ensure your production deployment uses HTTPS for webhook URLs.Understanding SMS Delivery Status Values
Vonage delivery status webhooks include a
status
field indicating the current message state:submitted
: Message accepted by Vonage and sent to the carrier networkdelivered
: Carrier confirmed the message reached the recipient's devicefailed
: Delivery failed (network issues, invalid number, etc.)rejected
: Message rejected by carrier (often due to content filtering)expired
: Message expired before delivery (recipient phone off for extended period)Important: Not all carriers support delivery receipts. In some countries/networks, you may only receive
submitted
status. Always handle cases wheredelivered
status never arrives.Additional Implementation Considerations
message_type: 'text'
+14155550101
) for international compatibilityImplementing Performance Optimizations
200 OK
immediately. Offload slow processing (DB writes, external calls) to background jobs (e.g.,bullmq
,agenda
, AWS SQS).sms_messages
) on frequently queried columns (message_uuid
,status
, numbers).pm2
for process management and clustering.Adding Monitoring, Observability, and Analytics
/health
endpoint returning200 OK
.Troubleshooting Common Issues
VONAGE_API_KEY
,VONAGE_API_SECRET
,VONAGE_APPLICATION_ID
,VONAGE_PRIVATE_KEY_PATH
in.env
. Ensure the private key file exists and is readable.ngrok
Issues:ngrok
runs and points to the correct local port (3000
).ngrok
Forwarding URL in the Vonage Application webhook settings is current (it changes on restart for free accounts).ngrok
web interface (http://127.0.0.1:4040
) for requests/errors.3000
).200 OK
: Check server logs (server.js
output) for errors if Vonage retries webhooks. Ensure quick responses.submitted
confirms handoff to the carrier.private.key
: Ensure theprivate.key
file matches theVONAGE_APPLICATION_ID
and its content is correct.+1...
) for phone numbers.Deployment and CI/CD
ngrok
: Deployserver.js
to a hosting provider (Heroku, AWS, Google Cloud, etc.)..env
file. Uploadprivate.key
securely or store its content in an environment variable (handle newlines carefully).pm2
to run your Node.js app:Testing SMS Delivery Status Webhooks
1. Start Required Services:
ngrok http 3000
and copy the Forwarding URLngrok
URLnode server.js
2. Test Sending SMS:
node send-sms.js
.SMS Sent Successfully! Message UUID: <uuid>
.TO_NUMBER
receives the SMS.server.js
logs a "Delivery Status Update" (initiallysubmitted
, then potentiallydelivered
).3. Test Receiving Inbound SMS:
VONAGE_NUMBER
.server.js
logs an "Inbound SMS Received" entry.ngrok
web interface (http://127.0.0.1:4040
) for request details.4. Test Error Cases:
TO_NUMBER
to an invalid format insend-sms.js
, run it, and observe script errors and potentialrejected
/failed
status updates.server.js
, send an SMS viasend-sms.js
. Observe webhook failures inngrok
. Restartserver.js
to receive queued webhooks.Verification Checklist:
npm install
)..env
populated correctly.private.key
file present and correct path in.env
.ngrok
/production URL + paths.ngrok
running, forwarding correctly.server.js
running without errors.node send-sms.js
sends SMS successfully.server.js
logs delivery status.VONAGE_NUMBER
logs inbound message inserver.js
.200 OK
.Next Steps and Production Considerations
You now have a working implementation for tracking Vonage SMS delivery status with Node.js webhooks. To prepare for production:
Related Resources