Search code examples
nestjstwiliobackend

Twilio webhooks not working when certain event occurs


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 Webhook Url

Event selection on twilio Event selection

Message sent successfully Frontend log

Twilio conversation messages logs Twilio conversation 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.


Solution

  • 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.