Skip to main content

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

ParameterTypeDescription
statusstringopen, closed, archived, all
channelstringwhatsapp, instagram, sms, email
assigned_tostringUser ID
labelstringFilter by label
searchstringSearch in subject and messages
sortstringcreated_at:desc, last_message_at:desc
limitintegerResults per page (max 100)
offsetintegerPagination 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

ReasonDescription
issue_resolvedProblem was fixed
not_issueNot a real issue/question answered
duplicateSame as another conversation
spamSpam 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()
}