I have a backend on NestJs. Basically I am implementing Twilio conversation api for making real-time chat application. I have setup Twilio webhook url for post request as soon as message is added in the chat it should raise onMessageAdded event and hit the webhook url. Also I have used ngrok for forwarding. But issue is message is sending successfully but onMessageAdded is not hitting my backend url. Currently I am in dev environment.
Following is the code for reference.
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.enableCors();
const twilioChatService = app.get(TwilioChatService);
await twilioChatService.setupConversationsWebhook(ENV['TWILIO_CHAT_SID'], 'https://lab-amazing-seahorse.ngrok-free.app/');
app.useGlobalPipes(new ValidationPipe());
app.useGlobalPipes(
new ValidationPipe({
whitelist: true,
}),
);
const document = SwaggerModule.createDocument(app, config);
SwaggerModule.setup('api', app, document);
app.useGlobalPipes(new ValidationPipe());
app.useGlobalInterceptors(new ClassSerializerInterceptor(app.get(Reflector)));
await app.listen(ENV['PORT'], () =>
console.log(`Server is running on port ${ENV['PORT']}`),
);
}
bootstrap();
// TwilioChatService
private readonly twilioClient: Twilio;
constructor() {
this.twilioClient = new Twilio(process.env.TWILIO_ACCOUNT_SID, process.env.TWILIO_AUTH_TOKEN);
}
async setupConversationsWebhook(conversationSid: string, webhookUrl: string) {
try {
this.twilioClient.conversations.v1.conversations(conversationSid).webhooks(ENV['TWILIO_WEBHOOK_SID']).update({
'configuration.method': 'POST',
'configuration.filters': ['onMessageAdded'],
'configuration.url': webhookUrl,
}).then(webhook => console.log(webhook.sid));
console.log(`Conversations webhook set up at ${webhookUrl}`);
} catch (error) {
console.error('Error setting up Conversations webhook:', error.message);
}
}
// chat.controller.ts
import { Controller, Post, Body, Req, Get, Param } from '@nestjs/common';
import { ChatService } from './chat.service';
@Controller('chat')
export class ChatController {
constructor(private readonly chatService: ChatService) { }
@Post('webhook')
async handleWebhook(@Body() eventData: any): Promise<any> {
console.log(" === handleWebhook called ===");
console.log("Received webhook event:", eventData);
await this.chatService.handleWebhookEvent(eventData);
}
}
// chat.service.ts
async handleWebhookEvent(eventData: any): Promise<void> {
const eventType = eventData.EventType;
if (eventType === 'onMessageAdded') {
console.log("Called onMessageSent()");
const conversationSid = eventData.ConversationSid;
const messageSid = eventData.MessageSid;
// Send HTTP request when a new message is sent
console.log("=== GOT the Message ===", messageSid);
this.sendMessage(conversationSid, eventData.SenderIdentity, eventData.Body);
}
}
// chat.module.ts
@Module({
imports: [TwilioModule.forRoot({ accountSid: process.env.TWILIO_ACCOUNT_SID, authToken: process.env.TWILIO_AUTH_TOKEN })],
controllers: [ChatController],
providers: [TwilioChatService, ChatService],
})
export class ChatModule { }
Twilio webhook url and request method
Event selection on twilio
Message sent successfully
Twilio conversation messages logs
Ngrok Logs Ngrok logs
I have added all the configurations which are necessary for Webhook setup but still it is not hitting my backend after message is added to the chat.
The issue was I wasn't passing the specific header to make webhook enable on any event registered on Twilio.
await this.twilioClient.conversations.v1.conversations(conversationSid).messages.create({
"xTwilioWebhookEnabled": "true",
body: body,
author: senderIdentity,
});
This xTwilioWebhookEnabled field should be set to true to enable webhook to hit your backend.