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
| Field | Type | Description |
|---|---|---|
conversationId | string | Conversation ID from the incoming message |
poolNumberId | string | Pool number ID from the incoming message |
toNumber | string | Recipient's WhatsApp number |
text | string | Reply 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_statuswithcode: "SERVICE_WINDOW_EXPIRED" - REST API replies receive HTTP
403withcode: "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}`);
}
}
});