Frequently Asked Questions
Vonage automatically segments longer messages exceeding the standard SMS character limit (160 for GSM-7, 70 for UCS-2). Consider message length to manage costs.
Use the Vonage Messages API with the Express.js framework and the @vonage/server-sdk library. This setup allows your Node.js application to send SMS messages by making HTTP requests to the Vonage API. The article provides a step-by-step guide on setting up this project.
The Vonage Messages API is a versatile tool that enables sending messages over various channels, including SMS. It offers a unified interface for different message types. This article focuses on its SMS capabilities using the @vonage/messages package in Node.js.
Dotenv helps manage environment variables by loading them from a .env file into process.env. This enhances security by keeping sensitive credentials like API keys out of your codebase and makes configuration more manageable.
The Vonage Messages API is suitable when your Node.js applications need features like SMS notifications, two-factor authentication, or other communication services. It's a robust solution for sending SMS messages programmatically.
Create an application in your Vonage API Dashboard, generate a private key file, and link your Vonage virtual number to the application. Then, enable the “Messages” capability within the application settings for SMS functionality.
The private key, along with your Application ID, authenticates your Node.js application with the Vonage API. Keep this file secure and never commit it to version control, as it grants access to your Vonage account resources.
Implement a try...catch block around the vonageMessages.send() function. This allows you to capture and handle potential errors during the API call. Detailed error information is available in the error.response.data property of the error object.
Use E.164 formatting (e.g., 14155552671 or +14155552671) for recipient phone numbers in the 'to' parameter of your API requests to Vonage. Avoid spaces, parentheses, or other formatting.
Yes, Vonage supports international SMS. However, different pricing and regulations may apply based on the destination country. Make sure your account allows international messaging before sending SMS globally.
Use tools like curl or Postman to send POST requests to your local endpoint (e.g., http://localhost:3000/send-sms). The request body should be JSON with 'to' and 'text' fields.
Store API credentials in environment variables, use HTTPS, validate and sanitize user input, implement rate limiting to prevent abuse, and never expose your private key.
Trial Vonage accounts require whitelisting destination numbers. Add the recipient's number to your allowed list in the Vonage Dashboard. You will receive a verification code on the whitelisted number to confirm ownership.
Choose a platform like Heroku, AWS, or Google Cloud. Configure environment variables securely, and handle the private key by loading its content directly into an environment variable or storing it securely on the server filesystem. Ensure HTTPS for secure communication.
Build a Vonage SMS Sender with Node.js and Express
Tracking SMS delivery status is critical for production applications that rely on SMS for authentication, notifications, or transactional messages. This comprehensive tutorial shows you how to build a production-ready MessageBird SMS delivery tracking system with a Node.js backend and Vite-powered frontend (React or Vue), implementing secure webhook handling for real-time delivery status updates.
This guide provides a step-by-step walkthrough for building a complete SMS delivery tracking system with MessageBird's webhook callbacks. You'll learn how to send SMS messages via MessageBird's REST API, configure and secure delivery status webhooks, and display real-time delivery updates in a modern Vite + React or Vue frontend application.
By the end of this guide, you will have:
Key Technologies:
System Architecture:
The system consists of three main components: a frontend dashboard (Vite + React/Vue), a Node.js backend API, and MessageBird's webhook service. When you send an SMS, MessageBird assigns it a unique message ID and begins delivery. As the delivery progresses through states (sent → buffered → delivered or failed), MessageBird sends HTTP POST webhooks to your server with status updates. Your webhook handler verifies the signature, updates the database, and the frontend polls or uses WebSockets to display real-time status.
Prerequisites:
Understanding MessageBird Delivery Status Webhooks
Before diving into implementation_ it's essential to understand how MessageBird delivery status webhooks work and why they're critical for production SMS applications.
What Are SMS Delivery Status Webhooks?
When you send an SMS via MessageBird_ the API returns a
201 Created
response with a message ID almost instantly. However_ this doesn't mean the SMS has been delivered to the recipient's phone – it only confirms MessageBird accepted your request. The actual delivery process involves:Delivery status webhooks are HTTP POST callbacks that MessageBird sends to your server URL whenever a message's status changes. This enables you to:
MessageBird Webhook Payload Structure
MessageBird sends webhooks with a JSON payload containing delivery information. Here's a typical webhook payload for a delivered message:
Key Fields for Delivery Tracking:
id
: MessageBird's unique message identifier (use this to correlate with your database)recipients.items[].status
: The delivery status (sent
_buffered
_delivered
_delivery_failed
_expired
)recipients.items[].statusDatetime
: Timestamp when the status was updatedrecipients.items[].recipient
: The phone number that received (or failed to receive) the messagereference
: Your custom reference ID (optional but recommended for linking to orders_ users_ etc.)Webhook Security: Signature Verification
Critical: Always verify webhook signatures to prevent malicious actors from sending fake delivery status updates to your system. MessageBird signs each webhook request using HMAC-SHA256 with your signing key.
The signature is sent in the
MessageBird-Signature
HTTP header. To verify:MessageBird-Signature
header valueExample verification code (we'll implement this in detail later):
Setting Up Your Development Environment
We'll start by setting up the Node.js backend server that handles SMS sending and webhook callbacks.
1. Initialize Node.js Project
Create a new project directory and initialize npm:
2. Install Backend Dependencies
Install the required packages for the Node.js backend:
Package overview:
express
: Web framework for REST API and webhook endpointsmessagebird
: Official MessageBird Node.js SDKdotenv
: Environment variable managementbody-parser
: Middleware to parse webhook JSON payloads (also need raw body for signature verification)For database integration (optional but recommended)_ install:
3. Configure Environment Variables
Create a
.env
file in your project root with your MessageBird credentials:Important: Never commit the
.env
file to version control. Add it to.gitignore
:4. Obtain MessageBird Credentials
Implementing the Backend API
Create
server.js
as your main backend entry point:Key Implementation Details:
verifyWebhookSignature
function runs before the webhook handler, rejecting invalid requestsmessagebird.messages.create()
, we includereportUrl
pointing to our webhook endpointMap
. In production, replace with PostgreSQL, MongoDB, or RedisDatabase Schema for Message Tracking
For production applications, implement a proper database schema to persist message delivery status. Here's an example using PostgreSQL with Prisma:
Prisma Schema (schema.prisma)
Status Values:
pending
,sent
,buffered
,delivered
,delivery_failed
,expired
Database Integration Code
Replace the in-memory
Map
with Prisma:Building the Vite Frontend
Now let's create the frontend dashboard to display real-time delivery status using Vite with React or Vue.
Initialize Vite Project
React Component: Message Status Dashboard
Create
src/components/MessageDashboard.jsx
:Vue Component Alternative
For Vue users, create
src/components/MessageDashboard.vue
:Testing Webhooks Locally with ngrok
MessageBird needs a publicly accessible HTTPS URL to send webhooks. For local development, use ngrok:
1. Install and Run ngrok
ngrok will provide a public URL like
https://abc123.ngrok.io
.2. Update Environment Variables
Update your
.env
file with the ngrok URL:3. Configure MessageBird Dashboard (Optional)
MessageBird also allows configuring default webhook URLs in the dashboard:
Note: The
reportUrl
parameter in the send request overrides the dashboard default.4. Test the Complete Flow
node server.js
cd frontend && npm run dev
http://localhost:5173
)Check your backend logs for webhook payloads:
Security Best Practices
1. Webhook Signature Verification
Always verify the
MessageBird-Signature
header. Never process webhooks without verification:2. Rate Limiting
Protect your endpoints from abuse:
3. HTTPS in Production
Always use HTTPS in production to prevent man-in-the-middle attacks:
4. Environment Variable Security
.env
files to version controlError Handling and Retry Logic
Handling Webhook Delivery Failures
MessageBird will retry failed webhook deliveries up to 10 times with exponential backoff. Ensure your webhook handler:
Handling SMS Send Failures
Implement retry logic for transient failures:
Deployment
Backend Deployment (Node.js)
Deploy your backend to platforms that support webhooks:
Heroku:
Railway:
AWS Lambda + API Gateway:
Use the Serverless Framework or AWS SAM to deploy the Express app as Lambda functions.
Frontend Deployment (Vite)
Vercel:
Netlify:
Update your frontend API calls to use the production backend URL.
Monitoring and Analytics
Track Delivery Metrics
Monitor key SMS delivery metrics:
Integration with Analytics Tools
Send delivery metrics to monitoring platforms:
Troubleshooting Common Issues
Webhooks Not Being Received
Possible causes:
reportUrl
parameter matches your actual endpointSolutions:
Signature Verification Failures
Possible causes:
Solution: Enable debug logging:
Messages Stuck in "Sent" Status
Possible causes:
Solution: Query MessageBird API directly:
Related Resources
Frequently Asked Questions
How do I verify MessageBird webhook signatures?
Extract the
MessageBird-Signature
header, compute HMAC-SHA256 of the raw request body using your signing key, and compare with the header value usingcrypto.timingSafeEqual()
to prevent timing attacks.What MessageBird delivery statuses should I handle?
Handle these key statuses:
sent
(handed to carrier),buffered
(queued at carrier),delivered
(confirmed receipt),delivery_failed
(permanent failure), andexpired
(validity period exceeded).Can I use Vite with other frameworks besides React and Vue?
Yes, Vite supports Svelte, Preact, Lit, and vanilla JavaScript. Use
npm create vite@latest
and select your preferred framework template.How long do MessageBird webhooks take to arrive?
Webhooks typically arrive within 1-30 seconds after status changes. Delivery confirmations depend on carrier speed (usually 5-60 seconds for most carriers).
Do I need a database for production deployments?
Yes, use PostgreSQL, MySQL, or MongoDB to persist message status across server restarts. In-memory storage loses data when the server stops.
How can I test webhooks without deploying to production?
Use ngrok to expose your local development server with a public HTTPS URL. MessageBird will send webhooks to your localhost through the ngrok tunnel.
What happens if my webhook endpoint is down?
MessageBird retries failed webhooks up to 10 times with exponential backoff (up to 24 hours). Ensure your endpoint returns 200 OK quickly to avoid retries.
Can I configure different webhook URLs for different messages?
Yes, use the
reportUrl
parameter when sending each message. This overrides the default webhook URL configured in your MessageBird dashboard.How do I handle duplicate webhook deliveries?
Use the message ID as a unique key in your database. When updating status, use
UPDATE WHERE messageBirdId = ?
which safely handles duplicate webhooks.What's the difference between MessageBird's signing key and access key?
The access key authenticates API requests you send to MessageBird. The signing key validates webhook requests MessageBird sends to you. Never share either key.