This guide provides a step-by-step walkthrough for building a Node.js and Express application capable of sending and receiving WhatsApp messages using the Vonage Messages API. We will cover everything from project setup and Vonage configuration to handling inbound messages, sending replies, verifying webhook signatures, and essential considerations for a production-ready deployment.
By the end of this tutorial, you will have a functional Express server that:
- Receives incoming WhatsApp messages sent to your Vonage number (or Sandbox number).
- Sends automated text replies back to the user via WhatsApp.
- Verifies the authenticity of incoming webhook requests from Vonage using JWT signatures.
- Logs message events and status updates.
This solves the common need for businesses to programmatically interact with customers on WhatsApp for notifications, support, or automated services.
Technologies Used:
- Node.js: A JavaScript runtime environment (version 20 or higher recommended for latest features and performance; v18 LTS is generally compatible but testing is advised).
- Express: A minimal and flexible Node.js web application framework for building the server and API endpoints (webhooks).
- Vonage Messages API: A unified API for sending and receiving messages across various channels, including WhatsApp, SMS, MMS, and more.
- Vonage Node SDK (
@vonage/server-sdk
): Simplifies interaction with Vonage APIs within a Node.js application. Includes modules for messages (@vonage/messages
) and JWT verification (@vonage/jwt
). - ngrok: A tool to expose your local development server to the internet, necessary for Vonage webhooks to reach your machine during development.
- dotenv: A module to load environment variables from a
.env
file intoprocess.env
.
Prerequisites:
- A Vonage API account. Sign up if you don't have one (free credit is available for new accounts).
- Node.js and npm (or yarn) installed (v20 or higher recommended for latest features and performance; v18 LTS is generally compatible but testing is advised).
- An ngrok account and the ngrok CLI installed.
- A personal WhatsApp account on a smartphone for testing.
- Optional: A WhatsApp Business Account (WABA) for production use beyond the Sandbox.
System Architecture:
graph LR
subgraph Your Infrastructure
A[Node.js/Express App] -- Listens on Port --> B(Local Server: e.g., localhost:8000);
B <-. Forwards Traffic .-> C(ngrok);
end
subgraph Internet
D(User's WhatsApp) -- Sends/Receives --> E(WhatsApp Platform);
E -- Sends/Receives --> F(Vonage Messages API);
end
subgraph Vonage Platform
F -- Webhook (Inbound Msg) --> G{Webhook Endpoint};
F -- Webhook (Status Update) --> G;
G -- Forwards to --> C;
A -- Sends API Request --> F;
end
style Your Infrastructure fill:#f9f,stroke:#333,stroke-width:2px
style Vonage Platform fill:#e6f3ff,stroke:#333,stroke-width:2px
This diagram shows the flow: A user sends a WhatsApp message, which goes through WhatsApp to Vonage. Vonage sends a webhook to your ngrok tunnel, which forwards it to your local Express application. Your application processes the message, sends an API request back to Vonage to send a reply, which Vonage delivers to the user via WhatsApp. Status updates follow a similar webhook path.
Final Outcome:
A running Node.js application that can bidirectionally communicate via WhatsApp using the Vonage Sandbox, ready to be adapted for production use with a purchased Vonage number and a WhatsApp Business Account.
1. Setting up the Project
Let's initialize our Node.js project and install the necessary dependencies.
-
Create Project Directory: Open your terminal and create a new directory for your project, then navigate into it.
mkdir vonage-whatsapp-app cd vonage-whatsapp-app
-
Initialize npm: Initialize a new Node.js project. The
-y
flag accepts default settings.npm init -y
This creates a
package.json
file. -
Create Source Directory: It's good practice to keep your source code in a dedicated directory.
mkdir src
-
Install Dependencies: Install Express for the web server, the Vonage SDK components, and
dotenv
for environment variable management.npm install express dotenv @vonage/server-sdk @vonage/messages @vonage/jwt
Note: While
@vonage/server-sdk
bundles functionality, explicitly listing@vonage/messages
and@vonage/jwt
aligns with the specific import statements used in this guide (import { WhatsAppText } from '@vonage/messages'
, etc.) and ensures clarity. -
Create Core Files: Create the main server file and the environment variable file.
touch src/server.js touch .env
-
Create
.gitignore
: Prevent sensitive information and unnecessary files from being committed to version control. Create a.gitignore
file in the project root:# .gitignore # Dependencies node_modules/ # Environment variables .env # OS generated files .DS_Store Thumbs.db # Log files *.log # Private key file (if stored in project) private.key *.pem
Your initial project structure should look like this:
vonage-whatsapp-app/
├── node_modules/
├── src/
│ └── server.js
├── .env
├── .gitignore
├── package-lock.json
└── package.json
2. Configuring Vonage and Webhooks
Before writing code, we need to configure Vonage by creating an application, setting up the WhatsApp Sandbox (or linking a purchased number), and configuring webhooks to point to our local development environment via ngrok.
-
Create a Vonage Application:
- Log in to your Vonage API Dashboard.
- Navigate to Applications > Create a new application.
- Give your Vonage application a name (e.g.,
""WhatsApp Express Demo""
). - Click Generate public and private key. Crucially, save the
private.key
file that downloads. Move this file into your project's root directory (or a secure location referenced by your environment variable later). The public key is automatically associated with your application on Vonage's side. - Enable the Messages capability.
- You'll see fields for Inbound URL and Status URL. We need an ngrok URL first, so we'll come back to this step.
- Click Create application. Note the Application ID shown on the next page – you'll need it later.
-
Set Up ngrok:
- Open a new terminal window/tab in your project directory.
- Start ngrok, telling it to forward traffic to the port your Express app will run on (we'll use 8000).
ngrok http 8000
- ngrok will display output including a
Forwarding
URL usinghttps
. Copy this HTTPS URL (e.g.,https://xyz-123.ngrok-free.app
). This URL exposes your local server to the internet. Keep ngrok running.
-
Configure Vonage Application Webhooks:
- Go back to your Vonage application settings in the dashboard.
- Under the Messages capability:
- Set Inbound URL to your ngrok HTTPS URL +
/webhooks/inbound
. Example:https://xyz-123.ngrok-free.app/webhooks/inbound
- Set Status URL to your ngrok HTTPS URL +
/webhooks/status
. Example:https://xyz-123.ngrok-free.app/webhooks/status
- Set Inbound URL to your ngrok HTTPS URL +
- Click Save changes at the bottom of the application settings.
-
Set Up Vonage WhatsApp Sandbox:
- For development and testing without needing a dedicated WhatsApp Business Account number immediately, use the Sandbox.
- In the Vonage Dashboard, navigate to Developer Tools > Messages API Sandbox.
- Scan the QR code with your phone's WhatsApp or send the specified message (e.g.,
""Join <keyword>""
) to the provided Sandbox phone number from your personal WhatsApp account. This ""allowlists"" your number for testing with this Sandbox. - Crucially: Configure the Sandbox webhooks. Click the Webhooks tab within the Sandbox page.
- Set Inbound Message URL to your ngrok HTTPS URL +
/webhooks/inbound
. Example:https://xyz-123.ngrok-free.app/webhooks/inbound
- Set Message Status URL to your ngrok HTTPS URL +
/webhooks/status
. Example:https://xyz-123.ngrok-free.app/webhooks/status
- Set Inbound Message URL to your ngrok HTTPS URL +
- Click Save webhooks.
- Note the Sandbox WhatsApp Number provided on this page (e.g.,
14157386102
). This is the number you'll interact with for testing.
-
(Optional - Production) Link a Purchased Number:
- If you intend to go to production, you'll need a dedicated Vonage virtual number capable of WhatsApp messaging and a configured WhatsApp Business Account.
- Purchase a suitable number via the Vonage Dashboard (Numbers > Buy numbers).
- Link this purchased number to your Vonage application (at the bottom of the Application settings page).
- You would then use this purchased number as the
FROM_NUMBER
instead of the Sandbox number.
3. Setting Environment Variables
We need to securely store API keys, secrets, and configuration details. Populate the .env
file in your project root:
# .env
# Vonage API Credentials (Found on Vonage Dashboard homepage)
VONAGE_API_KEY=YOUR_API_KEY
VONAGE_API_SECRET=YOUR_API_SECRET
# Vonage Application Details (Found in your Application settings)
VONAGE_APPLICATION_ID=YOUR_APPLICATION_ID
VONAGE_PRIVATE_KEY=./private.key # Path to your downloaded private key file
# Vonage WhatsApp Number (Use Sandbox number for testing)
# Found on the Messages API Sandbox page
# IMPORTANT: Use E.164 format without leading + or 00 (e.g., 14157386102)
VONAGE_WHATSAPP_NUMBER=VONAGE_SANDBOX_WHATSAPP_NUMBER
# Vonage Signature Secret (Found in Dashboard Settings -> API Settings)
# Used to verify webhook signatures
VONAGE_API_SIGNATURE_SECRET=YOUR_SIGNATURE_SECRET
# Server Configuration
PORT=8000
Explanation of Variables:
VONAGE_API_KEY
: Found on the main page of your Vonage API Dashboard. Identifies your account.VONAGE_API_SECRET
: Found alongside the API Key. Used for authentication.VONAGE_APPLICATION_ID
: The unique ID of the Vonage application you created in Step 2.1. Found in Applications.VONAGE_PRIVATE_KEY
: The file path to theprivate.key
file you downloaded when creating the Vonage application. Ensure this path is correct relative to where you run thenode
command (usually the project root).VONAGE_WHATSAPP_NUMBER
: The Vonage number used for sending/receiving. For testing, use the number shown on the Messages API Sandbox page. For production, use your purchased Vonage number linked to your WABA. Format: E.164 without+
or00
(e.g.,14157386102
).VONAGE_API_SIGNATURE_SECRET
: Found in your main Vonage Dashboard under Settings > API settings. Used to verify that incoming webhooks genuinely originate from Vonage. Crucial for security.PORT
: The local port your Express server will listen on. Must match the port used in thengrok http
command.
Security: Remember to keep your .env
file out of version control (as ensured by .gitignore
) and manage secrets appropriately in production environments (e.g., using environment variables provided by your hosting platform or a secrets manager).
src/server.js
)
4. Implementing the Core Logic (Now, let's write the code for our Express server to handle Vonage webhooks and send messages.
// src/server.js
// 1. Import Dependencies
require('dotenv').config(); // Load .env variables into process.env
const express = require('express');
const { Vonage } = require('@vonage/server-sdk');
const { WhatsAppText } = require('@vonage/messages');
const { verifySignature } = require('@vonage/jwt');
// 2. Initialize Express App
const app = express();
// Middleware to parse JSON bodies (essential for Vonage webhooks)
app.use(express.json());
// Middleware to parse URL-encoded bodies (less critical for this specific API, but good practice)
app.use(express.urlencoded({ extended: true }));
// 3. Initialize Vonage Client
// Use environment variables for credentials and configuration
// The 'apiHost' option directs requests to the Sandbox environment.
// Remove 'apiHost' when using a production WhatsApp Business Account number.
const vonage = new Vonage(
{
apiKey: process.env.VONAGE_API_KEY,
apiSecret: process.env.VONAGE_API_SECRET,
applicationId: process.env.VONAGE_APPLICATION_ID,
privateKey: process.env.VONAGE_PRIVATE_KEY,
},
{
// IMPORTANT: Use sandbox host for testing with the Sandbox number.
// REMOVE this option for production use with a purchased number.
apiHost: 'https://messages-sandbox.nexmo.com',
}
);
// 4. Webhook Signature Verification Middleware (Security)
// This function checks if the incoming request genuinely came from Vonage
const vonageWebhookVerification = (req, res, next) => {
try {
// Get the authorization header (should contain the JWT)
const authHeader = req.headers.authorization;
if (!authHeader || !authHeader.startsWith('Bearer ')) {
console.error('__ Error: Missing or invalid Authorization header.');
return res.status(401).send('Unauthorized: Missing or invalid token');
}
const token = authHeader.split(' ')[1];
// Verify the JWT signature using your Signature Secret
if (verifySignature(token, process.env.VONAGE_API_SIGNATURE_SECRET)) {
console.log('_ JWT Signature Verified');
next(); // Signature is valid, proceed to the route handler
} else {
console.error('__ Error: Invalid JWT Signature.');
return res.status(401).send('Unauthorized: Invalid signature');
}
} catch (error) {
console.error('__ Error verifying webhook signature:', error);
return res.status(401).send('Unauthorized: Signature verification failed');
}
};
// 5. Inbound Message Webhook Endpoint
// Handles messages sent FROM users TO your Vonage number
app.post('/webhooks/inbound', vonageWebhookVerification, async (req, res) => {
console.log(' M INBOUND MESSAGE RECEIVED M ');
console.log('Request Body:', JSON.stringify(req.body, null, 2)); // Log the full incoming payload
// Extract key information (adjust based on actual payload structure)
const senderNumber = req.body.from?.number; // User's WhatsApp number
const messageContent = req.body.message?.content?.text; // The text they sent
const vonageNumber = req.body.to?.number; // Your Vonage number that received it
if (!senderNumber) {
console.error('__ Error: Could not extract sender number from inbound webhook.');
// Send 200 OK even if processing fails, otherwise Vonage retries
return res.status(200).send('OK');
}
console.log(`Received message """"""""${messageContent}"""""""" from ${senderNumber}`);
// --- Your Business Logic Here ---
// Example: Send a simple reply acknowledging receipt
try {
const replyText = `__ Received your message: """"""""${messageContent}""""""""`;
await sendWhatsAppReply(senderNumber, replyText);
} catch (error) {
console.error('__ Error sending WhatsApp reply:', error);
// Log error but still send 200 OK to Vonage
}
// --- End Business Logic ---
// Always respond with 200 OK to acknowledge receipt to Vonage,
// otherwise, Vonage will retry sending the webhook.
res.status(200).send('OK');
});
// 6. Status Webhook Endpoint
// Handles delivery receipts and status updates for messages SENT BY your app
app.post('/webhooks/status', vonageWebhookVerification, (req, res) => {
console.log(' S STATUS UPDATE RECEIVED S '); // Consistent spacing applied
console.log('Request Body:', JSON.stringify(req.body, null, 2)); // Log the full status payload
// Extract key information
const messageUuid = req.body.message_uuid;
const status = req.body.status;
const timestamp = req.body.timestamp;
console.log(`Status update for message ${messageUuid}: ${status} at ${timestamp}`);
// --- Your Logic for Handling Status Updates ---
// e.g., Update message status in a database, trigger other actions on delivery/failure
// --- End Status Handling Logic ---
// Always respond with 200 OK to acknowledge receipt
res.status(200).send('OK');
});
// 7. Function to Send WhatsApp Messages
// Encapsulates the logic for sending a message via Vonage
async function sendWhatsAppReply(recipientNumber, messageText) {
console.log(`Attempting to send reply to ${recipientNumber}...`);
try {
const response = await vonage.messages.send(
new WhatsAppText({
text: messageText,
to: recipientNumber, // User's number (the 'from' number in the inbound webhook)
from: process.env.VONAGE_WHATSAPP_NUMBER, // Your Vonage Sandbox/WABA number
// client_ref: 'your-internal-reference' // Optional: Add your own reference ID
})
);
console.log(`_ Message sent successfully with UUID: ${response.messageUUID}`);
return response; // Contains message_uuid
} catch (error) {
console.error(
'_ Error sending WhatsApp message:',
error.response ? JSON.stringify(error.response.data, null, 2) : error.message
);
// Re-throw the error for the caller to handle if needed, or handle here
throw error;
}
}
// 8. Start the Server
const port = process.env.PORT || 8000;
app.listen(port, () => {
console.log(`__ Server listening on http://localhost:${port}`);
console.log(`__ ngrok should be forwarding to this port.`);
console.log('Waiting for WhatsApp messages... Ensure ngrok is running.');
});
Code Explanation:
- Imports: Loads
dotenv
first, thenexpress
and the necessary Vonage SDK components. - Express Init: Creates the Express app and adds middleware to parse incoming JSON and URL-encoded request bodies.
express.json()
is vital for Vonage webhooks. - Vonage Client Init: Initializes the Vonage client using credentials from
.env
. TheapiHost
option is critical for directing requests to the Sandbox; remove it for production. - Webhook Verification Middleware: This function (
vonageWebhookVerification
) intercepts requests to webhook endpoints. It extracts theBearer
token from theAuthorization
header and usesverifySignature
from@vonage/jwt
along with yourVONAGE_API_SIGNATURE_SECRET
to validate the request. If verification fails, it sends a401 Unauthorized
response. If successful, it callsnext()
to pass control to the actual route handler (/webhooks/inbound
or/webhooks/status
). This is applied as middleware specifically to the webhook routes. - /webhooks/inbound: This
POST
route handles incoming messages from users. It first runs the verification middleware. If verified, it logs the request body, extracts the sender's number and message content, logs them, calls thesendWhatsAppReply
function to send an acknowledgement, and finally must send a200 OK
response back to Vonage to prevent retries. - /webhooks/status: This
POST
route handles status updates (e.g.,delivered
,read
,failed
) for messages you sent. It also uses the verification middleware. It logs the status details and sends200 OK
. You would add logic here to update database records or track message delivery. - sendWhatsAppReply Function: A helper function that takes the recipient's number and message text, creates a
WhatsAppText
object, and usesvonage.messages.send()
to send the message via the Vonage API. It includes basic logging and error handling usingtry...catch
. - Server Start: Starts the Express server, listening on the port defined in
.env
(defaulting to 8000).
5. Testing the Integration
Now, let's run the application and test sending/receiving messages.
- Ensure ngrok is Running: Check the terminal window where you started ngrok. It should still be running and show
""Session Status online""
. If not, restart it (ngrok http 8000
). Verify the HTTPS URL hasn't changed; if it has, update the webhook URLs in your Vonage application and Sandbox settings. - Start the Node.js Server: Open your main project terminal (where
package.json
is) and run:You should see output like:node src/server.js
__ Server listening on http://localhost:8000 __ ngrok should be forwarding to this port. Waiting for WhatsApp messages... Ensure ngrok is running.
- Send a WhatsApp Message:
- Using your personal WhatsApp account (the one you allowlisted with the Sandbox), send a message to the Vonage Sandbox WhatsApp number (e.g.,
14157386102
).
- Using your personal WhatsApp account (the one you allowlisted with the Sandbox), send a message to the Vonage Sandbox WhatsApp number (e.g.,
- Observe Server Logs:
- In the terminal running
node src/server.js
, you should see logs indicating:_ JWT Signature Verified
(from the verification middleware).M INBOUND MESSAGE RECEIVED M
- The full JSON payload of the inbound message.
Received message """"""""<Your message text>"""""""" from <Your WhatsApp Number>
Attempting to send reply to <Your WhatsApp Number>...
_ Message sent successfully with UUID: <message-uuid>
- In the terminal running
- Check Your WhatsApp:
- You should receive a reply on your personal WhatsApp from the Sandbox number saying something like:
__ Received your message: """"""""<Your original message text>""""""""
- You should receive a reply on your personal WhatsApp from the Sandbox number saying something like:
- Observe Status Logs:
- Shortly after the reply is sent, you should see status update logs in your server terminal:
_ JWT Signature Verified
S STATUS UPDATE RECEIVED S
- The full JSON payload of the status update (showing
submitted
, then potentiallydelivered
orread
). Status update for message <message-uuid>: submitted at <timestamp>
(and subsequent statuses).
- Shortly after the reply is sent, you should see status update logs in your server terminal:
If you see these logs and receive the reply, your basic integration is working!
6. Security Considerations
- Webhook Signature Verification: As implemented, this is the most critical security measure. Never disable it. It ensures that only Vonage can send data to your webhook endpoints. Keep your
VONAGE_API_SIGNATURE_SECRET
secure. - Environment Variables: Never commit
.env
files or hardcode secrets (API Key, Secret, Signature Secret, Private Key path) directly in your code. Use environment variables provided by your deployment environment in production. - Input Sanitization: While less critical for this simple echo bot, if you process user input for database queries, API calls, or display it elsewhere, always sanitize it to prevent injection attacks (e.g., XSS, SQL injection). Libraries like
DOMPurify
(for HTML) or parameterized queries (for SQL) are essential. - Rate Limiting: Implement rate limiting on your webhook endpoints (using libraries like
express-rate-limit
) to prevent abuse or denial-of-service attacks if your endpoint becomes public. - HTTPS: Always use HTTPS for your webhook URLs (ngrok provides this automatically; ensure your production deployment does too) to encrypt data in transit.
7. Error Handling and Logging
The current implementation includes basic console.log
and console.error
. For production:
- Structured Logging: Use a dedicated logging library (like
winston
orpino
) to create structured logs (e.g., JSON format) with timestamps, log levels (info, warn, error), and request context. This makes searching and analysis much easier. - Centralized Logging: Send logs to a centralized logging platform (e.g., Datadog, Logz.io, ELK stack) for aggregation and monitoring.
- Detailed Error Reporting: Catch errors explicitly, log detailed stack traces, and potentially send alerts to an error tracking service (e.g., Sentry, Rollbar) for critical failures.
- Graceful Shutdown: Implement graceful shutdown logic for your server to finish processing ongoing requests before exiting, preventing data loss.
- Retry Mechanisms (for sending): While Vonage handles retries for receiving webhooks, you might implement retries with exponential backoff in your
sendWhatsAppReply
function if the initial API call to Vonage fails due to temporary network issues. Be careful not to retry on non-retriable errors (like invalid number format).
8. Troubleshooting and Caveats
- Webhook Not Reaching Server:
- Check ngrok: Is it running? Is the URL correct in Vonage settings (Application and Sandbox)? Is the port correct (
ngrok http 8000
andPORT=8000
)? - Check Firewall: Any local firewall blocking incoming connections?
- Check Server Logs: Any startup errors in
node src/server.js
?
- Check ngrok: Is it running? Is the URL correct in Vonage settings (Application and Sandbox)? Is the port correct (
401 Unauthorized
Errors in Logs:- Incorrect
VONAGE_API_SIGNATURE_SECRET
in.env
. Verify it in Dashboard > Settings. - Issue with the JWT token sent by Vonage (less likely, but possible). Check Vonage status pages.
- Problem in your verification logic (compare with the example).
- Incorrect
- Message Sending Fails:
- Check
VONAGE_API_KEY
,VONAGE_API_SECRET
,VONAGE_APPLICATION_ID
,VONAGE_PRIVATE_KEY
path in.env
. - Ensure
apiHost
is set correctly (use sandbox URL for sandbox testing, remove for production). - Check recipient number format (E.164 required, no
+
). - Are you using the Sandbox? Ensure the recipient number is allowlisted in the Sandbox settings.
- Check Vonage API status for outages.
- Examine the detailed error response logged by the
catch
block insendWhatsAppReply
.
- Check
- Sandbox Limitations: The Sandbox can only send messages to numbers explicitly allowlisted by scanning the QR code or sending the join keyword. It cannot send to arbitrary numbers. Production requires a purchased Vonage number and a configured WhatsApp Business Account.
- Rate Limits: Be aware of Vonage API rate limits, especially when sending bulk messages. Check Vonage documentation for details.
- WhatsApp Templates: For sending unsolicited messages (notifications) more than 24 hours after the last user interaction, WhatsApp requires pre-approved Message Templates. The
WhatsAppText
object used here is for ""session messages"" (replies within 24 hours). Sending templates requires different objects (WhatsAppTemplate
) and setup.
9. Deployment Considerations (Conceptual)
Moving from local development (with ngrok) to production requires:
- Hosting: Deploy your Node.js application to a hosting provider (e.g., Heroku, AWS EC2/Lambda/ECS, Google Cloud Run/App Engine, DigitalOcean App Platform).
- Permanent Webhook URL: Your hosting provider will give you a stable public URL. Update the Inbound and Status webhook URLs in your Vonage application settings to use this permanent HTTPS URL. You no longer need ngrok.
- Environment Variables: Configure your production environment variables securely using your hosting provider's interface or a secrets management service. Do not commit
.env
to production. - Remove Sandbox
apiHost
: If using a purchased number and WABA, remove the{ apiHost: '...' }
option when initializing the Vonage client insrc/server.js
. - Process Management: Use a process manager (like
pm2
) to keep your Node.js application running reliably, manage clustering for performance, and handle restarts. - CI/CD: Set up a Continuous Integration/Continuous Deployment pipeline (e.g., GitHub Actions, GitLab CI, Jenkins) to automate testing and deployment whenever you push changes to your code repository.
- Monitoring & Alerting: Implement health checks, performance monitoring (CPU, memory, response times), and alerting for errors or downtime using tools provided by your host or third-party services.
10. Verification Checklist
Before considering the integration complete, verify:
- Project dependencies are installed (
npm install
). -
.env
file is created and populated with correct Vonage credentials, App ID, Sandbox/WABA number, Signature Secret, and private key path. -
private.key
file exists at the path specified in.env
. - Vonage application is created, Messages capability enabled.
- ngrok (for local) or permanent URL (for production) is correctly configured for Inbound and Status webhooks in both the Vonage application settings and Vonage Sandbox settings (if using Sandbox).
- Personal WhatsApp number is allowlisted in the Vonage Sandbox (if using Sandbox).
- Node.js server starts without errors (
node src/server.js
). - Sending a message from the allowlisted WhatsApp to the Vonage number triggers the
/webhooks/inbound
endpoint (check server logs). - JWT signature is successfully verified for inbound messages (check logs for
_ JWT Signature Verified
). - An automated reply is received on the personal WhatsApp.
- The
/webhooks/status
endpoint receives delivery status updates (check logs). - JWT signature is successfully verified for status updates.
- No sensitive credentials are hardcoded in
src/server.js
. -
.gitignore
prevents.env
,node_modules
, andprivate.key
from being committed.
Conclusion
You have successfully built a Node.js and Express application capable of sending and receiving WhatsApp messages using the Vonage Messages API and its Sandbox environment. You've implemented essential features like webhook handling, signature verification for security, and sending replies.
This forms a solid foundation. Next steps could include:
- Integrating a database (like PostgreSQL, MongoDB, or Airtable) to store conversation history.
- Implementing more sophisticated conversational logic (e.g., using NLP or simple state machines).
- Adding support for WhatsApp Message Templates for outbound notifications.
- Transitioning to a production environment with a purchased Vonage number and a WhatsApp Business Account.
- Enhancing error handling, logging, and monitoring for production robustness.
Remember to consult the Vonage Messages API documentation for more advanced features and channel options.
Disclaimer: Vonage API features and dashboard layouts may change over time. Always refer to the official Vonage documentation for the most current information.