Frequently Asked Questions
Use the Vonage Messages API with Node.js and a framework like Fastify. The Vonage Node.js SDK simplifies sending messages via WhatsApp. Create a route in your Fastify app that takes the recipient's number and message text and calls vonage.messages.send()
with the appropriate parameters, including channel: "whatsapp"
.
The Vonage Messages API is a unified API that allows you to send and receive messages across multiple channels, including WhatsApp, SMS, MMS, and Facebook Messenger. This tutorial focuses on its WhatsApp capabilities for two-way communication.
Fastify is a high-performance Node.js web framework known for its speed and ease of use. It's ideal for building robust and efficient applications that interact with APIs like the Vonage Messages API, especially for real-time or high-throughput scenarios.
Vonage uses webhooks to deliver incoming WhatsApp messages and status updates to your application. You'll need to configure URLs in your Vonage dashboard that point to specific routes in your Fastify app. These routes will then process the incoming webhook data, such as sender number and message content. Secure these webhooks using the HMAC-SHA256 signature validation mechanism described in the article to ensure authenticity.
Webhook signature validation is essential for ensuring requests originate from Vonage and haven't been tampered with. It is critically important to do this verification on the raw, unparsed request body to prevent vulnerabilities. You should validate signatures on every webhook request received.
Capture the raw request body using Fastify's app.addContentTypeParser
before the body is parsed as JSON. Then, use the crypto
module in Node.js, along with your unique VONAGE_SIGNATURE_SECRET
(configured in both the Vonage dashboard and your .env file), to calculate an HMAC-SHA256 signature. Compare this calculated signature with the one provided in the x-vonage-hmac-sha256
(or similarly named) header from Vonage.
ngrok creates a secure tunnel that allows Vonage webhooks to reach your locally hosted application during development. It provides a publicly accessible URL that forwards requests to your localhost server, essential for testing interactions with Vonage during local development before deploying to a public server.
Yes, you can use Express.js, NestJS, or other Node.js frameworks, but you'll need to adapt the specific setup and routing to your framework's way of creating HTTP endpoints and handling middleware. The Vonage SDK will work with any Node.js compatible framework.
The @vonage/server-sdk
package is a Node.js library provided by Vonage to streamline interactions with Vonage APIs. It provides convenient methods for sending SMS messages, making voice calls, managing users, and other Vonage API functionalities including working with the messages API.
In your Vonage Dashboard, navigate to "Messages and Dispatch" > "Sandbox." Activate the WhatsApp Sandbox either by scanning the QR code with your WhatsApp app or by sending a designated text message to the Vonage sandbox number provided in the dashboard. The Sandbox allows you to test receiving WhatsApp messages without a dedicated WhatsApp Business account. This is critical for initial development and testing.
Use a .env
file to store sensitive information like API keys and secrets. You can use the dotenv
package in Node.js to load these environment variables into your application. Create a .env.example
file with placeholders for required environment variables to act as a template.
The project demonstrates how to create a production-ready Node.js application, using Fastify, that integrates with the Vonage Messages API to send and receive WhatsApp messages. It covers aspects such as API setup, sending messages, handling incoming webhooks securely, and development setup using tools like ngrok.
Note: This article covers Vonage Messages API integration. The filename references Twilio, but the content is specifically for Vonage's WhatsApp Business API.
Learn how to send and receive WhatsApp messages programmatically using the Vonage Messages API with Node.js v22 and Fastify v5. This step-by-step tutorial shows you how to build a production-ready WhatsApp integration, from initial setup to secure webhook handling with JWT authentication, complete with working code examples you can deploy today.
This integration enables real-world use cases like customer support automation, appointment reminders, order notifications, two-factor authentication (2FA), and interactive chatbots—all through WhatsApp Business API.
By the end of this tutorial, you'll have a functional Fastify application capable of:
This guide assumes you have foundational knowledge of Node.js, asynchronous programming (
async
/await
), and REST APIs.What You'll Build: WhatsApp Messaging API Integration
Problem: Businesses need reliable ways to communicate with customers on preferred channels like WhatsApp. Building this integration from scratch involves handling API authentication, message sending protocols, receiving incoming messages (webhooks), and securing these endpoints.
Solution: Build a Node.js backend using the Fastify framework to interact with the Vonage Messages API. This provides a structured way to send messages and expose secure HTTP endpoints (webhooks) for receiving messages and delivery status updates from WhatsApp via Vonage.
Technologies:
@vonage/server-sdk
): Simplifies interaction with Vonage APIs in Node.js applicationsdotenv
: Manages environment variables securelyngrok
(for development): Exposes local development servers to the internet for webhook testingjsonwebtoken
: Validates JWT tokens for webhook authenticationFor additional messaging options, see our guides on SMS integration with E.164 formatting and 10DLC registration for US phone numbers.
System Architecture:
(Note: Ensure your publishing platform supports Mermaid diagram rendering.)
Prerequisites:
Version Compatibility (2025):
@vonage/server-sdk
)Final Outcome: A Fastify application with endpoints to send WhatsApp messages and receive/validate incoming message webhooks from Vonage with production-ready security.
Step 1: Set Up Your Node.js Development Environment
Ensure Node.js and npm/yarn are installed. Verify by opening your terminal and running:
If not installed, download and install Node.js from nodejs.org. For additional setup guidance, check our Node.js SMS tutorial with Express which covers similar environment configuration.
Step 2: Create Your Fastify Project Structure
Create your project directory and initialize it with npm (or yarn).
Create Project Directory:
Initialize Node.js Project:
This creates a
package.json
file.Install Dependencies: Install production dependencies first:
Then, install development dependencies like
pino-pretty
:fastify
: The web framework@vonage/server-sdk
: The official Vonage Node SDK for WhatsApp messagingdotenv
: Loads environment variables from a.env
filejsonwebtoken
: Validates JWT tokens for webhook authenticationpino-pretty
: (Dev Dependency) Makes Fastify's logs more readable during developmentSet up Basic Project Structure: Create the following files and directories:
Configure
.gitignore
: Create a.gitignore
file to prevent committing sensitive information and unnecessary files:Step 3: Configure Your Vonage WhatsApp Account
Configure your Vonage account and the WhatsApp Sandbox before writing code.
Step 4: Set Up API Credentials and Environment Variables
Use environment variables to store sensitive credentials and configuration details.
Create
.env.example
: This file serves as a template for required variables.Create
.env
: Duplicate.env.example
, rename it to.env
, and fill in your actual values.VONAGE_API_KEY
,VONAGE_API_SECRET
: From your Vonage dashboardVONAGE_WHATSAPP_NUMBER
: The phone number provided on the Vonage WhatsApp Sandbox pageVONAGE_SIGNATURE_SECRET
: Obtain this from your Vonage Dashboard under the webhook settings for Messages API. This is the shared secret used to validate JWT tokens in webhook requests.PORT
,HOST
,LOG_LEVEL
: Default application settingsWEBHOOK_BASE_URL
: Leave this blank for now; fill it when running ngrokVONAGE_APPLICATION_ID
,VONAGE_PRIVATE_KEY_PATH
: Not required for the basic authentication method (API Key/Secret) used in this guide but needed for advanced JWT-based authentication featuresLoad Environment Variables: Modify your
package.json
scripts to usedotenv
(for loading.env
files) andpino-pretty
(for readable logs) during development:start
script runs the server directly (suitable for production where env vars are set externally)dev
script uses-r dotenv/config
to preload environment variables from your.env
file before the application starts. It then pipes the JSON output logs throughpino-pretty
for better readability in the terminal5. Installing Vonage SDK (Already Done)
We installed
@vonage/server-sdk
andjsonwebtoken
in Step 2. These packages provide convenient methods for interacting with the Vonage API and validating webhook JWTs.Step 6: How to Send WhatsApp Messages Programmatically
Create the Fastify application structure and add a route to send messages.
Set up Fastify App (
src/app.js
):app.decorate
to make thevonage
client easily available within route handlers (request.server.vonage
)/api/vonage
prefix/health
check endpointCreate Server Entry Point (
src/server.js
):.env
if not preloaded via the script (useful for some debugging scenarios)Create Send Message Route (
src/routes/vonage.js
):sendMessageSchema
for request body validation using Fastify's built-in capabilities, including a basic E.164 pattern check for theto
number/api/vonage/send-whatsapp
takes theto
number andtext
from the request bodyVONAGE_WHATSAPP_NUMBER
from environment variables to use as thefrom
numbervonage.messages.send()
with the required parameters for a text message via WhatsAppvalidateVonageJWT
helper function implements JWT validation using thejsonwebtoken
library/webhooks/inbound
,/webhooks/status
) use the helper for signature validation and log incoming data, responding quickly with200 OK
Test Sending:
npm run dev
(oryarn dev
)curl
(or a tool like Postman) to send a request. ReplaceYOUR_WHATSAPP_NUMBER
with your actual number linked to the Vonage Sandbox (in E.164 format, e.g.,+14155552671
){"message_uuid":"...","detail":"Message sent to YOUR_WHATSAPP_NUMBER"}
). Check the server logs as well.Step 7: How to Receive WhatsApp Messages via Webhooks
Vonage uses webhooks to notify your application about incoming WhatsApp messages and message status updates. The routes for this (
/api/vonage/webhooks/inbound
and/api/vonage/webhooks/status
) are already included insrc/routes/vonage.js
from the previous step.Step 8: Expose Your Local Server for Webhook Testing
Allow Vonage's servers to reach your local development machine using ngrok.
npm run dev
. Note the port (default is 3000).3000
if your app uses a different port).https
URL (e.g.,https://random-string.ngrok-free.app
)..env
: Set theWEBHOOK_BASE_URL
in your.env
file to this ngrok URL.Ctrl+C
) and restart your Fastify app (npm run dev
) to pick up theWEBHOOK_BASE_URL
if your code uses it (though it's primarily for configuring Vonage).YOUR_NGROK_HTTPS_URL/api/vonage/webhooks/inbound
(e.g.,https://<your-random-string>.ngrok-free.app/api/vonage/webhooks/inbound
)YOUR_NGROK_HTTPS_URL/api/vonage/webhooks/status
(e.g.,https://<your-random-string>.ngrok-free.app/api/vonage/webhooks/status
)VONAGE_SIGNATURE_SECRET
in your.env
file exactlyStep 9: Test Your WhatsApp Message Receiving
Test receiving messages now.
npm run dev
). You should see logs indicating:Received inbound webhook
JWT signature validated successfully.
(if validation passes)Inbound message data: { ... }
(showing the message payload)Message from <your_number>: <your_message_text>
ngrok http 3000
) will also show incomingPOST
requests to your webhook URLs (e.g.,POST /api/vonage/webhooks/inbound 200 OK
).If you see errors, especially related to signature validation (401 Unauthorized response in ngrok, validation failure logs in Fastify):
VONAGE_SIGNATURE_SECRET
in your.env
exactly matches the secret configured in the Vonage Dashboard. Even a single character difference or whitespace will cause failure.https
and the full path/api/vonage/webhooks/...
).jsonwebtoken
package is installed.Step 10: Secure Your WhatsApp Webhooks with JWT Authentication
Validating webhook signatures is critical to ensure requests genuinely come from Vonage and haven't been tampered with or forged.
Vonage Messages API Webhook Security:
Vonage uses JSON Web Token (JWT) Bearer Authorization for webhooks sent from the Messages API. This provides robust authentication different from HMAC signature validation.
How JWT Webhook Authentication Works:
Authorization Header: Vonage includes a JWT in the
Authorization
header of each webhook request in the format:Authorization: Bearer <jwt_token>
JWT Contents: The JWT is signed using HMAC-SHA256 with your signature secret and contains:
iat
– issued at timestamp)payload_hash
– SHA-256 hash of the webhook payload for tamper detectionValidation Process:
VONAGE_SIGNATURE_SECRET
payload_hash
matches the actual payloadiat
timestamp to reject stale tokensImplementation:
The
validateVonageJWT
function insrc/routes/vonage.js
implements this validation using thejsonwebtoken
library. Ensure you have installed it:Security Best Practices for WhatsApp Webhooks:
.env
must exactly match the one in your Vonage DashboardTroubleshooting Webhook Authentication:
If webhook validation fails:
VONAGE_SIGNATURE_SECRET
matches exactly in both.env
and Vonage Dashboardhttps
and the correct pathsjsonwebtoken
package is installed