When to Use
- Acknowledgement without noise: A customer support bot reacts to an inbound message with a checkmark emoji to confirm receipt, avoiding a "Message received" reply that adds conversation clutter.
- Bot-to-human signal: A triage workflow reacts with a clock emoji when a case is queued, and a human agent's workflow reacts with a thumbs-up when they pick up the case.
- Sentiment confirmation: After a customer selects "Great" on a satisfaction survey, the workflow reacts to their inbound reply with a heart emoji as a positive closing signal.
- Task completion markers: An internal group notification workflow reacts to a previously sent task assignment message with a checkmark emoji when the task is marked complete in the task management system.
- Re-engagement acknowledgement: When a user replies to a dormant conversation, the bot immediately reacts with an eyes emoji to signal that their message has been seen before a full response is composed.
Configuration
Connection
| Field | Required | Description |
accessToken | Required | Permanent System User access token. Store in BizFirst Credentials Manager. |
phoneNumberId | Required | Numeric string ID of the sending WhatsApp Business phone number. |
apiVersion | Optional | Meta Graph API version. Defaults to v18.0. |
Operation
| Field | Required | Description |
to | Required | Phone number of the conversation participant (the sender of the message being reacted to), with country code, no + prefix. |
messageId | Required | The WhatsApp message ID (wamid) of the specific message to react to. This is the messageId from the send result of a previous operation, or the id from an inbound webhook event. |
emoji | Required | A single Unicode emoji character (e.g. ✅ for checkmark, 👍 for thumbs up, ❤ for heart). Only standard Unicode emoji are supported — custom stickers cannot be used as reactions. To remove a reaction, pass an empty string "". |
Removing a reaction: To remove an existing reaction from a message, send this operation again with the same messageId and an empty string for emoji. This clears any reaction the business account has placed on that message.
Sample Configuration
{
"resource": "message",
"operation": "sendReaction",
"accessToken": "{{ $credentials.whatsAppToken }}",
"phoneNumberId": "123456789012345",
"to": "{{ $input.customerPhone }}",
"messageId": "{{ $input.inboundMessageId }}",
"emoji": "✅"
}
Validation Errors
| Error | Cause |
accessToken is required | The accessToken field is empty. |
phoneNumberId is required | The phoneNumberId field is empty. |
to is required | The to field is empty. |
messageId is required | The messageId field is empty. |
emoji is required | The emoji field is empty (use "" explicitly to remove a reaction). |
131026 (Meta) | The target message ID is invalid or does not belong to this conversation. |
131047 (Meta) | 24-hour customer service window has expired — reactions are also subject to the conversation window. |
Output
Success Port
| Field | Type | Description |
messageId | string | The wamid of the reaction message itself (not the message being reacted to). |
phoneNumberId | string | The sending phone number ID. |
to | string | The conversation participant's phone number. |
status | string | "sent" on success. |
errorCode | string | Empty on success. |
errorMessage | string | Empty on success. |
rawResponse | string | Full raw JSON from the Meta API. |
Error Port
| Field | Type | Description |
status | string | "failed" or "error". |
errorCode | string | Meta error code or BizFirst validation code. |
errorMessage | string | Human-readable error description. |
rawResponse | string | Raw API error response. |
Sample Output
{
"messageId": "wamid.HBgLMTQxNTU1NTI2NzEVAgARGBIyQzM4NjhGQTExMjQ3RDMAA",
"phoneNumberId": "123456789012345",
"to": "14155552671",
"status": "sent",
"errorCode": null,
"errorMessage": null,
"rawResponse": "{\"messaging_product\":\"whatsapp\",\"contacts\":[{\"input\":\"14155552671\",\"wa_id\":\"14155552671\"}],\"messages\":[{\"id\":\"wamid.HBgLMTQxNTU1NTI2NzEVAgARGBIyQzM4NjhGQTExMjQ3RDMAA\"}]}"
}
Expression Reference
| Value | Expression | Notes |
| Reaction message ID | {{ $output.sendReaction.messageId }} | ID of the reaction itself, not the message reacted to. Rarely needed downstream. |
| Recipient | {{ $output.sendReaction.to }} | For delivery audit logging. |
| Status | {{ $output.sendReaction.status }} | Branch on "sent" vs "failed" if reaction confirmation is business-critical. |
Node Policies & GuardRails
| Policy Area | Recommendation |
| Credential storage | Store the access token in BizFirst Credentials Manager. Never inline in configuration. |
| Message ID source | The messageId must be a valid wamid. For inbound messages, extract it from the webhook payload (entry[0].changes[0].value.messages[0].id). For sent messages, use the messageId from the previous send operation's success port output. |
| Emoji encoding | Use the Unicode code point (e.g. ✅) or the literal emoji character. Avoid emoji shortcodes (e.g. :check:) — WhatsApp does not expand them. |
| One reaction per message | The business account can place only one reaction per message. Sending a new reaction replaces the previous one. Use empty string to remove. |
| 24-hour window | Reactions are subject to the 24-hour customer service window. Reacting to old messages from outside the window will fail with 131047. |
| Error port | Connect the error port. Reactions are a low-criticality operation — route errors to a logging node rather than a customer-facing error flow. |
Examples
Instant Acknowledgement on Inbound Message
{
"resource": "message",
"operation": "sendReaction",
"accessToken": "{{ $credentials.whatsAppToken }}",
"phoneNumberId": "123456789012345",
"to": "{{ $input.customerPhone }}",
"messageId": "{{ $input.inboundMessageId }}",
"emoji": "ὄ0"
}
A WebhookTrigger receives an inbound WhatsApp message. Immediately before the triage logic runs, this node reacts with eyes emoji to signal that the message was seen. The customer sees a near-instant acknowledgement even if the full response takes a few seconds to generate.
Task Completion Checkmark
{
"resource": "message",
"operation": "sendReaction",
"accessToken": "{{ $credentials.whatsAppToken }}",
"phoneNumberId": "123456789012345",
"to": "{{ $input.teamMemberPhone }}",
"messageId": "{{ $output.sendTaskMsg.messageId }}",
"emoji": "✅"
}
A task management webhook fires when a task is marked complete. The workflow retrieves the wamid of the original task assignment message (stored in the task record when first sent), then reacts with a checkmark to visually close the loop in the WhatsApp conversation without sending a separate reply.