Send a reply to a contact

Sends a plain text message to a contact using their default messaging channel (WhatsApp or RCS).

Use Case: Use this endpoint to integrate your own AI, automation, or help desk system with Wax. When you receive an inbound message webhook, process it with your system, then use this endpoint to send a reply back to the customer.

Technical Details:

  • The message is sent via the contact's default_channel (WhatsApp or RCS), which is automatically set based on the channel they last messaged from
  • If the contact has no default channel, WhatsApp is used as fallback
  • Only plain text messages are supported (no images, cards, or interactive elements)
  • The conversation remains in the inbox as unresolved for human agents to monitor
  • The contact_id is included in the inbound message webhook payload for easy reference
  • The response returns message_id, the identifier of the message WAX created for your reply. It uses the same channel:id format as the webhook payloads, so you can match it against messages you receive back (see Conversation mirror webhook below)

Inbound message webhook

When a contact sends a message that is not handled by one of your automations, WAX POSTs it to the webhook URL configured in Settings → Organization → External AI. Each request carries an X-Signature header (HMAC-SHA256 of the raw JSON body, signed with your signing key) plus any custom headers you configured.

{
  "message_id": "wamid.HBgLM...",
  "organization_id": 42,
  "contact_id": 12345,
  "message": {
    "id": "whatsapp:48213",
    "external_message_id": "wamid.HBgLM...",
    "channel": "whatsapp",
    "content": "Where is my order?",
    "timestamp": "2026-07-08T14:03:21.532Z",
    "media_url": "https://cdn.example.com/img.jpg",
    "media_type": "image/jpeg"
  },
  "contact": {
    "name": "John Doe",
    "phone": "+33612345678",
    "email": "[email protected]",
    "tags": ["VIP"],
    "custom_attributes": { "loyalty_tier": "gold" }
  },
  "history": [
    {
      "id": "whatsapp:48201",
      "external_message_id": "wamid.HBgKN...",
      "role": "user",
      "content": "Hi!",
      "timestamp": "2026-07-08T13:58:02.101Z"
    },
    {
      "id": "whatsapp:48204",
      "external_message_id": "wamid.HBgQP...",
      "role": "assistant",
      "content": "Hello John, how can we help?",
      "timestamp": "2026-07-08T13:58:40.870Z"
    }
  ],
  "shopify": {
    "recent_orders": [
      { "order_number": "#1001", "status": "shipped", "items": ["Blue T-Shirt"], "date": "2026-07-06T09:12:00Z" }
    ],
    "active_checkouts": [
      { "items": ["Red Sneakers"], "created_at": "2026-07-07T18:44:00Z" }
    ]
  }
}

Message identity & deduplication:

  • message.id and history[].id are stable, globally unique message identifiers prefixed with the channel (whatsapp:123, rcs:45, sms:67). The same message keeps the same id across deliveries, so you can upsert messages and store them deduplicated.
  • external_message_id is the provider-side identifier (e.g. the WhatsApp wamid); it can be null.
  • timestamp is ISO8601 with millisecond precision; history is sorted chronologically ascending.
  • Deliveries are at-least-once (failed requests are retried), and history overlaps across deliveries by design — always deduplicate on id.

Payload notes:

  • message.media_url / message.media_type are only present for image messages.
  • history contains up to 20 previous text messages (role is user for the contact, assistant for messages sent by WAX or your integration).
  • shopify contains the contact's 5 most recent orders (status: ordered, shipped, delivered or cancelled) and up to 3 active checkouts. It is null unless the organization has an active Shopify connection and the "Include Shopify data" option is enabled on the webhook.

Conversation mirror webhook

Separately from the inbound webhook above, a URL can be configured in Settings → Organization → External helpdesk. Once a conversation needs attention, WAX POSTs every message on it to that URL, one request per message, in both directions: free-text, quick replies, media, the automated messages your flows send, and replies sent through this endpoint. It is a one-way feed, WAX expects no reply to these requests. Signing is identical (X-Signature HMAC-SHA256 of the raw body).

Every call carries a history array (up to the last 20 messages, oldest first, same entry shape as message) so an agent picking the conversation up has the context that was never forwarded while your automations were handling it, and so a dropped delivery is repaired by the next call. event is conversation.opened on the first call (create the ticket) and message.created afterwards (append). Deduplicate on message.id.

{
  "event": "message.created",
  "organization_id": 42,
  "contact_id": 12345,
  "timeline": { "id": 987, "status": "unresolved" },
  "message": {
    "id": "whatsapp:48213",
    "external_message_id": "wamid.HBgLM...",
    "channel": "whatsapp",
    "direction": "inbound",
    "kind": "quick_reply",
    "origin": "customer",
    "content": "Track my order",
    "timestamp": "2026-07-08T14:03:21.532Z"
  },
  "contact": {
    "name": "John Doe",
    "phone": "+33612345678",
    "email": "[email protected]",
    "tags": ["VIP"]
  }
}
  • direction is inbound (from the contact) or outbound (sent by WAX).
  • origin says who produced the message: customer, human (a teammate in the WAX inbox), ai_agent (the WAX AI agent), flow (an automation) or api (sent through this endpoint).
  • media_url is present for image, video, audio and document messages. It is a permanent link WAX re-hosted, so you can fetch it directly with no authentication. Use kind to know what kind of asset to expect. When a media message has a caption, content holds it; otherwise content is a short label such as 📷 Photo.
  • Deduplicating your own replies: a message you send via POST /v1/conversation_replies is mirrored back to you with direction: "outbound" and origin: "api". Its message.id equals the message_id returned by that call, so store the returned id and drop the echo rather than duplicating it in your thread.
  • Reactions, stickers, locations and shared contacts are not mirrored.
Recent Requests
Log in to see full request history
TimeStatusUser Agent
Retrieving recent requests…
LoadingLoading…
Body Params
integer
required

The WAX contact ID (included in the inbound message webhook payload).

string
required

The plain text message to send to the contact. Maximum 4096 characters.

Headers
string
required

Bearer token

Responses

Language
LoadingLoading…
Response
Click Try It! to start a request and see the response here! Or choose an example:
application/json