WhatsApp module

WhatsApp messages

Evolution API integration for sending text via authenticated REST.

Overview

The whatsapp module sends text messages through the Evolution API (/message/sendText/{instance}). It is a thin wrapper: one REST endpoint and a service using fetch.

Key points

  • • Config via EVOLUTION_API_URL / INSTANCE / KEY
  • • POST /whatsapp/send with JWT
  • • Phone number sent as provided
  • • Network/API failures propagate as HTTP 502
  • • WhatsappService exported

Structure

Filesystemsrc/modules/whatsapp
src/modules/whatsapp/
├── whatsapp.module.ts
├── whatsapp.controller.ts
├── whatsapp.service.ts
└── dtos/
    └── send-whatsapp.dto.ts

src/config/whatsapp.config.ts

Evolution API configuration

whatsapp namespace in src/config/whatsapp.config.ts:

Environment.env
EVOLUTION_API_URL=http://localhost:8080
EVOLUTION_API_INSTANCE=default
EVOLUTION_API_KEY=your-api-key

Instance

The instance must exist in Evolution API. The key is sent as the apiKey request header. Missing URL/instance yields HTTP 503.

WhatsappService

Main method:

  • • sendMessage(to, message) — POST ${url}/message/sendText/${instance}
  • • Body: { number: to, text: message }
  • • Headers: Content-Type application/json, apiKey

Error behavior

Network or non-OK Evolution HTTP → BadGatewayException (502). Missing config → ServiceUnavailableException (503). The controller does not return 200 in those cases.

TypeScriptsendMessage
// WhatsappService.sendMessage(to, message)
// number is sent as-is

POST ${EVOLUTION_API_URL}/message/sendText/${EVOLUTION_API_INSTANCE}
Headers: { "Content-Type": "application/json", "apiKey": "..." }
Body: { "number": to, "text": message }

REST API

JWT required. No @Roles — any authenticated user.

DTO

  • • to — digit-only string (@Matches /^\d+$/); sent as-is
  • • message — non-empty string

Send message

to: digits only, in the format Evolution expects (include DDI yourself if needed, e.g. 5511999999999). message: text.

HTTP RequestPOST
POST /api/v1/whatsapp/send
Content-Type: application/json
Authorization: Bearer <access_token>

{
  "to": "5511999999999",
  "message": "Hello, this is a test message"
}

Success response

HTTP Response200
{
  "message": "WhatsApp message sent successfully"
}

Error responses

  • • 401 — missing or invalid JWT
  • • 502 — Evolution unreachable or returned an error
  • • 503 — EVOLUTION_API_URL / INSTANCE not configured

Use in another module

Import WhatsappModule and inject WhatsappService.

TypeScriptFeature module
@Module({
  imports: [WhatsappModule],
  providers: [MyService],
})
export class MyModule {}

@Injectable()
export class MyService {
  constructor(private readonly whatsappService: WhatsappService) {}

  async notify(phone: string, text: string) {
    await this.whatsappService.sendMessage(phone, text);
  }
}

Notes

Number format

The service does not add a DDI. Send to already in the format Evolution API expects (e.g. 5511999999999 for Brazil).

API errors

Network/HTTP failures from Evolution surface as 502. Success only after response.ok.

Explore