Frequently Asked Questions
Integrate WhatsApp by using Express.js and the Sinch Conversation API. This allows sending and receiving messages and provides a REST endpoint to trigger outgoing messages from your backend systems via Sinch.
The Sinch Conversation API is a unified platform to manage conversations across multiple channels, including WhatsApp. It simplifies interaction with the WhatsApp Business Platform and streamlines communication.
Express.js is used as a framework for building the API and web application in a Node.js environment due to its minimal and flexible nature, making integration with Sinch smoother.
Pre-approved templates are required when initiating conversations with users or messaging outside the 24-hour customer service window. This ensures compliance with WhatsApp Business policies.
Yes, Sinch provides delivery receipts through webhooks. The statuses include, DELIVERED, FAILED, READ, and PENDING, allowing you to track message delivery and handle failures. These statuses can be viewed in the webhook payload from Sinch
Use the 'x-sinch-signature' and 'x-sinch-timestamp' headers along with your Webhook Secret to calculate the expected signature. Compare this with the received signature using a constant-time comparison method like `crypto.timingSafeEqual` for security.
The 24-hour window allows businesses to send free-form messages after a user initiates contact. Outside this window, you must use pre-approved message templates or risk non-delivery.
Set up a webhook endpoint to receive incoming messages from Sinch. The webhook will provide details like contact ID, message content, and timestamp which will be used to trigger actions or replies based on the 24-hour window.
The `sendMessage` function, using helper functions like `sendTextMessage` or `sendTemplateMessage`, handles sending messages. It takes the recipient's phone number and message payload as arguments and makes a POST request to the Sinch API.
The `app_id` is your provisioned WhatsApp Sender ID from Sinch. It identifies your WhatsApp Business number when sending messages through the Sinch API.
You'll need Node.js/npm, a Sinch account with postpay billing, Conversation API access, a Sinch project and app, access keys, a WhatsApp Sender ID, and optionally ngrok for local testing.
The `contact_id` typically represents the sender's WhatsApp phone number. It is used to identify the user who sent the inbound message and is crucial for managing the 24-hour customer service window.
Webhooks require verification of the signature provided by Sinch in request headers. Verify this against your Webhook Secret by calculating the hash locally to ensure the origin of the messages received.
ngrok helps create a secure tunnel between your local development server and the internet, exposing it to receive webhooks for testing purposes before actual deployment.
Production-Ready WhatsApp Integration with Node.js, Express, and Sinch Conversation API
This guide provides a comprehensive walkthrough for integrating WhatsApp messaging capabilities into your Node.js application using Express and the Sinch Conversation API. We'll cover everything from initial setup to deployment, security, and monitoring, enabling you to build a robust, production-grade solution.
Note: This guide uses the current Sinch Conversation API. Some Sinch documentation might still reference older, standalone WhatsApp APIs which are deprecated or scheduled for deprecation. Always refer to the Conversation API documentation for the latest methods.
Project Overview and Goals
What We're Building:
We will build a Node.js Express application that can:
Problem Solved:
This integration enables businesses to leverage the ubiquity of WhatsApp for customer communication, support, notifications, and engagement directly from their backend systems, managed through a unified API (Sinch Conversation API).
Technologies Used:
.env
file.express.raw()
is specifically needed beforeexpress.json()
for the webhook route to correctly verify Sinch signatures which rely on the unmodified raw body.Prerequisites:
Access Key ID
andAccess Secret
generated for your Conversation API App. Store the secret securely; it's only shown once.WhatsApp Sender ID
provided by Sinch after setup (often referred to asSender ID
,WhatsApp Bot
, orclaimed_identity
in the dashboard). This is used as theapp_id
in API calls.1. Setting Up the Project
Let's initialize our Node.js project and install necessary dependencies.
1.1. Create Project Directory:
1.2. Initialize npm Project:
This creates a
package.json
file.1.3. Install Dependencies:
express
: Web framework.dotenv
: Loads environment variables from.env
.axios
: HTTP client to call the Sinch API.crypto
: Built-in Node module for webhook signature verification.express.json()
andexpress.raw()
middleware.body-parser
is not strictly needed unless you require features not covered by the built-ins. Crucially,express.raw()
must be configured for the webhook route beforeexpress.json()
to accessreq.rawBody
for signature verification.1.4. Project Structure:
Create the following directory structure for better organization:
1.5. Create
.gitignore
:Create a
.gitignore
file in the root directory to prevent committing sensitive files and unnecessary directories:1.6. Create
.env
File:Create a
.env
file in the root directory. We will populate this with credentials obtained from Sinch later.Explanation:
dotenv
to manage sensitive credentials and configuration, keeping them out of source code.controllers
,routes
,services
) promote modularity and maintainability, following common Express patterns.axios
is chosen for its simplicity and widespread use for making HTTP requests.crypto
is essential for securing our webhook endpoint.2. Implementing Core Functionality
Now, let's implement the core logic for sending and receiving messages.
2.1. Sending WhatsApp Messages via Sinch (
src/services/sinchService.js
)This service will encapsulate the logic for interacting with the Sinch Conversation API.
Explanation:
generateSinchAuthHeader
): Added explicit notes emphasizing the need to verify thestringToSign
format and secret handling against current Sinch documentation.sendMessage
: Added note clarifying recipient identification options (contact_id
vsidentified_by
). Corrected quotes aroundWHATSAPP
. Enriched error re-throwing. Added basic check for missing env vars.sendTemplateMessage
: Added note about verifying template parameter names. Corrected quotes aroundlatest
anden_US
.SINCH_REGION
variable ensures we hit the correct API endpoint (us
oreu
).2.2. Receiving WhatsApp Messages (Webhook)
We need an endpoint to receive callbacks from Sinch when users send messages to our number or when message events occur.
2.2.1. Webhook Verification Middleware (
src/middleware/verifySinchWebhook.js
)Security is paramount. We must verify that incoming webhook requests genuinely originate from Sinch using the signature provided in the headers.
Explanation:
NaN
and logging details on failure.req.rawBody
: Added more emphasis on the critical need for this and the correct middleware setup order. Returns 500 if missing.stringToSign
format against Sinch docs.split(',')
and a warning, explaining why the first is taken, but advising to check Sinch docs.try...catch
around crypto operations.2.2.2. Webhook Controller (
src/controllers/webhookController.js
)This controller handles the logic after the webhook signature has been verified.
Explanation:
console.debug
for full payload.handleInboundMessage
. Improved error logging in the main handler.media_message
andchoice_response_message
(button/list replies).READ
status. EnhancedFAILED
logging.2.2.3. Webhook Route (
src/routes/webhookRoutes.js
)This defines the
/webhook
endpoint and applies the verification middleware.Explanation:
app.js
.express.json()
afterverifySinchWebhook
in this route definition to ensure the controller getsreq.body
. The raw parser needs to be applied even earlier inapp.js
.3. Building a Complete API Layer
Let's create a simple API endpoint to trigger sending messages.
3.1. Message Controller (
src/controllers/messageController.js
)