Manage Conversations
Handle customer conversations across all channels.
What is a Conversation?
A conversation is a thread of messages between your team and a contact. Each conversation:
- Belongs to one contact
- Uses one channel (WhatsApp, Instagram, SMS, or Email)
- Has a status (open, closed, archived)
- Can be assigned to team members
- Can have labels for organization
Listing Conversations
Get All Open Conversations
curl "https://api.huechat.ai/v2/conversations?status=open" \
-H "X-API-Key: sk_live_your_key"
Response
{
"data": [
{
"id": "conv_abc123",
"contact_id": "cnt_xyz789",
"contact": {
"id": "cnt_xyz789",
"full_name": "John Doe",
"phone": "+1234567890"
},
"channel": "whatsapp",
"subject": "Order inquiry",
"status": "open",
"priority": "high",
"assigned_to": {
"id": "usr_agent1",
"name": "Sarah Johnson"
},
"labels": ["billing", "urgent"],
"message_count": 5,
"unread_count": 2,
"created_at": "2026-01-25T10:00:00Z",
"last_message_at": "2026-01-25T14:30:00Z",
"last_message_preview": "Can you check my order status?"
}
],
"pagination": {
"limit": 20,
"offset": 0,
"total": 45,
"has_more": true
}
}
Filtering Options
| Parameter | Type | Description |
|---|---|---|
status | string | open, closed, archived, all |
channel | string | whatsapp, instagram, sms, email |
assigned_to | string | User ID |
label | string | Filter by label |
search | string | Search in subject and messages |
sort | string | created_at:desc, last_message_at:desc |
limit | integer | Results per page (max 100) |
offset | integer | Pagination offset |
Examples
Unassigned conversations:
curl "https://api.huechat.ai/v2/conversations?status=open&assigned_to=none" \
-H "X-API-Key: sk_live_your_key"
Urgent WhatsApp conversations:
curl "https://api.huechat.ai/v2/conversations?channel=whatsapp&label=urgent" \
-H "X-API-Key: sk_live_your_key"
Search for keyword:
curl "https://api.huechat.ai/v2/conversations?search=refund" \
-H "X-API-Key: sk_live_your_key"
Get Single Conversation
curl https://api.huechat.ai/v2/conversation/conv_abc123 \
-H "X-API-Key: sk_live_your_key"
Get Conversation Messages
curl "https://api.huechat.ai/v2/conversation/conv_abc123/messages?limit=50" \
-H "X-API-Key: sk_live_your_key"
Response
{
"data": [
{
"id": "msg_001",
"conversation_id": "conv_abc123",
"content": "Hi, I have a question about my order",
"message_type": "text",
"sent_by": "contact",
"sent_at": "2026-01-25T10:00:00Z",
"status": "received"
},
{
"id": "msg_002",
"conversation_id": "conv_abc123",
"content": "Of course! What's your order number?",
"message_type": "text",
"sent_by": "user",
"sender": {
"id": "usr_agent1",
"name": "Sarah Johnson"
},
"sent_at": "2026-01-25T10:05:00Z",
"status": "delivered"
}
],
"pagination": {
"limit": 50,
"offset": 0,
"total": 2,
"has_more": false
}
}
Sending Messages
Reply in Conversation
curl -X POST https://api.huechat.ai/v2/conversation/conv_abc123/message \
-H "X-API-Key: sk_live_your_key" \
-H "Content-Type: application/json" \
-d '{
"message_type": "text",
"content": "Your order #12345 has shipped!"
}'
Internal Note (Agent-Only)
Send a message visible only to your team:
curl -X POST https://api.huechat.ai/v2/conversation/conv_abc123/message \
-H "X-API-Key: sk_live_your_key" \
-H "Content-Type: application/json" \
-d '{
"message_type": "text",
"content": "Customer seems upset - handle with care",
"internal": true
}'
Assigning Conversations
curl -X POST https://api.huechat.ai/v2/conversation/conv_abc123/assign \
-H "X-API-Key: sk_live_your_key" \
-H "Content-Type: application/json" \
-d '{
"assigned_to": "usr_agent1",
"internal_note": "Please handle this VIP customer"
}'
Unassign
Set assigned_to to null:
curl -X POST https://api.huechat.ai/v2/conversation/conv_abc123/assign \
-H "X-API-Key: sk_live_your_key" \
-H "Content-Type: application/json" \
-d '{
"assigned_to": null
}'
Managing Labels
Add Labels
curl -X POST https://api.huechat.ai/v2/conversation/conv_abc123/label \
-H "X-API-Key: sk_live_your_key" \
-H "Content-Type: application/json" \
-d '{
"labels": ["urgent", "billing"],
"action": "add"
}'
Remove Labels
curl -X POST https://api.huechat.ai/v2/conversation/conv_abc123/label \
-H "X-API-Key: sk_live_your_key" \
-H "Content-Type: application/json" \
-d '{
"labels": ["urgent"],
"action": "remove"
}'
Replace All Labels
curl -X POST https://api.huechat.ai/v2/conversation/conv_abc123/label \
-H "X-API-Key: sk_live_your_key" \
-H "Content-Type: application/json" \
-d '{
"labels": ["resolved", "feedback-requested"],
"action": "replace"
}'
Resolving Conversations
curl -X POST https://api.huechat.ai/v2/conversation/conv_abc123/resolve \
-H "X-API-Key: sk_live_your_key" \
-H "Content-Type: application/json" \
-d '{
"resolution_reason": "issue_resolved",
"internal_note": "Refund processed successfully",
"send_satisfaction_survey": true
}'
Resolution Reasons
| Reason | Description |
|---|---|
issue_resolved | Problem was fixed |
not_issue | Not a real issue/question answered |
duplicate | Same as another conversation |
spam | Spam or unwanted contact |
Conversation Status Flow
┌─────────────────────────────────────┐
│ │
▼ │
┌────────┐ ┌────────┐ ┌──────────┐│
│ OPEN │────▶│ CLOSED │────▶│ ARCHIVED ││
└────────┘ └────────┘ └──────────┘│
▲ │ │
│ │ (reopened by new │
│ │ customer message) │
└───────────────┘ │
│
Code Examples
Handle Incoming Messages
// Webhook handler
app.post('/webhooks/huechat', async (req, res) => {
const event = req.body;
if (event.type === 'message.received') {
const { conversation_id, content, contact } = event.data;
console.log(`New message from ${contact.name}: ${content}`);
// Auto-assign to available agent
if (!event.data.conversation.assigned_to) {
const availableAgent = await getAvailableAgent();
await client.conversations.assign(conversation_id, {
assigned_to: availableAgent.id
});
}
// Add label for keywords
if (content.toLowerCase().includes('urgent')) {
await client.conversations.addLabels(conversation_id, ['urgent']);
}
}
res.status(200).send();
});
Conversation Dashboard
def get_dashboard_stats():
# Get conversation counts
open_convs = client.conversations.list(status='open')
unassigned = client.conversations.list(status='open', assigned_to='none')
return {
'open_count': open_convs.pagination.total,
'unassigned_count': unassigned.pagination.total,
'oldest_unanswered': get_oldest_unanswered(),
'avg_response_time': calculate_avg_response_time()
}