Messaging Service

Mushu Messaging is a channel-agnostic two-way messaging service. Send outbound messages and receive inbound replies through pluggable channels — Twilio SMS and Twilio WhatsApp ship today, with the same canonical request/response shape across channels.

Each channel handles its own signature verification, webhook parsing, and provider API calls. Your app talks to a single /send and a single webhook handler regardless of whether the message went over SMS or WhatsApp.

Endpoints Overview

MethodEndpointAuthDescription
POST/sendAPI KeySend an outbound message via the given channel
POST/webhook/{channel_id}SignatureReceive inbound messages from the provider
POST/status/{channel_id}SignatureReceive delivery-status callbacks from the provider
GET/healthNoneService health + registered channels

Channels

Channel IDProviderIdentifier format
twilio_smsTwilio (toll-free SMS)E.164 phone, e.g. +14155551234
twilio_whatsapp_sandboxTwilio WhatsApp Sandboxwhatsapp:+14155551234

Channels are configured at deploy time via env + Secrets Manager. A channel is only registered if its credentials are present; missing credentials produce a clear startup log and the channel is simply unavailable for /send.


Sending Messages

POST /send
X-API-Key: ms_your_key

{
  "channel_id": "twilio_sms",
  "to_identifier": "+14155551234",
  "body": "Hi! Here's your meal summary: https://womojifood.app/m/abc",
  "media_url": null
}

Response:

{
  "outbound_sid": "SM1234567890abcdef...",
  "status": "queued",
  "channel_id": "twilio_sms"
}

The returned outbound_sid is the provider's message ID. Use it to correlate later status-callback events.

Send status values

StatusMeaning
queuedProvider accepted the message
sentHanded off to the carrier
deliveredConfirmed delivered to handset
undeliveredCarrier rejected the message
failedProvider rejected the message

Receiving Inbound Messages

Configure your provider to POST inbound messages to https://messaging.mushucorp.com/webhook/{channel_id}. The service verifies the provider's signature (Twilio HMAC), parses the channel-specific payload into a canonical InboundMessage, logs it, and returns 200.

The canonical inbound shape:

{
  "channel_id": "twilio_sms",
  "from_identifier": "+14155551234",
  "to_identifier": "+18447291483",
  "body": "I just ate a burrito",
  "media_urls": [],
  "inbound_sid": "SM..."
}

Signature mismatches produce 403. Unknown channel IDs produce 404. Providers retry on non-2xx — return 200 even when you decide to drop a message.


Delivery Status Callbacks

Configure your provider to POST status updates to https://messaging.mushucorp.com/status/{channel_id}. Each callback updates the stored outbound row's status and error fields in place, so the full lifecycle (queuedsentdelivered or failed) is visible in logs.

Signed with the same HMAC secret as the inbound webhook.


Twilio SMS Setup

  1. Buy or verify a toll-free number in Twilio Console.
  2. Submit the number for Toll-Free Verification (TFV). Without TFV, US carriers hard-block messages with error 30032.
  3. In the number's Messaging Config, set the webhook URL to https://messaging.mushucorp.com/webhook/twilio_sms and status callback URL to https://messaging.mushucorp.com/status/twilio_sms.
  4. Store your Account SID and Auth Token in AWS Secrets Manager under mushu-messaging/twilio.

Twilio WhatsApp Sandbox Setup

Good for dev loops while TFV is pending. Each participant texts join <code> to the sandbox number; inbound messages then flow through the same pipeline.

  1. Activate the WhatsApp Sandbox in Twilio Console.
  2. Set the inbound webhook to https://messaging.mushucorp.com/webhook/twilio_whatsapp_sandbox.
  3. Set the status callback to https://messaging.mushucorp.com/status/twilio_whatsapp_sandbox.
  4. Send join <code> from every test device.

Health Check

GET /health

{
  "status": "ok",
  "channels": ["twilio_sms", "twilio_whatsapp_sandbox"]
}

The channels field is the list of channel IDs whose credentials were found at startup. Useful for confirming an env-specific deploy picked up the right secrets.


API Reference

Interactive docs: messaging.mushucorp.com/docs