Frequently Asked Questions
Use the Vonage Messages API and Node.js SDK within a RedwoodJS service. Create a service function that initializes the Vonage client with your API credentials and uses the vonage.messages.send method with a WhatsAppText object to send messages.
The Vonage Messages API Sandbox is a testing environment provided by Vonage that allows developers to experiment with WhatsApp integration without a dedicated WhatsApp Business Account. It provides a sandbox number and allows you to whitelist personal WhatsApp numbers for testing.
RedwoodJS uses environment variables (.env files) to store sensitive information like API keys and secrets. This approach keeps credentials out of your codebase, improving security and portability across different environments.
The apiHost pointing to the sandbox should be removed from your Vonage client configuration when you deploy your RedwoodJS application to production and are ready to use a live WhatsApp Business Account and number.
While Vonage's primary interaction is through webhooks, you can create GraphQL mutations to trigger outbound WhatsApp messages manually from your RedwoodJS frontend. Define a mutation in your schema, implement a corresponding service function, and call sendWhatsAppMessage within it.
Configure webhook URLs in both your Vonage application settings and the Messages API Sandbox. Use your Ngrok URL combined with the Redwood function paths (e.g., YOUR_NGROK_URL/.redwood/functions/whatsappInbound). This allows Vonage to send incoming messages and status updates to your Redwood application.
Ngrok creates a public URL that tunnels to your local development server, which is essential for Vonage to send webhooks to your RedwoodJS application during development. Vonage webhooks require a publicly accessible URL to reach your local machine.
Create a Redwood function (whatsappStatus) to handle status update webhooks. Verify the JWT signature for security, parse the message status, and update your database accordingly using the handleMessageStatusUpdate service function.
You need Node.js 18+, Yarn, the RedwoodJS CLI, a Vonage API account (with API Key and Secret), Ngrok, a WhatsApp account for testing, basic Git knowledge, and a compatible operating system (macOS, Windows with WSL, or Linux).
Store Vonage credentials (including the private key content) as environment variables in a .env file. Ensure this file is added to your .gitignore. For production, use secure secret management provided by your hosting platform (like Render Environment Variables).
Create a Redwood function (whatsappInbound) as an API endpoint to handle incoming WhatsApp messages. This function will receive message data via webhooks from the Vonage Messages API after you've configured the webhook URL in your Vonage application settings.
RedwoodJS Services encapsulate the core logic for interacting with external APIs like Vonage. They provide a structured way to organize your Vonage API calls, handle authentication, send messages, and process incoming webhooks.
Navigate to the 'api' workspace in your RedwoodJS project and run yarn add @vonage/server-sdk @vonage/messages @vonage/jwt. These packages provide the necessary tools to interact with the Vonage APIs.
Common errors include incorrect environment variable setup, webhook URL misconfiguration, JWT signature verification failures, and issues with parsing JSON payloads. The guide provides troubleshooting tips and error handling suggestions for each step.
Build Vonage WhatsApp Integration with RedwoodJS & Node.js
Integrate Vonage's WhatsApp Business API to send and receive WhatsApp messages within your RedwoodJS application. This comprehensive tutorial shows you how to build a production-ready solution with secure webhook handling, JWT authentication, Prisma database logging, and automated message replies using RedwoodJS Functions and Services.
By the end of this guide, you'll have a fully functional RedwoodJS WhatsApp integration capable of two-way communication, complete with security best practices, error handling, deployment guidance, and troubleshooting strategies for real-world applications.
Project Overview and Goals
What You'll Build:
Create a RedwoodJS application featuring:
Use Cases:
Development Time: Approximately 2-3 hours for initial setup and basic implementation. Additional time required for custom business logic and production hardening.
Skill Level: Intermediate. Requires familiarity with JavaScript/TypeScript, REST APIs, and basic understanding of webhooks and asynchronous messaging patterns.
Problem Solved: This guide enables you to leverage WhatsApp's ubiquity (over 2 billion users worldwide as of 2024) for customer communication, notifications, or bot interactions directly within your RedwoodJS applications, using Vonage as the communication provider. WhatsApp offers higher engagement rates (98% open rate) compared to email (20-25%), making it ideal for time-sensitive communications.
Technologies Used:
Version Compatibility Matrix:
yarn rw upgradeto updateSystem Architecture:
Prerequisites:
npm install -g yarnnpm install -g @redwoodjs/clioryarn global add @redwoodjs/cliVerification Steps:
1. Setting up Your RedwoodJS WhatsApp Project
Create a new RedwoodJS project and configure it for Vonage WhatsApp integration.
Create RedwoodJS App: Open your terminal and run:
Choose TypeScript when prompted for the best development experience. This command scaffolds a complete RedwoodJS project with api and web directories_ configures Prisma_ and sets up the development environment.
Install Vonage SDK Dependencies: Install the Vonage SDKs. Navigate to the
apiworkspace:@vonage/server-sdk: Core SDK for authentication_ general API access_ and initialization of Vonage services@vonage/messages: Specific SDK for the Messages API with WhatsApp_ Viber_ and Facebook Messenger support@vonage/jwt: Verifies webhook signatures using JWT tokens to ensure requests originate from VonageDefine Prisma Schema for Message Logging: Before configuring environment variables_ define the database model for message logging. Open
api/db/schema.prismaand add the MessageLog model:Run Prisma migrations to create the database schema:
Configure Environment Variables: RedwoodJS uses
.envfiles for environment variables. Create a.envfile in your project root:Environment Variable Validation:
Test that environment variables are loaded correctly:
How to Obtain These Values:
VONAGE_API_KEY&VONAGE_API_SECRET: Found on the main page of your Vonage API Dashboard after logging in.VONAGE_APPLICATION_ID&VONAGE_PRIVATE_KEY_CONTENT:private.keyfile that downloads.private.keyfile with a text editor and copy its entire content.VONAGE_PRIVATE_KEY_CONTENTin your.envfile. Make sure to include the-----BEGIN PRIVATE KEY-----and-----END PRIVATE KEY-----lines and enclose the whole thing in double quotes.VONAGE_APPLICATION_IDwill be displayed for your new application. Copy it.VONAGE_API_SIGNATURE_SECRET: Go to the Vonage Dashboard → Settings. Find your API key and click Edit. Your signature secret is listed there. If none exists_ generate one.VONAGE_WHATSAPP_NUMBER: Go to Messages API Sandbox in the Vonage Dashboard. The sandbox number is displayed prominently (often14157386102).Allowlisting Your WhatsApp Number (Required):
To use the Messages API Sandbox_ you must allowlist your personal WhatsApp number:
14157386102Security Considerations:
.envFile: Add.envto your.gitignorefile to prevent committing secrets. Redwood's default.gitignoreusually covers this_ but double-check.VONAGE_PRIVATE_KEY_CONTENTvalue as highly sensitive. Do not commit it to version control. Use platform-specific secret management (like Render Environment Variables_ GitHub Secrets_ etc.) for production deployments.VONAGE_PRIVATE_KEY_CONTENTin all environmentsVONAGE_API_SIGNATURE_SECRET(Settings → API Key → Edit → Regenerate signature secret)Start Ngrok for Webhook Development: Vonage needs a publicly accessible URL to send webhooks. Ngrok creates a secure tunnel to your local machine. The RedwoodJS API server runs on port 8911 by default (defined by
PORTin.env).Ngrok Free Tier Limitations (as of 2024):
Ngrok displays a forwarding URL like
https://<unique_id>.ngrok.ioorhttps://<unique_id>.ngrok.app. Keep this URL handy. Keep this terminal window running.Ngrok Troubleshooting:
yarn rw dev api)Configure Vonage Webhooks: Tell Vonage where to send incoming messages and status updates.
Application Webhooks: Go back to your application settings in the Vonage Dashboard (Applications → Your App → Edit).
YOUR_NGROK_URL/.redwood/functions/whatsappInbound(e.g.,https://xyz.ngrok.app/.redwood/functions/whatsappInbound)YOUR_NGROK_URL/.redwood/functions/whatsappStatus(e.g.,https://xyz.ngrok.app/.redwood/functions/whatsappStatus)Sandbox Webhooks: Go to the Messages API Sandbox page.
Why configure both? The Sandbox Webhooks are used specifically when you interact directly with the Messages API Sandbox environment (using the sandbox number, allowlisted numbers, etc.). The Application Webhooks are tied to your specific Vonage Application (identified by the
VONAGE_APPLICATION_ID). These become relevant when you move beyond the sandbox, potentially using a purchased WhatsApp number linked to that application or utilizing other application-specific features. For initial sandbox testing, configuring both ensures messages sent via the sandbox trigger your endpoints correctly.Why
/.redwood/functions/? This is the default path RedwoodJS exposes its API functions under during development and typically in serverless deployments.Webhook Testing:
After configuration, test webhooks are working:
yarn rw dev api2. Implementing WhatsApp Message Handling (API Side)
Create Redwood Functions to handle the webhooks and a Service to manage Vonage interactions.
Create Redwood Service for Vonage: Services encapsulate business logic in RedwoodJS, providing a clean separation of concerns and making code testable. Generate a service:
This creates
api/src/services/vonage/vonage.ts(and test files).Implement Vonage Service Logic: Open
api/src/services/vonage/vonage.tsand add the following code:Vonageclient using environment variables, now directly usingVONAGE_PRIVATE_KEY_CONTENTfor theprivateKey. The complex file reading logic is removed. Remember to manage theVONAGE_PRIVATE_KEY_CONTENTsecurely, especially in production. The sandboxapiHostis explicitly set; remove this line when deploying to production.validateE164()helper function and validation for phone numbers and message length+[country code][national number]with maximum 15 digits. Examples:+14155552671(US),+442071838750(UK),+34912345678(Spain). Read more at Vonage's E.164 guide.sendWhatsAppMessage: Takestoandtext, usesvonage.messages.sendwithWhatsAppText, logs the outcome, and logs the message to the database. Includes improved error logging.handleInboundWhatsAppMessage: Logs the incoming message and triggerssendWhatsAppMessagefor a reply.handleMessageStatusUpdate: Logs the status update and attempts to update the corresponding message record in the database, including error details if present.logMessage: A helper to encapsulate database logging logic, now withstatusDetails.Create Webhook Functions: Generate the functions to handle HTTP requests from Vonage:
--no-typescriptfor simplicity here, but feel free to use TypeScript.Implement Inbound Webhook Function: Open
api/src/functions/whatsappInbound.js(or.ts) and add:from.number), message text (message.content.text), and message ID (message_uuid).handleInboundWhatsAppMessageservice function.200 OKstatus to Vonage. Basic error handling returns appropriate status codes.Implement Status Webhook Function: Open
api/src/functions/whatsappStatus.js(or.ts) and add:verifySignatureand yourVONAGE_API_SIGNATURE_SECRET. Do not skip this step.handleMessageStatusUpdateservice function.200 OK.Possible Message Status Values:
Common status values from Vonage Messages API (source: Vonage API Errors - Messages):
submitted: Message accepted by Vonagedelivered: Message delivered to recipientread: Message read by recipient (if supported by channel)failed: Message delivery failedrejected: Message rejected by carrier or Vonageundeliverable: Message could not be delivered3. Building a GraphQL API for WhatsApp Messaging
RedwoodJS handles the API layer primarily through GraphQL. While our core interaction uses webhook Functions (plain HTTP endpoints), you could expose functionality via GraphQL if needed for triggering manual sends or building admin interfaces.
Example GraphQL Mutation (Conceptual):
Define Schema: Add to
api/src/graphql/vonage.sdl.ts:Implement Service Function: Add a wrapper in
api/src/services/vonage/vonage.ts:Generate Types:
yarn rw g typesTest: Use the Redwood GraphQL playground (
yarn rw dev, navigate to/graphql) to call the mutation.Authentication with @requireAuth:
The
@requireAuthdirective requires authentication setup. To implement:Set up authentication provider (dbAuth, Auth0, Clerk, etc.):
Follow the setup wizard to create User model in Prisma schema
Run migrations:
The
@requireAuthdirective will now enforce authentication on the mutationFor detailed authentication setup, see RedwoodJS Authentication docs.
This section is optional for the basic webhook setup but shows how to integrate with Redwood's standard API pattern if needed.
4. Understanding Vonage WhatsApp Integration Components
This was covered extensively during setup and implementation. Key points:
.env(use proper secret management like platform environment variables or a secrets manager in production).@vonage/server-sdkand@vonage/messagesin the service layer (api/src/services/vonage/vonage.ts), configured with credentials (reading private key content from env var) and the sandboxapiHost(which should be removed for production)./.redwood/functions/whatsappInbound,/.redwood/functions/whatsappStatus)..envvariable's purpose and origin is detailed in Section 1, Step 4.Common Vonage Integration Issues:
VONAGE_API_SIGNATURE_SECRETis correct, ensure@vonage/jwtpackage is installedVONAGE_WHATSAPP_NUMBERmatches sandbox number, verify number is in E.164 formatVONAGE_PRIVATE_KEY_CONTENT, check for newline encodingyarn rw prisma migrate dev, verifyDATABASE_URLis set correctly5. Error Handling, Logging, and Retry Mechanisms
Logging: Redwood's built-in
pinologger (api/src/lib/logger.ts) is used throughout the service and function code (logger.info,logger.error,logger.warn,logger.debug). SDK logs are also piped to Redwood's logger. Check your console output during development. Configure production log levels and potentially ship logs to a logging service.Error Handling:
try...catchblocks are used in service functions (sendWhatsAppMessage, database interactions) and webhook handlers.Retry Mechanisms:
whatsappInbound,whatsappStatus) don't return a2xxstatus code promptly (within 5 seconds). Vonage will retry with exponential backoff for up to 24 hours. Ensure your functions respond quickly. If processing takes longer, acknowledge the webhook immediately (return 200 OK) and handle the processing asynchronously (e.g., using Redwood experimental background jobs or a dedicated queue).Vonage API Error Codes:
Key error codes from Vonage Messages API Errors:
10001010102010301050107011201160117011801190124012601330134014001420VONAGE_WHATSAPP_NUMBERconfiguration14301460For the complete list, see Vonage Messages API Errors.
Summary
This comprehensive guide covered:
Next Steps:
apiHost: 'https://messages-sandbox.nexmo.com'from Vonage initializationAdditional Resources: