Frequently Asked Questions
Integrate WhatsApp with RedwoodJS using AWS SNS and AWS End User Messaging Social. This involves setting up a RedwoodJS API function as a webhook endpoint to receive incoming WhatsApp messages and send replies via the AWS SDK.
AWS End User Messaging Social is an AWS service that connects your WhatsApp Business Account (WABA) to your AWS account, enabling seamless integration with other AWS services like SNS for message handling.
AWS SNS acts as a pub/sub messaging service, allowing AWS End User Messaging Social to publish incoming WhatsApp messages to an SNS topic, which your RedwoodJS application can subscribe to for real-time message processing.
Use pre-approved WhatsApp Message Templates when replying to users outside the 24-hour free-form message window. Within 24 hours of a user's last message, you can send free-form text replies.
Yes, you can store WhatsApp message details in a database using Prisma, RedwoodJS's default ORM. Define a schema in `schema.prisma` and use the Prisma client in your API function to save incoming and outgoing message data.
Create a RedwoodJS API function (e.g., `whatsappWebhook`) and deploy it to a public HTTPS URL. Subscribe this URL to your AWS SNS topic, which receives messages from AWS End User Messaging Social linked to your WhatsApp Business Account.
WhatsApp allows free-form text replies only within 24 hours of a user's last message. Outside this window, use pre-approved Message Templates, which have a different structure within the AWS Social Post Messaging API.
Within your RedwoodJS webhook function, validate that the `TopicArn` in the `SubscriptionConfirmation` message matches your expected ARN, then use the AWS SDK's `ConfirmSubscriptionCommand` to programmatically confirm the subscription.
Zod is used for validating the incoming WhatsApp payload structure within the RedwoodJS function. It ensures data integrity by checking against a predefined schema, protecting your app from unexpected data formats.
Use the AWS SDK for JavaScript v3, specifically the `SocialPostMessagingClient` (or similar) and `SendWhatsappMessageCommand` with the correct parameters to send replies from your RedwoodJS API function to users' WhatsApp numbers.
Your RedwoodJS function needs AWS credentials to interact with AWS services (SNS, End User Messaging Social, etc.). Securely manage these using environment variables, IAM roles (recommended for production), or secrets management tools.
SNS signature verification validates that incoming webhook requests originate from AWS SNS, ensuring security. Use the `aws-sns-verify` library in your RedwoodJS function to verify the signature before processing any message data.
A DLQ (SQS queue) captures messages that SNS fails to deliver to your RedwoodJS webhook after multiple retries. This enables inspecting and potentially reprocessing failed messages, preventing data loss.
Implement `try...catch` blocks and logging for robust error handling. Return appropriate HTTP status codes (e.g., 403 for invalid signature, 400 for bad payload, 500 for processing errors or failed subscription confirmation to allow retries) to manage SNS retries and DLQ routing.
Developer Guide: Integrating RedwoodJS with WhatsApp using AWS SNS
This guide provides a step-by-step walkthrough for building a production-ready integration between a RedwoodJS application and WhatsApp, leveraging AWS Simple Notification Service (SNS) and AWS End User Messaging Social for seamless message handling.
Project Overview and Goals
This guide details how to build a system where your RedwoodJS application can receive incoming WhatsApp messages sent to your business number and send replies back to users.
Problem Solved: Businesses need effective ways to communicate with customers on preferred platforms like WhatsApp. This integration enables automated responses, custom workflows, and data logging triggered by customer messages directly within your RedwoodJS application.
Technologies Used:
System Architecture:
Expected Outcome: A RedwoodJS application capable of:
Prerequisites:
npm install -g yarn
).aws configure
).1. Setting up the RedwoodJS Project
First, create a new RedwoodJS project if you don't have one already.
Create RedwoodJS App: Open your terminal and run:
Choose your preferred options (TypeScript recommended).
Environment Variables: RedwoodJS uses a
.env
file for environment variables. Create one in the project root:Add the following placeholders. We will populate these later.
Important: Add
.env
to your.gitignore
file to avoid committing secrets. For production deployments, use environment variables provided by your hosting platform or secrets management tools instead of hardcoding AWS keys. IAM roles are the recommended approach for AWS deployments.Install AWS SDK: Install the necessary AWS SDK v3 clients for SNS and Social Messaging. Note: The package name
@aws-sdk/client-social-post-messaging
is used here based on available information. Verify this is the correct and current package name in the official AWS SDK v3 documentation, as it might be part of Pinpoint, Chime SDK Messaging, or another service.Install the library for SNS signature verification:
Install Zod for validation:
Install cuid if saving outgoing messages with temporary IDs (Section 6):
2. Implementing Core Functionality: The API Function
We'll create a RedwoodJS API function to act as the webhook endpoint for SNS notifications.
Generate API Function: Use the RedwoodJS CLI to generate a new function:
This creates
api/src/functions/whatsappWebhook.ts
and a test file.Implement Function Logic (Initial Version - Receiving & Parsing): Replace the contents of
api/src/functions/whatsappWebhook.ts
with the following code. This version includes SNS verification and parsing, preparing for reply logic.Explanation:
handler
receives the HTTP request from SNS.aws-sns-verify
to ensure the request is authentic before processing. This is crucial for security.Message
field (containing the WhatsApp payload).WhatsappMessageSchema
(Zod).200 OK
for successful processing or appropriate error codes (403
for bad signature,400
for invalid payload,500
for processing errors or failed subscription confirmation to allow retries).3. Building the API Layer
In RedwoodJS, the API function
whatsappWebhook
is the API layer for this integration point.Endpoint: RedwoodJS exposes this function at
/api/whatsappWebhook
. This is the URL you provide to AWS SNS.Authentication/Authorization:
Request Validation:
WhatsappMessageSchema
) validates the structure of the inner WhatsApp payload (snsMessage.Message
). Important: This schema is an example based on common structures. You must verify and potentially adjust it based on the actual payloads you receive from Meta/AWS via SNS, as these can evolve. Test with real messages.API Documentation (SNS Input): The function expects POST requests with a JSON body matching the AWS SNS notification format. The critical field is
Message
, which contains a stringified JSON payload from AWS End User Messaging Social, mirroring Meta's Webhook format.Message
Payload (Parsed WhatsApp Event - for clarity): This is what theJSON.parse(snsMessage.Message)
call produces (structure needs verification):Testing (Simulating SNS): Use
curl
or Postman to send a POST request to your local development server's webhook endpoint (http://localhost:8911/api/whatsappWebhook
by default). You'll need to generate a valid signature or temporarily disable verification for local testing. Tools exist to help craft signed SNS messages if needed. Basiccurl
without a valid signature will be rejected if verification is active.4. Integrating with AWS Services (SNS, End User Messaging, Sending Replies)
This section covers setting up AWS infrastructure and enabling replies.
Create SNS Topic (AWS Console or CLI):
Standard
, Name:WhatsAppIncomingMessages
(or similar). Note the Topic ARN. Add it to your.env
(INCOMING_SNS_TOPIC_ARN
).aws sns create-topic --name WhatsAppIncomingMessages --region YOUR_REGION
(Copy theTopicArn
).Link WABA to AWS End User Messaging Social:
INCOMING_SNS_TOPIC_ARN
)..env
file (WABA_PHONE_NUMBER_ID
).Subscribe RedwoodJS Function to SNS Topic:
https://your-app.com/api/whatsappWebhook
.HTTPS
, Endpoint:https://your-app.com/api/whatsappWebhook
, Disable ""Enable raw message delivery"". Create subscription.aws sns subscribe --topic-arn YOUR_SNS_TOPIC_ARN --protocol https --endpoint https://your-app.com/api/whatsappWebhook --region YOUR_REGION
SubscriptionConfirmation
message. Your deployed function's logic (from Section 2) should handle this programmatically (validating the ARN and callingConfirmSubscriptionCommand
). Monitor logs to ensure confirmation succeeds. The subscription status in AWS changes from ""Pending confirmation"" to ""Confirmed"".Implement Sending Replies: Update the
whatsappWebhook.ts
function (or create a helper file likewhatsappWebhook.lib.ts
) to include the reply logic.Key Changes & Considerations:
sendWhatsAppReply
using the client.SendWhatsappMessageCommandInput
structure (params
) must be verified against official AWS SDK documentation. The provided code is a placeholder guess.sendWhatsAppReply
into the main handler'sNotification
block (shown commented out for integration).5. Implementing Error Handling, Logging, and Retry Mechanisms
try...catch
blocks extensively.403 Forbidden
. No retry needed.400 Bad Request
. The message structure is wrong; retrying won't help.500 Internal Server Error
. Fix config and potentially use DLQ for failed messages.sendWhatsAppReply
): Catch errors. Log details. Return500 Internal Server Error
to signal to SNS that it should retry (could be throttling, temporary network issue).500 Internal Server Error
for potential retries.logger
(import { logger } from 'src/lib/logger'
).logger.info({ key: value }, 'Message')
.LOG_LEVEL
per environment.5xx
errors or timeouts. Customize the retry policy (attempts, backoff) in the SNS subscription settings if needed.setTimeout
) to ensure correct error code responses and DLQ behavior.6. Creating a Database Schema and Data Layer (Optional)
Use Prisma to store message history or related data.
Define Schema: Edit
api/db/schema.prisma
.Apply Schema Changes: Run Prisma Migrate to update your database schema and generate the Prisma Client.
Use Prisma Client in API Function: Modify
api/src/functions/whatsappWebhook.ts
to save incoming messages.Key Changes:
db
fromsrc/lib/db
.try...catch
block arounddb.whatsappMessage.create
to save the incoming message details.Date
object.Remember to configure your
DATABASE_URL
environment variable in.env
for Prisma to connect to your database.