Documentation Index Fetch the complete documentation index at: https://www.docs.wazap.dev/llms.txt
Use this file to discover all available pages before exploring further.
Overview
Message reactions allow you to respond to any message with an emoji, providing a quick and expressive way to acknowledge, appreciate, or react to content without sending a full message. This feature enhances user engagement and reduces message clutter.
Key Features
Emoji Reactions : React with any emoji to any message
Predefined Constants : 14 commonly used emoji reactions
Convenience Methods : Dedicated methods for popular reactions
Remove Reactions : Ability to remove reactions from messages
Universal Support : React to any message type (text, media, interactive, etc.)
How Reactions Work
When you send a reaction, it appears as a small emoji overlay on the original message, similar to social media platforms. Users can see who reacted and with which emoji.
Visual Example:
[Original Message]
📸 Here's the photo from our meeting
[With Reaction]
📸 Here's the photo from our meeting 👍 ❤️ 🔥
↳ You reacted with 👍
Reaction Interface
export interface ReactionMessage extends BaseMessage {
type : WhatsAppMessageType . REACTION ;
reaction : {
message_id : string ; // ID of message to react to
emoji : string ; // Emoji to use as reaction
};
}
export interface ReactionResponse {
success : boolean ;
messageId ?: string ;
error ?: string ;
}
Available Emojis
Predefined Emoji Constants
export const REACTION_EMOJIS = {
LIKE: '👍' ,
LOVE: '❤️' ,
LAUGH: '😂' ,
WOW: '😮' ,
SAD: '😢' ,
ANGRY: '😠' ,
THUMBS_UP: '👍' ,
THUMBS_DOWN: '👎' ,
HEART: '❤️' ,
HEART_EYES: '😍' ,
FIRE: '🔥' ,
CLAP: '👏' ,
CHECK: '✅' ,
CROSS: '❌'
} as const ;
export type ReactionEmoji = typeof REACTION_EMOJIS [ keyof typeof REACTION_EMOJIS ] | string ;
Reaction Methods
Primary Reaction Method
// Send any emoji reaction
async sendReaction ( to : string , messageId : string , emoji : ReactionEmoji ): Promise < ReactionResponse >
// Remove a reaction
async removeReaction ( to : string , messageId : string ): Promise < ReactionResponse >
Convenience Methods
// Common reactions
async reactWithLike ( to : string , messageId : string ): Promise < ReactionResponse >
async reactWithLove ( to : string , messageId : string ): Promise < ReactionResponse >
async reactWithLaugh ( to : string , messageId : string ): Promise < ReactionResponse >
async reactWithWow ( to : string , messageId : string ): Promise < ReactionResponse >
async reactWithSad ( to : string , messageId : string ): Promise < ReactionResponse >
async reactWithAngry ( to : string , messageId : string ): Promise < ReactionResponse >
// Gesture reactions
async reactWithThumbsUp ( to : string , messageId : string ): Promise < ReactionResponse >
async reactWithThumbsDown ( to : string , messageId : string ): Promise < ReactionResponse >
async reactWithClap ( to : string , messageId : string ): Promise < ReactionResponse >
// Emotion reactions
async reactWithHeart ( to : string , messageId : string ): Promise < ReactionResponse >
async reactWithHeartEyes ( to : string , messageId : string ): Promise < ReactionResponse >
async reactWithFire ( to : string , messageId : string ): Promise < ReactionResponse >
// Status reactions
async reactWithCheck ( to : string , messageId : string ): Promise < ReactionResponse >
async reactWithCross ( to : string , messageId : string ): Promise < ReactionResponse >
Usage Examples
Basic Reactions
import { WhatsAppClient , REACTION_EMOJIS } from 'whatsapp-client-sdk' ;
const client = new WhatsAppClient ( accessToken , phoneNumberId );
// React with a thumbs up
await client . reactWithLike ( '+1234567890' , messageId );
// React with a custom emoji
await client . sendReaction ( '+1234567890' , messageId , '🎉' );
// React using predefined constants
await client . sendReaction ( '+1234567890' , messageId , REACTION_EMOJIS . FIRE );
// Remove a reaction
await client . removeReaction ( '+1234567890' , messageId );
Convenience Method Examples
// Positive reactions
await client . reactWithLike ( userPhone , messageId ); // 👍
await client . reactWithLove ( userPhone , messageId ); // ❤️
await client . reactWithFire ( userPhone , messageId ); // 🔥
await client . reactWithClap ( userPhone , messageId ); // 👏
await client . reactWithCheck ( userPhone , messageId ); // ✅
// Emotional reactions
await client . reactWithLaugh ( userPhone , messageId ); // 😂
await client . reactWithWow ( userPhone , messageId ); // 😮
await client . reactWithHeartEyes ( userPhone , messageId ); // 😍
// Negative reactions
await client . reactWithSad ( userPhone , messageId ); // 😢
await client . reactWithAngry ( userPhone , messageId ); // 😠
await client . reactWithThumbsDown ( userPhone , messageId ); // 👎
await client . reactWithCross ( userPhone , messageId ); // ❌
Webhook Integration
Automatic reactions based on message content:
const webhookProcessor = client . createWebhookProcessor ({
onTextMessage : async ( message ) => {
const text = message . text . toLowerCase ();
// Auto-react to positive messages
if ( text . includes ( 'awesome' ) || text . includes ( 'amazing' )) {
await client . reactWithFire ( message . from , message . id );
}
// React to gratitude
else if ( text . includes ( 'thank' ) || text . includes ( 'gracias' )) {
await client . reactWithHeart ( message . from , message . id );
}
// React to questions
else if ( text . includes ( '?' )) {
await client . reactWithWow ( message . from , message . id );
}
// Default positive reaction
else {
await client . reactWithLike ( message . from , message . id );
}
},
onImageMessage : async ( message ) => {
// React to images with heart eyes
await client . reactWithHeartEyes ( message . from , message . id );
},
onVideoMessage : async ( message ) => {
// React to videos with fire
await client . reactWithFire ( message . from , message . id );
},
onAudioMessage : async ( message ) => {
// React to audio with thumbs up
await client . reactWithThumbsUp ( message . from , message . id );
}
});
Advanced Use Cases
Smart Customer Service Reactions
class SmartReactionBot {
async processCustomerMessage ( message ) {
const content = message . text ?. toLowerCase () || '' ;
// Categorize and react accordingly
if ( this . isComplaint ( content )) {
await client . reactWithSad ( message . from , message . id );
await this . escalateToSupport ( message );
}
else if ( this . isCompliment ( content )) {
await client . reactWithHeartEyes ( message . from , message . id );
await this . thankCustomer ( message );
}
else if ( this . isUrgent ( content )) {
await client . reactWithWow ( message . from , message . id );
await this . prioritizeMessage ( message );
}
else if ( this . isOrder ( content )) {
await client . reactWithCheck ( message . from , message . id );
await this . processOrder ( message );
}
}
isComplaint ( text ) {
return text . includes ( 'problem' ) || text . includes ( 'issue' ) || text . includes ( 'wrong' );
}
isCompliment ( text ) {
return text . includes ( 'great' ) || text . includes ( 'excellent' ) || text . includes ( 'perfect' );
}
isUrgent ( text ) {
return text . includes ( 'urgent' ) || text . includes ( 'asap' ) || text . includes ( 'emergency' );
}
isOrder ( text ) {
return text . includes ( 'order' ) || text . includes ( 'buy' ) || text . includes ( 'purchase' );
}
}
Reaction-Based Feedback System
class FeedbackCollector {
async sendFeedbackRequest ( userPhone ) {
const response = await client . sendText (
userPhone ,
'How was your experience with our service today?'
);
// Store message ID for reaction tracking
this . pendingFeedback . set ( response . messages [ 0 ]. id , {
userPhone ,
timestamp: Date . now ()
});
}
async handleReactionWebhook ( reactionData ) {
const { message_id , emoji , from } = reactionData ;
if ( this . pendingFeedback . has ( message_id )) {
const feedback = this . analyzeFeedback ( emoji );
await this . storeFeedback ( from , feedback );
// Thank with appropriate reaction
if ( feedback . rating >= 4 ) {
await client . reactWithLove ( from , message_id );
} else if ( feedback . rating >= 3 ) {
await client . reactWithThumbsUp ( from , message_id );
} else {
await client . reactWithSad ( from , message_id );
}
}
}
analyzeFeedback ( emoji ) {
const feedbackMap = {
'😍' : { rating: 5 , sentiment: 'excellent' },
'❤️' : { rating: 5 , sentiment: 'love' },
'🔥' : { rating: 5 , sentiment: 'amazing' },
'👍' : { rating: 4 , sentiment: 'good' },
'👏' : { rating: 4 , sentiment: 'satisfied' },
'😊' : { rating: 3 , sentiment: 'okay' },
'😐' : { rating: 2 , sentiment: 'neutral' },
'👎' : { rating: 1 , sentiment: 'poor' },
'😢' : { rating: 1 , sentiment: 'disappointed' },
'😠' : { rating: 1 , sentiment: 'angry' }
};
return feedbackMap [ emoji ] || { rating: 3 , sentiment: 'unknown' };
}
}
Multi-Reaction Conversation Flow
async function handleOrderProcess ( message ) {
const orderId = extractOrderId ( message . text );
if ( orderId ) {
// Acknowledge order inquiry
await client . reactWithCheck ( message . from , message . id );
// Send order status
const orderStatus = await getOrderStatus ( orderId );
const statusMessage = await client . sendText (
message . from ,
`Order # ${ orderId } status: ${ orderStatus . status } `
);
// React based on status
switch ( orderStatus . status ) {
case 'delivered' :
await client . reactWithCheck ( message . from , statusMessage . messages [ 0 ]. id );
break ;
case 'shipped' :
await client . reactWithFire ( message . from , statusMessage . messages [ 0 ]. id );
break ;
case 'processing' :
await client . reactWithThumbsUp ( message . from , statusMessage . messages [ 0 ]. id );
break ;
case 'cancelled' :
await client . reactWithSad ( message . from , statusMessage . messages [ 0 ]. id );
break ;
}
}
}
Custom Emoji Reactions
Beyond the predefined constants, you can use any emoji:
// Custom emojis
await client . sendReaction ( userPhone , messageId , '🎉' ); // Party
await client . sendReaction ( userPhone , messageId , '🌟' ); // Star
await client . sendReaction ( userPhone , messageId , '💯' ); // 100
await client . sendReaction ( userPhone , messageId , '🚀' ); // Rocket
await client . sendReaction ( userPhone , messageId , '☕' ); // Coffee
await client . sendReaction ( userPhone , messageId , '🎵' ); // Music
await client . sendReaction ( userPhone , messageId , '📝' ); // Note
await client . sendReaction ( userPhone , messageId , '💡' ); // Idea
// Seasonal reactions
await client . sendReaction ( userPhone , messageId , '🎄' ); // Christmas
await client . sendReaction ( userPhone , messageId , '🎃' ); // Halloween
await client . sendReaction ( userPhone , messageId , '💝' ); // Gift
await client . sendReaction ( userPhone , messageId , '🌺' ); // Flower
Message Structure
A reaction message has this structure:
{
messaging_product : 'whatsapp' ,
recipient_type : 'individual' ,
to : '+1234567890' ,
type : 'reaction' ,
reaction : {
message_id : 'wamid.HBgLMTY1MDM4Nzk0MzkVAgARGBJDQjZCMzlEQUE4OTJCMTE4RTUA' ,
emoji : '👍'
}
}
To remove a reaction:
{
messaging_product : 'whatsapp' ,
recipient_type : 'individual' ,
to : '+1234567890' ,
type : 'reaction' ,
reaction : {
message_id : 'wamid.HBgLMTY1MDM4Nzk0MzkVAgARGBJDQjZCMzlEQUE4OTJCMTE4RTUA' ,
emoji : '' // Empty string removes the reaction
}
}
Best Practices
1. Appropriate Reaction Selection
// ✅ Good: Match reaction to content
await client . reactWithFire ( userPhone , messageId ); // For exciting content
await client . reactWithHeart ( userPhone , messageId ); // For appreciation
await client . reactWithCheck ( userPhone , messageId ); // For confirmations
await client . reactWithThumbsUp ( userPhone , messageId ); // For approval
// ❌ Avoid: Inappropriate reactions
// Don't use sad face for positive content
// Don't overuse fire emoji for everything
2. Reaction Timing
// ✅ Good: React promptly to user messages
webhookProcessor . onTextMessage = async ( message ) => {
// Quick acknowledgment reaction
await client . reactWithLike ( message . from , message . id );
// Then process and respond
const response = await processMessage ( message );
await client . sendText ( message . from , response );
};
// ❌ Avoid: Delayed reactions without context
// Don't react to messages hours later without explanation
3. Reaction Combinations
// ✅ Good: Use reactions + messages for rich communication
async function acknowledgeOrder ( message , orderDetails ) {
// React to acknowledge receipt
await client . reactWithCheck ( message . from , message . id );
// Follow with detailed response
await client . sendText (
message . from ,
`Order confirmed! 🎉 \n\n Order # ${ orderDetails . id } \n Total: $ ${ orderDetails . total } \n ETA: ${ orderDetails . eta } `
);
}
4. Error Handling
async function safeReaction ( userPhone , messageId , emoji ) {
try {
const response = await client . sendReaction ( userPhone , messageId , emoji );
if ( ! response . success ) {
console . log ( 'Reaction failed:' , response . error );
// Optionally try alternative reaction
await client . reactWithThumbsUp ( userPhone , messageId );
}
} catch ( error ) {
console . error ( 'Reaction error:' , error );
// Don't let reaction failures break the flow
}
}
Limitations
One Reaction per User : You can only have one active reaction per message
Message Age : Can only react to messages within the last 30 days
Emoji Support : Limited to standard Unicode emojis
Rate Limits : Reactions count toward your messaging rate limits
Remove Only Own : You can only remove your own reactions
Migration Guide
Adding Reactions to Existing Workflows
// Before: Simple acknowledgment
webhookProcessor . onTextMessage = async ( message ) => {
await client . sendText ( message . from , 'Message received' );
};
// After: Reaction + response
webhookProcessor . onTextMessage = async ( message ) => {
// Quick reaction for immediate feedback
await client . reactWithThumbsUp ( message . from , message . id );
// Optional follow-up message if needed
if ( requiresResponse ( message )) {
await client . sendText ( message . from , 'Thanks! I \' ll get back to you shortly.' );
}
};
Reaction Analytics
Track reaction patterns for insights:
class ReactionAnalytics {
constructor () {
this . reactionStats = new Map ();
}
async trackReaction ( userPhone , messageId , emoji ) {
await client . sendReaction ( userPhone , messageId , emoji );
// Track for analytics
const key = ` ${ userPhone } : ${ emoji } ` ;
const count = this . reactionStats . get ( key ) || 0 ;
this . reactionStats . set ( key , count + 1 );
}
getTopReactions () {
return Array . from ( this . reactionStats . entries ())
. sort (([, a ], [, b ]) => b - a )
. slice ( 0 , 10 );
}
getUserPreferences ( userPhone ) {
const userReactions = Array . from ( this . reactionStats . entries ())
. filter (([ key ]) => key . startsWith ( userPhone ))
. map (([ key , count ]) => [ key . split ( ':' )[ 1 ], count ]);
return userReactions . sort (([, a ], [, b ]) => b - a );
}
}
Next Steps
Contextual Replies Learn about replying to specific messages
Interactive Messages Create engaging buttons and lists
Typing Indicators Show when you’re typing or mark messages as read
Webhook System Set up automated reaction responses