Frequently Asked Questions
Integrate Sinch WhatsApp with NestJS by setting up a new NestJS project, installing necessary dependencies like `@nestjs/config`, `axios`, and `class-validator`, configuring environment variables for Sinch credentials, and structuring the project into modules for Sinch API interaction, webhook handling, and optional database integration.
The Sinch Conversation API is a unified platform provided by Sinch that allows developers to manage conversations across various channels, including WhatsApp. It simplifies the process of sending and receiving messages, managing contacts, and handling other communication aspects.
NestJS provides a robust and scalable framework for building server-side applications. Its modular architecture, dependency injection, and TypeScript support make it well-suited for complex integrations like WhatsApp messaging through the Sinch API.
MongoDB is optional but recommended if you need to persist message history or other data related to your WhatsApp interactions. Use it when you require data storage and retrieval capabilities beyond the immediate request-response cycle.
Create a Sinch service in your NestJS project to handle API calls. Use `axios` to send HTTP requests to the Sinch API endpoint for sending WhatsApp messages. Ensure you have the recipient's phone number and the message text content.
The webhook secret is a crucial security measure to verify the authenticity of incoming webhook requests from Sinch. It ensures that the requests originated from Sinch and haven't been tampered with.
Secure your webhook endpoint by verifying the signature of incoming requests using the shared webhook secret. Implement a guard or middleware that calculates the signature from the request body and compares it with the signature provided in the `x-sinch-signature` header.
You'll need Node.js, npm or yarn, the NestJS CLI, a Sinch account with Conversation API access, a registered and approved WhatsApp Business Sender, a publicly accessible HTTPS URL for webhooks, and a basic understanding of NestJS concepts.
Your Sinch API token and Service Plan ID are found in your Sinch Customer Dashboard under APIs > API Credentials. Ensure these are kept secure and not exposed in your codebase.
Sinch sends webhook notifications to your specified endpoint for incoming WhatsApp messages. Create a webhook controller in your NestJS app to receive these notifications and process the message data accordingly. Verify the signature of the webhook requests for security.
The `body-parser` middleware, specifically `bodyParser.raw()`, is crucial for accessing the raw request body of incoming webhooks. This raw body is required for webhook signature verification to ensure the message integrity and security.
Your application interacts with your NestJS backend, which communicates with the Sinch platform using the Conversation API. Sinch then sends the messages to WhatsApp users, and incoming messages flow back through webhooks to your NestJS backend.
Docker is optional but recommended for containerizing your NestJS application and Sinch integration for consistent deployment across different environments.
Create DTOs for sending messages (recipient's number, message content) and receiving webhook payloads. These DTOs enhance code clarity and provide validation for incoming data. For webhooks, DTOs should handle various event types via validation and nested properties.
The Sinch webhook signature is verified using a SHA256 HMAC with your webhook secret and a concatenation of the timestamp and raw request body. This is compared to the received signature in the x-sinch-signature header to ensure message integrity.
This guide provides a step-by-step walkthrough for integrating the Sinch Conversation API for WhatsApp messaging into a NestJS application. We'll build a backend service capable of sending WhatsApp messages via Sinch and receiving incoming messages through webhooks.
This implementation enables businesses to leverage NestJS's robust framework for building scalable applications that communicate with customers on the world's most popular messaging platform.
Technologies Used:
System Architecture:
(Note: This ASCII diagram illustrates the flow. For final documentation_ consider generating a visual diagram using tools like MermaidJS or other diagramming software.)
Prerequisites:
npm install -g @nestjs/cli
).1. Project Setup and Configuration
Let's initialize our NestJS project and set up the basic structure and environment configuration.
1.1. Create NestJS Project:
Open your terminal and run:
Choose your preferred package manager (npm or yarn).
1.2. Install Dependencies:
We need modules for HTTP requests_ configuration management_ data validation_ and handling raw request bodies for webhooks. Optionally_ add Mongoose for database interaction.
@nestjs/config
: Manages environment variables.axios
: A promise-based HTTP client for making requests to the Sinch API. (Alternatively_ you can use NestJS's built-inHttpModule
).class-validator
&class-transformer
: Used for validating incoming webhook payloads and API request bodies.body-parser
&@types/body-parser
: Required for accessing the raw request body_ necessary for webhook signature verification.@nestjs/mongoose
&mongoose
: For MongoDB integration (if storing messages).1.3. Environment Variables:
Security best practice dictates storing sensitive credentials outside your codebase. We'll use a
.env
file.Create a
.env
file in the project root:How to Obtain Sinch Credentials:
SINCH_WHATSAPP_SENDER_ID
. This must be the exact, approved number in E.164 format (including+
and country code).SINCH_WEBHOOK_SECRET
(e.g., using a password manager or online generator). You will need to provide this exact same secret to Sinch when configuring the webhook later. Treat this like a password.1.4. Configure Environment Module:
Load the
.env
file into the application using@nestjs/config
.Modify
src/app.module.ts
:1.5. Project Structure:
We'll organize our code into modules for better separation of concerns.
Create these folders (
sinch
,webhook
,config
, etc.) within thesrc
directory.2. Implementing Core Functionality: Sending Messages
Let's create a service to interact with the Sinch Conversation API for sending WhatsApp messages.
2.1. Create Sinch Module and Service:
Generate the module and service using the NestJS CLI:
2.2. Define Sinch Configuration (Optional but Recommended):
Create a typed configuration file for Sinch settings.
Inject this configuration into your
SinchService
.2.3. Implement
SinchService
:This service will contain the logic to call the Sinch API.
2.4. Update
SinchModule
:Register the service and the configuration.
2.5. Import
SinchModule
intoAppModule
:3. Building the API Layer (Example: Sending a Message)
Let's expose an endpoint to trigger sending a message.
3.1. Create DTOs for Sending Messages and Responses:
Define the expected request body structure and validation rules. Also, define a basic DTO for the Sinch API response.
3.2. Create a Controller (e.g., add to
AppController
or create a dedicatedMessageController
):Explanation:
SinchService
is injected.POST /send-whatsapp
is defined.@UsePipes(new ValidationPipe(...))
validates the request body againstSendMessageDto
.forbidNonWhitelisted: true
rejects requests with extra fields.sinchService.sendWhatsAppTextMessage
.202 Accepted
with themessageId
on success.AxiosError
to provide more context from Sinch API failures, and throws appropriateHttpException
instances which NestJS handles.3.3. Testing the Endpoint:
Run your NestJS application:
Use
curl
or Postman. Usingcurl
(note the use of single quotes around the JSON data for shell safety):Expected Response (Success - Status Code 202):
Expected Response (Validation Error - Status Code 400):
Expected Response (Sinch API Error - Status Code e.g., 400, 401, 503):
The response will reflect the
HttpException
thrown in the controller, e.g.:4. Integrating Third-Party Services: Handling Incoming Webhooks
Sinch notifies your application about incoming messages or status updates via webhooks. We need an endpoint to receive and process these notifications securely.
4.1. Configure Webhook in Sinch Dashboard:
https://your-public-domain.com/webhook/sinch
or your ngrok URL likehttps://<your-id>.ngrok.io/webhook/sinch
). This URL MUST use HTTPS..env
file (SINCH_WEBHOOK_SECRET
). This is used for signature verification. Ensure there are no typos or extra spaces.MESSAGE_INBOUND
,MESSAGE_DELIVERY
). Start withMESSAGE_INBOUND
.Screenshot Example (Conceptual - Actual UI may vary):
4.2. Create Webhook Module_ Controller_ and Service:
4.3. Enable Raw Body Parsing (Via Middleware):
Webhook signature verification requires the raw_ unparsed request body. We will apply
body-parser
's raw body middleware specifically to the webhook route. This is configured in theWebhookModule
(see section 4.4).Modify
src/main.ts
to ensure global pipes or other global body parsers don't interfere_ although selective middleware is preferred:4.4. Create Webhook Verification Guard & Configure Middleware:
This guard checks the
x-sinch-signature
header.Middleware Configuration (Important!): Apply the raw body parser middleware in
WebhookModule
.Modify
src/webhook/webhook.module.ts
:Import
WebhookModule
intoAppModule
:4.5. Define DTO for Incoming Webhooks:
Map the structure of Sinch's webhook payloads. This DTO handles multiple event types using the
trigger
field. Note: The original provided DTO was incomplete; this version provides a more structured example forMESSAGE_INBOUND
.