WhatsApp Integration API Endpoints
This page provides the complete API reference for the WhatsApp Integration API.
OpenAPI Specification
The complete OpenAPI specification for the WhatsApp Integration API is available at openapi.yaml.
Common Messaging Workflows
Basic Text Messaging
// Send simple text message
const textMessage = await fetch('/api/v1/whatsapp/messages/send', {
method: 'POST',
headers: {
'Authorization': `Bearer ${staffToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
guest_phone: '+1234567890',
message_type: 'text',
content: {
text: 'Welcome to Grand Plaza Hotel! How can we assist you today?'
},
conversation_id: 'conv_abc123',
staff_member_id: 'staff_456'
})
});
const { message_id, status } = await textMessage.json();
Template Messaging
// Send welcome template message
const welcomeTemplate = await fetch('/api/v1/whatsapp/templates/send', {
method: 'POST',
headers: {
'Authorization': `Bearer ${staffToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
guest_phone: '+1234567890',
template_name: 'welcome_checkin',
language: 'en',
parameters: {
guest_name: 'John Smith',
hotel_name: 'Grand Plaza Hotel',
room_number: '205',
checkin_time: '3:00 PM',
checkout_date: 'January 18, 2024'
},
conversation_metadata: {
booking_reference: 'RB123456',
guest_tier: 'gold_member'
}
})
});
// Send service confirmation template
const serviceTemplate = await fetch('/api/v1/whatsapp/templates/send', {
method: 'POST',
headers: {
'Authorization': `Bearer ${staffToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
guest_phone: '+1234567890',
template_name: 'service_confirmation',
language: 'en',
parameters: {
service_type: 'Spa Massage',
appointment_time: 'Tomorrow at 2:00 PM',
location: 'Wellness Center - Room 3',
estimated_duration: '90 minutes'
}
})
});
Rich Media Messaging
// Upload media file first
const formData = new FormData();
formData.append('media', fileBlob, 'room_key_info.jpg');
formData.append('media_type', 'image');
const mediaUpload = await fetch('/api/v1/whatsapp/media/upload', {
method: 'POST',
headers: {
'Authorization': `Bearer ${staffToken}`
},
body: formData
});
const { media_id, media_url } = await mediaUpload.json();
// Send image with caption
const imageMessage = await fetch('/api/v1/whatsapp/messages/send-media', {
method: 'POST',
headers: {
'Authorization': `Bearer ${staffToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
guest_phone: '+1234567890',
media_id: media_id,
media_type: 'image',
caption: 'Here is your digital room key information. Tap your phone on the door reader to access your room.',
conversation_id: 'conv_abc123'
})
});
// Send document
const documentMessage = await fetch('/api/v1/whatsapp/messages/send-media', {
method: 'POST',
headers: {
'Authorization': `Bearer ${staffToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
guest_phone: '+1234567890',
media_id: 'doc_media_789',
media_type: 'document',
filename: 'hotel_amenities_guide.pdf',
caption: 'Complete guide to all hotel amenities and services'
})
});
Interactive Messaging
// Send message with quick reply buttons
const interactiveMessage = await fetch('/api/v1/whatsapp/messages/send-interactive', {
method: 'POST',
headers: {
'Authorization': `Bearer ${staffToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
guest_phone: '+1234567890',
interactive_type: 'buttons',
content: {
text: 'How would you like to extend your stay?',
buttons: [
{
id: 'extend_1_night',
title: '1 More Night'
},
{
id: 'extend_2_nights',
title: '2 More Nights'
},
{
id: 'call_front_desk',
title: 'Call Front Desk'
}
]
}
})
});
// Send list message for service options
const listMessage = await fetch('/api/v1/whatsapp/messages/send-interactive', {
method: 'POST',
headers: {
'Authorization': `Bearer ${staffToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
guest_phone: '+1234567890',
interactive_type: 'list',
content: {
text: 'What service would you like to request?',
button_text: 'View Services',
sections: [
{
title: 'Room Services',
rows: [
{ id: 'housekeeping', title: 'Housekeeping', description: 'Extra towels, cleaning' },
{ id: 'room_service', title: 'Room Service', description: 'Food and beverage delivery' },
{ id: 'maintenance', title: 'Maintenance', description: 'Technical issues' }
]
},
{
title: 'Guest Services',
rows: [
{ id: 'concierge', title: 'Concierge', description: 'Local recommendations, bookings' },
{ id: 'transportation', title: 'Transportation', description: 'Taxi, shuttle service' }
]
}
]
}
})
});
Conversation Management
// Get conversation history
const conversation = await fetch('/api/v1/whatsapp/conversations/conv_abc123', {
headers: {
'Authorization': `Bearer ${staffToken}`
}
});
const conversationData = await conversation.json();
// Returns: messages, participants, status, metadata
// Get all conversations for a guest
const guestConversations = await fetch('/api/v1/whatsapp/conversations?guest_phone=%2B1234567890&status=active', {
headers: {
'Authorization': `Bearer ${staffToken}`
}
});
// Mark conversation as resolved
const resolveConversation = await fetch('/api/v1/whatsapp/conversations/conv_abc123/resolve', {
method: 'POST',
headers: {
'Authorization': `Bearer ${staffToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
resolution_notes: 'Guest room service request completed successfully',
satisfaction_rating: 5,
follow_up_required: false
})
});
Message Status Tracking
// Get message status
const messageStatus = await fetch('/api/v1/whatsapp/messages/msg_123456/status', {
headers: {
'Authorization': `Bearer ${staffToken}`
}
});
const {
status, // sent, delivered, read, failed
sent_at,
delivered_at,
read_at,
failure_reason
} = await messageStatus.json();
// Get delivery analytics for a conversation
const deliveryAnalytics = await fetch('/api/v1/whatsapp/conversations/conv_abc123/analytics', {
headers: {
'Authorization': `Bearer ${staffToken}`
}
});
const analytics = await deliveryAnalytics.json();
// Returns: delivery rates, response times, satisfaction scores
Template Management
// Get available templates
const templates = await fetch('/api/v1/whatsapp/templates?language=en&category=guest_services', {
headers: {
'Authorization': `Bearer ${staffToken}`
}
});
const templateList = await templates.json();
// Get template details
const templateDetails = await fetch('/api/v1/whatsapp/templates/welcome_checkin', {
headers: {
'Authorization': `Bearer ${staffToken}`
}
});
const {
name,
category,
language,
status,
components,
parameters,
example
} = await templateDetails.json();
// Submit new template for approval
const newTemplate = await fetch('/api/v1/whatsapp/templates', {
method: 'POST',
headers: {
'Authorization': `Bearer ${adminToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'late_checkout_confirmation',
category: 'UTILITY',
language: 'en',
components: [
{
type: 'HEADER',
format: 'TEXT',
text: 'Late Checkout Confirmed'
},
{
type: 'BODY',
text: 'Hi {{1}}, your late checkout until {{2}} has been confirmed for room {{3}}. Additional charges: {{4}}.'
},
{
type: 'FOOTER',
text: 'Thank you for staying with us!'
}
]
})
});
Webhook Event Handling
Webhook Configuration
// Configure webhook endpoint
const webhookConfig = await fetch('/api/v1/whatsapp/webhooks/configure', {
method: 'POST',
headers: {
'Authorization': `Bearer ${adminToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
webhook_url: 'https://your-hotel.com/webhooks/whatsapp',
events: [
'message_delivered',
'message_read',
'message_failed',
'inbound_message',
'media_received'
],
verify_token: 'your_verification_token',
retry_config: {
max_retries: 3,
retry_delay: 5000
}
})
});
Processing Webhook Events
// Example webhook event handler
app.post('/webhooks/whatsapp', (req, res) => {
const event = req.body;
switch(event.event) {
case 'inbound_message':
handleInboundMessage(event.data);
break;
case 'message_delivered':
updateMessageStatus(event.data.message_id, 'delivered');
break;
case 'message_read':
updateMessageStatus(event.data.message_id, 'read');
break;
case 'message_failed':
handleMessageFailure(event.data);
break;
case 'media_received':
processInboundMedia(event.data);
break;
}
res.status(200).send('OK');
});
// Handle inbound message processing
async function handleInboundMessage(messageData) {
const { guest_phone, message_content, conversation_id } = messageData;
// Get guest context
const guestInfo = await getGuestByPhone(guest_phone);
// Process message content for intent
const intent = await analyzeMessageIntent(message_content);
// Route to appropriate staff member or automated response
if (intent.type === 'service_request') {
await routeToStaff(conversation_id, intent.department);
} else if (intent.type === 'faq') {
await sendAutomatedResponse(guest_phone, intent.response);
}
}
Error Handling and Best Practices
Message Window Management
// Check if guest is within messaging window
const windowStatus = await fetch(`/api/v1/whatsapp/conversations/conv_abc123/window-status`, {
headers: {
'Authorization': `Bearer ${staffToken}`
}
});
const {
within_window,
window_expires_at,
hours_remaining
} = await windowStatus.json();
if (!within_window) {
// Must use template message
await sendTemplateMessage(guestPhone, 'service_followup', parameters);
} else {
// Can send free-form message
await sendTextMessage(guestPhone, messageContent);
}
Rate Limiting and Optimization
// Batch send messages with rate limiting
const messages = [
{ phone: '+1234567890', content: 'Message 1' },
{ phone: '+1234567891', content: 'Message 2' },
// ... more messages
];
const batchSend = await fetch('/api/v1/whatsapp/messages/batch-send', {
method: 'POST',
headers: {
'Authorization': `Bearer ${staffToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
messages: messages,
rate_limit: {
messages_per_second: 10,
batch_size: 100
},
delivery_options: {
retry_failed: true,
track_delivery: true
}
})
});
const { batch_id, estimated_completion } = await batchSend.json();
Error Response Handling
{
"error": {
"code": "MESSAGE_WINDOW_EXPIRED",
"message": "Cannot send free-form message outside 24-hour window",
"details": {
"guest_phone": "+1234567890",
"last_guest_message": "2024-01-14T10:00:00Z",
"window_expires": "2024-01-15T10:00:00Z",
"suggested_templates": ["service_followup", "general_inquiry"]
},
"recovery_options": [
"Use approved template message",
"Wait for guest to initiate conversation",
"Contact guest via alternative channel"
]
}
}
Common Error Codes
INVALID_PHONE_NUMBER(400) - Invalid or unsupported phone number formatTEMPLATE_NOT_FOUND(404) - Specified WhatsApp template not found or not approvedMESSAGE_WINDOW_EXPIRED(403) - Cannot send outside 24-hour messaging windowRATE_LIMIT_EXCEEDED(429) - Exceeded WhatsApp or platform rate limitsMEDIA_UPLOAD_FAILED(422) - Media file upload or processing failedWEBHOOK_DELIVERY_FAILED(500) - Webhook delivery failureGUEST_OPTED_OUT(403) - Guest has opted out of WhatsApp communications