Pipes.bot

Sending Replies

Reply to WhatsApp messages through the WebSocket connection and REST API.

You can send replies through the WebSocket connection (text only) or the REST API (text and media).

Replying via WebSocket

Send a whatsapp_reply message through the open connection:

{
  "type": "whatsapp_reply",
  "data": {
    "conversationId": "conv_xyz789",
    "poolNumberId": "pool_123",
    "toNumber": "+15559876543",
    "text": "Thanks for reaching out!"
  }
}

Reply fields

FieldTypeDescription
conversationIdstringConversation ID from the incoming message
poolNumberIdstringPool number ID from the incoming message
toNumberstringRecipient's WhatsApp number
textstringReply text (max 4096 characters)

Reply confirmation

After sending a reply, the server responds with a reply_status event:

Success:

{
  "type": "reply_status",
  "data": {
    "conversationId": "conv_xyz789",
    "success": true,
    "messageId": "wamid.abc123..."
  }
}

Failure:

{
  "type": "reply_status",
  "data": {
    "conversationId": "conv_xyz789",
    "success": false,
    "error": "Service window expired — last inbound message is older than 24 hours.",
    "code": "SERVICE_WINDOW_EXPIRED"
  }
}

Reply scoping

Reply behavior depends on your connection scope:

  • User-scoped connections can reply to any conversation you own
  • Conversation-scoped connections can only reply to the conversation they are scoped to — replies targeting a different conversationId are rejected

Replying via REST API

For text and media replies, use the Messages API:

POST /v1/messages/send
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
{
  "conversationId": "conv_xyz789",
  "text": "Here's the info you requested"
}

The REST API is not affected by connection scoping — you can send to any conversation you own regardless of your WebSocket connections.

See Media Handling for sending images, audio, video, and documents.

24-hour service window

WhatsApp enforces a 24-hour messaging window. You can only send outbound messages within 24 hours of the customer's last inbound message. After the window expires:

  • WebSocket replies receive a reply_status with code: "SERVICE_WINDOW_EXPIRED"
  • REST API replies receive HTTP 403 with code: "SERVICE_WINDOW_EXPIRED"

The window resets each time the customer sends a new message.

Conversation ownership

Replies are validated against conversation ownership. You can only reply to conversations that belong to your account. Attempting to reply to another tenant's conversation is silently rejected.

Example: echo bot

ws.on("message", (raw) => {
  const event = JSON.parse(raw.toString());

  if (event.type === "whatsapp_message") {
    const msg = event.data;

    // Echo text messages back
    if (msg.type === "text") {
      ws.send(JSON.stringify({
        type: "whatsapp_reply",
        data: {
          conversationId: msg.conversationId,
          poolNumberId: msg.poolNumberId,
          toNumber: msg.fromNumber,
          text: `You said: ${msg.body}`,
        },
      }));
    }
  }

  if (event.type === "reply_status") {
    if (!event.data.success) {
      console.error(`Reply failed: ${event.data.error}`);
    }
  }
});

On this page