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.jsonfile.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.envfilejsonwebtoken: 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.gitignorefile 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.jsonscripts to usedotenv(for loading.envfiles) andpino-pretty(for readable logs) during development:startscript runs the server directly (suitable for production where env vars are set externally)devscript uses-r dotenv/configto preload environment variables from your.envfile before the application starts. It then pipes the JSON output logs throughpino-prettyfor better readability in the terminal5. Installing Vonage SDK (Already Done)
We installed
@vonage/server-sdkandjsonwebtokenin 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.decorateto make thevonageclient easily available within route handlers (request.server.vonage)/api/vonageprefix/healthcheck endpointCreate Server Entry Point (
src/server.js):.envif not preloaded via the script (useful for some debugging scenarios)Create Send Message Route (
src/routes/vonage.js):sendMessageSchemafor request body validation using Fastify's built-in capabilities, including a basic E.164 pattern check for thetonumber/api/vonage/send-whatsapptakes thetonumber andtextfrom the request bodyVONAGE_WHATSAPP_NUMBERfrom environment variables to use as thefromnumbervonage.messages.send()with the required parameters for a text message via WhatsAppvalidateVonageJWThelper function implements JWT validation using thejsonwebtokenlibrary/webhooks/inbound,/webhooks/status) use the helper for signature validation and log incoming data, responding quickly with200 OKTest Sending:
npm run dev(oryarn dev)curl(or a tool like Postman) to send a request. ReplaceYOUR_WHATSAPP_NUMBERwith 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/inboundand/api/vonage/webhooks/status) are already included insrc/routes/vonage.jsfrom 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).3000if your app uses a different port).httpsURL (e.g.,https://random-string.ngrok-free.app)..env: Set theWEBHOOK_BASE_URLin your.envfile to this ngrok URL.Ctrl+C) and restart your Fastify app (npm run dev) to pick up theWEBHOOK_BASE_URLif 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_SECRETin your.envfile exactlyStep 9: Test Your WhatsApp Message Receiving
Test receiving messages now.
npm run dev). You should see logs indicating:Received inbound webhookJWT 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 incomingPOSTrequests 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_SECRETin your.envexactly matches the secret configured in the Vonage Dashboard. Even a single character difference or whitespace will cause failure.httpsand the full path/api/vonage/webhooks/...).jsonwebtokenpackage 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
Authorizationheader 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_SECRETpayload_hashmatches the actual payloadiattimestamp to reject stale tokensImplementation:
The
validateVonageJWTfunction insrc/routes/vonage.jsimplements this validation using thejsonwebtokenlibrary. Ensure you have installed it:Security Best Practices for WhatsApp Webhooks:
.envmust exactly match the one in your Vonage DashboardTroubleshooting Webhook Authentication:
If webhook validation fails:
VONAGE_SIGNATURE_SECRETmatches exactly in both.envand Vonage Dashboardhttpsand the correct pathsjsonwebtokenpackage is installed