Conversas
Lista as conversas do WhatsApp do seller, abre uma com as últimas mensagens, mostra o contexto do cliente e marca como lida.
Use estas quatro rotas para montar uma fila de atendimento. A lista mostra as conversas do seller da mais recente para a mais antiga. Ao abrir uma conversa você recebe as últimas 50 mensagens em ordem cronológica. O contexto do cliente reúne pedidos e itens mais comprados do telefone da conversa, para o atendente saber com quem fala. mark-read zera o contador de não lidas.
Todas exigem token de seller e o módulo whatsapp-commerce ligado. Os erros comuns (401, 403, 404 thread not found) estão na tabela de cada rota e no resumo da seção.
Listar as conversas
/api/v1/vendor/whatsapp/inbox/threadsSellerLista as conversas do seller
Devolve só conversas do seller do token. Conversas sem seller (as do número padrão da loja) nunca aparecem aqui.
Parâmetros de consulta
statusstringopenpendingresolvedopen: conversas em que o assistente automático está ligado (bot_enabled=true). pending: conversas com mensagens não lidas. resolved: conversas sem nenhuma não lida. Qualquer outro valor é ignorado e não filtra.qstringcustomer_phone, que guarda só dígitos.fromstringYYYY-MM-DD, inclusiva. Compara com a última mensagem recebida; conversas que o cliente nunca respondeu usam a data de criação.tostringYYYY-MM-DD, inclusiva (vale o dia inteiro).pageintegerpadrão: 1per_pageintegerpadrão: 50Exemplo de requisição
curl "$BASE_URL/api/v1/vendor/whatsapp/inbox/threads?status=pending&per_page=20" \
-H "Authorization: Bearer $TOKEN"Resposta
{
"threads": [
{
"id": "9b1f3c52-6a0e-4d57-8a43-2f6c1d7e90ab",
"vendor_id": "94bd7e9a-fdad-4d01-8fc2-ba9d677d8b36",
"customer_phone": "5511999990000",
"bot_enabled": true,
"human_requested_at": "2026-10-11T13:02:11Z",
"last_inbound_at": "2026-10-11T13:02:11Z",
"last_outbound_at": "2026-10-11T12:58:40Z",
"unread_count": 2,
"created_at": "2026-10-09T18:20:03Z",
"updated_at": "2026-10-11T13:02:11Z",
"urgency_state": "human_requested",
"urgency_seconds_remaining": 240,
"tags": []
}
],
"total": 1,
"page": 1,
"per_page": 20,
"total_pages": 1
}{
"threads": [],
"total": 0,
"page": 1,
"per_page": 50,
"total_pages": 0,
"vendor_profile_required": true,
"code": "vendor_profile_not_found"
}Campos da resposta
threadsarraythreads[].iduuidthreads[].vendor_iduuidthreads[].customer_phonestringthreads[].bot_enabledbooleantrue se o assistente automático responde nesta conversa.threads[].human_requested_atstringthreads[].last_inbound_atstringthreads[].last_outbound_atstringthreads[].unread_countintegerthreads[].urgency_statestringnormalhuman_requestedwaiting_clientmanual_modethreads[].urgency_seconds_remainingintegernormal.threads[].tagsarraythreads[].assigned_to_user_iduuidtotalintegerpageintegerper_pageintegertotal_pagesintegervendor_profile_requiredbooleantrue) quando o usuário não tem cadastro de seller. A lista vem vazia com status 200 para o painel mostrar a tela de cadastro.Erros
| Status | Quando | Corpo |
|---|---|---|
| 400 | from ou to fora do formato YYYY-MM-DD | {"error":"whatsapp threads: invalid from date: parsing time \"10/10/2026\" as \"2006-01-02\": cannot parse ..."} |
| 401 | Sem token ou token inválido | {"error":"authentication required"} |
| 403 | Token que não é de seller | {"error":"insufficient permissions"} |
| 403 | Módulo desligado | {"error":"module_disabled","module":"whatsapp-commerce"} |
| 403 | Seller ainda em análise de cadastro | {"error":"vendor_pending_review","message":"..."} |
| 403 | Falta o privilégio da equipe | {"error":"insufficient vendor privileges","required":"vendor_manage_whatsapp"} |
| 500 | Falha ao consultar | {"error":"Failed to list threads: ..."} |
Abrir uma conversa
/api/v1/vendor/whatsapp/inbox/threads/{id}SellerAbre uma conversa com as últimas mensagens
Devolve a conversa e as 50 últimas mensagens, da mais antiga para a mais nova. Não há paginação para mensagens mais antigas.
Parâmetros de caminho
iduuidobrigatóriothreads[].id).Exemplo de requisição
curl "$BASE_URL/api/v1/vendor/whatsapp/inbox/threads/9b1f3c52-6a0e-4d57-8a43-2f6c1d7e90ab" \
-H "Authorization: Bearer $TOKEN"Resposta
{
"thread": {
"id": "9b1f3c52-6a0e-4d57-8a43-2f6c1d7e90ab",
"vendor_id": "94bd7e9a-fdad-4d01-8fc2-ba9d677d8b36",
"customer_phone": "5511999990000",
"bot_enabled": true,
"unread_count": 2,
"last_inbound_at": "2026-10-11T13:02:11Z",
"created_at": "2026-10-09T18:20:03Z",
"updated_at": "2026-10-11T13:02:11Z",
"urgency_state": "normal",
"tags": []
},
"messages": [
{
"id": 48211,
"thread_id": "9b1f3c52-6a0e-4d57-8a43-2f6c1d7e90ab",
"wa_message_id": "wamid.HBgNNTUxMTk5OTk5MDAwMBUCABIYFA",
"direction": "inbound",
"message_type": "text",
"body": "Oi, vocês têm o tênis preto no 42?",
"sent_manually": false,
"is_rep": false,
"created_at": "2026-10-11T13:02:11Z"
},
{
"id": 48212,
"thread_id": "9b1f3c52-6a0e-4d57-8a43-2f6c1d7e90ab",
"direction": "outbound",
"message_type": "image",
"body": "Segue a foto",
"media_url": "meta://1182773450123456",
"media_mime_type": "image/jpeg",
"media_share_url": "https://minhaloja.io.venddor.com.br/api/...",
"status": "delivered",
"sent_manually": true,
"is_rep": false,
"sent_at": "2026-10-11T13:04:00Z",
"delivered_at": "2026-10-11T13:04:02Z",
"created_at": "2026-10-11T13:04:00Z"
}
]
}Campos da resposta
threadobjectmessagesarraymessages[].idintegermessages[].wa_message_idstringwamid...). Use em reply_to para citar a mensagem.messages[].directionstringinboundoutboundinbound veio do cliente, outbound saiu da loja.messages[].message_typestringtext, image, video, audio, document, button, interactive, location ou template.messages[].bodystringmessages[].media_urlstringmeta://ID quer dizer que o arquivo está na Meta e só sai pela rota de mídia; uma URL http(s) é pública.messages[].media_mime_typestringmessages[].media_filenamestringmessages[].media_share_urlstringmessages[].template_namestringmessages[].statusstringpending, sent, delivered, read ou failed. Em mensagens recebidas costuma vir vazio ou delivered.messages[].sent_manuallybooleantrue quando um atendente humano enviou; false para o assistente automático.messages[].is_repbooleantrue se o telefone é de um representante comercial cadastrado, não de um cliente.messages[].sent_atstringmessages[].delivered_atstringmessages[].read_atstringmessages[].created_atstringErros
| Status | Quando | Corpo |
|---|---|---|
| 401 / 403 | Mesmos da lista | veja acima |
| 404 | Conversa não existe ou é de outro seller | {"error":"thread not found"} |
| 404 | Usuário sem cadastro de seller | {"error":"vendor profile not found","code":"vendor_profile_not_found"} |
| 500 | Falha ao ler | {"error":"Failed to fetch thread: ..."} |
Contexto do cliente
/api/v1/vendor/whatsapp/inbox/threads/{id}/customer-contextSellerPedidos e itens mais comprados do cliente da conversa
Somente leitura: nada é enviado ao cliente. A plataforma procura pedidos cujo telefone coincide com o da conversa, comparando só os dígitos (os 10 ou 11 últimos). Devolve até 12 pedidos recentes, os 5 produtos mais comprados e um link de recompra por pedido.
Parâmetros de caminho
iduuidobrigatórioExemplo de requisição
curl "$BASE_URL/api/v1/vendor/whatsapp/inbox/threads/$THREAD_ID/customer-context" \
-H "Authorization: Bearer $TOKEN"Resposta
{
"phone": "5511999990000",
"total_orders": 3,
"total_spent_cents": 52700,
"first_order_at": "2026-08-02T14:11:00Z",
"last_order_at": "2026-10-05T19:40:00Z",
"open_orders": [
{
"order_id": "3f73310d-bfdd-4713-a664-305c08eda58b",
"order_number": "PEDIDO-20261005-0007",
"status": "O",
"status_label": "Em aberto",
"payment_status": "pending",
"is_open": true,
"total_cents": 18900,
"created_at": "2026-10-05T19:40:00Z",
"item_count": 1,
"items": [
{
"product_id": "c3f92551-9dda-4fc7-b518-353d1c4e4035",
"name": "Tênis Urbano Preto",
"quantity": 1,
"variation_label": "42",
"unit_price_cents": 18900
}
],
"reorder_link": "https://minhaloja.io.venddor.com.br/wa/AbC123/cart?stage=W3sidCI6InAi..."
}
],
"recent_orders": [],
"top_products": [
{ "product_id": "c3f92551-9dda-4fc7-b518-353d1c4e4035", "name": "Tênis Urbano Preto", "total_qty": 2, "order_count": 2 }
]
}Campos da resposta
phonestringtotal_ordersintegertotal_spent_centsintegerfirst_order_atstringlast_order_atstringopen_ordersarrayrecent_orders que ainda estão em aberto (is_open). Mesmo formato.recent_ordersarrayrecent_orders[].order_iduuidsend-payment espera.recent_orders[].order_numberstringrecent_orders[].statusstringO em aberto, I incompleto, C cancelado, P processado, F concluído, D entregue, B backorder.recent_orders[].status_labelstringrecent_orders[].payment_statusstringrecent_orders[].is_openbooleantrue para status O ou I.recent_orders[].total_centsintegerrecent_orders[].item_countintegerrecent_orders[].itemsarrayproduct_id, name, quantity, variation_label, image_url, unit_price_cents (centavos).recent_orders[].reorder_linkstringtop_productsarrayproduct_id, name, total_qty, order_count, image_url.Erros
| Status | Quando | Corpo |
|---|---|---|
| 401 / 403 | Mesmos da lista | veja acima |
| 404 | Conversa de outro seller ou inexistente | {"error":"thread not found"} |
| 500 | Falha ao montar | {"error":"failed to load customer context"} |
Marcar como lida
/api/v1/vendor/whatsapp/inbox/threads/{id}/mark-readSellerZera as mensagens não lidas da conversa
Sem corpo. Define unread_count como 0. Repetir a chamada não tem efeito.
Parâmetros de caminho
iduuidobrigatórioExemplo de requisição
curl -X POST "$BASE_URL/api/v1/vendor/whatsapp/inbox/threads/$THREAD_ID/mark-read" \
-H "Authorization: Bearer $TOKEN"Resposta
{ "success": "ok" }Erros
| Status | Quando | Corpo |
|---|---|---|
| 401 / 403 | Mesmos da lista | veja acima |
| 404 | Conversa de outro seller ou inexistente | {"error":"thread not found"} |
| 500 | Falha ao gravar | {"error":"Failed to mark read: ..."} |