Skip to main content

WhatsApp Service Architecture

This document describes the separation of the WhatsApp domain from merchant_core_api into its own internal service.

Goals

  • Separate WhatsApp delivery from merchant business logic.
  • Reduce coupling between OTP/auth and the WhatsApp provider.
  • Provide a clean audit log, retry, and delivery-status webhook.
  • Make swapping WhatsApp providers easy without touching the entire main API.

Service Scope

whatsapp-service is only responsible for the delivery layer:

  • render the message template
  • send the message to the WhatsApp provider
  • record provider request/response
  • receive delivery/read/failed status webhooks
  • retry failed sends

What stays in merchant_core_api:

  • generate OTP
  • validate OTP
  • the rules for when a message must be sent
  • merchant business orchestration

Integration Boundary

Core API to WhatsApp Service

Recommended initial communication:

  • internal HTTP
  • auth via internal API key

Minimum internal endpoints:

  • POST /internal/whatsapp/otp
  • POST /internal/whatsapp/messages
  • GET /internal/whatsapp/messages/{id}
  • GET /health

Provider to WhatsApp Service

The provider webhook only enters the whatsapp-service, not merchant_core_api.

Example endpoint:

  • POST /webhooks/whatsapp/status

OTP Flow

  1. Mobile requests OTP from merchant_core_api
  2. Core API generates the OTP challenge
  3. Core API calls POST /internal/whatsapp/otp
  4. WhatsApp service persists the request to notification.whatsapp_messages
  5. WhatsApp service renders the OTP template
  6. WhatsApp service sends to the provider
  7. WhatsApp service stores the attempt result in notification.whatsapp_send_attempts
  8. The provider callback delivery status reaches whatsapp-service
  9. Status and delivery events can be re-read from GET /internal/whatsapp/messages/{id}

Business Notification Flow

  1. A business event happens in the core API
  2. Core API calls POST /internal/whatsapp/messages
  3. WhatsApp service persists the request to notification.whatsapp_messages
  4. WhatsApp service sends to the provider
  5. The send status is recorded in notification.whatsapp_send_attempts
  6. If needed, the core API can query the message status via the internal endpoint

Database

Schemas in use:

  • notification.whatsapp_provider_configs
  • notification.whatsapp_templates
  • notification.whatsapp_messages
  • notification.whatsapp_send_attempts
  • notification.whatsapp_delivery_events

Important notes:

  • the notification schema does not replace the existing OTP runtime tables
  • OTP tables like challenge/cooldown/rate limit stay in the auth/runtime domain
  • the notification schema only holds the WhatsApp delivery log, templates, provider config, and delivery events

See migration:

  • merchant_database/db_kesles_merchant/migrations/032_create_notification_whatsapp_tables.sql

Initial Technical Decisions

  • the database stays shared PostgreSQL for now
  • the schema is split into notification
  • internal transport uses HTTP
  • retry can still be synchronous/manual at first, queues come later

Evolution Phases

Phase 1

  • separate service
  • internal HTTP
  • synchronous send

Phase 2

  • queue for high-volume notifications
  • retry worker
  • rate limit per recipient/provider

Phase 3

  • provider failover
  • template approval workflow
  • dedicated delivery monitoring dashboard