VenddorDocumentação API
API atualAPI legada
Guia rápidoReferência completa
Carregando índice…
API atual/Referência completa/WhatsApp Commerce: caixa de entrada

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

GET/api/v1/vendor/whatsapp/inbox/threadsSeller

Lista 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

statusstring
openpendingresolved
Atalho de filtro, um valor por vez. open: 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.
qstring
Busca por trecho do telefone do cliente (sem diferenciar maiúsculas). Procura em customer_phone, que guarda só dígitos.
fromstring
Data inicial YYYY-MM-DD, inclusiva. Compara com a última mensagem recebida; conversas que o cliente nunca respondeu usam a data de criação.
tostring
Data final YYYY-MM-DD, inclusiva (vale o dia inteiro).
pageintegerpadrão: 1
Página, a partir de 1. Valor inválido ou menor que 1 vira 1.
per_pageintegerpadrão: 50
Itens por página, de 1 a 200. Acima de 200 volta para 50.

Exemplo de requisição

bash
curl "$BASE_URL/api/v1/vendor/whatsapp/inbox/threads?status=pending&per_page=20" \
  -H "Authorization: Bearer $TOKEN"

Resposta

200Conversas devolvidas
json
{
  "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
}
200Usuário sem cadastro de seller
json
{
  "threads": [],
  "total": 0,
  "page": 1,
  "per_page": 50,
  "total_pages": 0,
  "vendor_profile_required": true,
  "code": "vendor_profile_not_found"
}

Campos da resposta

threadsarray
Conversas da página, da mais recente para a mais antiga.
threads[].iduuid
Id da conversa. Use nas demais rotas.
threads[].vendor_iduuid
Seller dono da conversa.
threads[].customer_phonestring
Telefone do cliente, só dígitos com DDI.
threads[].bot_enabledboolean
true se o assistente automático responde nesta conversa.
threads[].human_requested_atstring
RFC 3339. Quando o cliente pediu um atendente. Ausente se nunca pediu.
threads[].last_inbound_atstring
RFC 3339. Última mensagem do cliente. Ausente se ele nunca escreveu (conversa aberta pela loja).
threads[].last_outbound_atstring
RFC 3339. Última mensagem enviada pela loja ou pelo assistente.
threads[].unread_countinteger
Mensagens do cliente ainda não marcadas como lidas.
threads[].urgency_statestring
normalhuman_requestedwaiting_clientmanual_mode
Estado de urgência, calculado a cada chamada e não gravado.
threads[].urgency_seconds_remaininginteger
Segundos restantes do prazo do estado de urgência. Ausente em normal.
threads[].tagsarray
Etiquetas da conversa. Sempre um array, possivelmente vazio.
threads[].assigned_to_user_iduuid
Atendente responsável, quando há. Ausente se ninguém foi atribuído.
totalinteger
Total de conversas que atendem ao filtro.
pageinteger
Página devolvida.
per_pageinteger
Tamanho da página usado.
total_pagesinteger
Total de páginas.
vendor_profile_requiredboolean
Só aparece (com true) 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

StatusQuandoCorpo
400from 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 ..."}
401Sem token ou token inválido{"error":"authentication required"}
403Token que não é de seller{"error":"insufficient permissions"}
403Módulo desligado{"error":"module_disabled","module":"whatsapp-commerce"}
403Seller ainda em análise de cadastro{"error":"vendor_pending_review","message":"..."}
403Falta o privilégio da equipe{"error":"insufficient vendor privileges","required":"vendor_manage_whatsapp"}
500Falha ao consultar{"error":"Failed to list threads: ..."}
Lista vazia não é erro

Um usuário sem cadastro de seller recebe 200 com a lista vazia e vendor_profile_required: true. As demais rotas desta página devolvem 404 com "code":"vendor_profile_not_found" nesse caso.

Abrir uma conversa

GET/api/v1/vendor/whatsapp/inbox/threads/{id}Seller

Abre 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ório
Id da conversa (threads[].id).

Exemplo de requisição

bash
curl "$BASE_URL/api/v1/vendor/whatsapp/inbox/threads/9b1f3c52-6a0e-4d57-8a43-2f6c1d7e90ab" \
  -H "Authorization: Bearer $TOKEN"

Resposta

200Conversa e mensagens
json
{
  "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

threadobject
A conversa, com os mesmos campos da lista.
messagesarray
Até 50 mensagens, da mais antiga para a mais nova.
messages[].idinteger
Id numérico da mensagem. Serve para baixar a mídia.
messages[].wa_message_idstring
Id da mensagem na Meta (wamid...). Use em reply_to para citar a mensagem.
messages[].directionstring
inboundoutbound
inbound veio do cliente, outbound saiu da loja.
messages[].message_typestring
text, image, video, audio, document, button, interactive, location ou template.
messages[].bodystring
Texto ou legenda. Pode estar ausente em mídia sem legenda.
messages[].media_urlstring
Origem da mídia. meta://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_typestring
Tipo MIME da mídia.
messages[].media_filenamestring
Nome do arquivo, quando o cliente mandou um documento.
messages[].media_share_urlstring
Link público assinado que serve a mídia sem token. Só vem em mensagens com mídia.
messages[].template_namestring
Nome do modelo, quando a mensagem foi um template.
messages[].statusstring
Entrega: pending, sent, delivered, read ou failed. Em mensagens recebidas costuma vir vazio ou delivered.
messages[].sent_manuallyboolean
true quando um atendente humano enviou; false para o assistente automático.
messages[].is_repboolean
true se o telefone é de um representante comercial cadastrado, não de um cliente.
messages[].sent_atstring
RFC 3339. Envio à Meta.
messages[].delivered_atstring
RFC 3339. Entrega ao aparelho do cliente.
messages[].read_atstring
RFC 3339. Quando o cliente leu.
messages[].created_atstring
RFC 3339. Quando a mensagem foi registrada.

Erros

StatusQuandoCorpo
401 / 403Mesmos da listaveja acima
404Conversa não existe ou é de outro seller{"error":"thread not found"}
404Usuário sem cadastro de seller{"error":"vendor profile not found","code":"vendor_profile_not_found"}
500Falha ao ler{"error":"Failed to fetch thread: ..."}
Abrir a conversa envia confirmação de leitura

Ao abrir uma conversa, a plataforma avisa a Meta que as até 10 últimas mensagens recebidas foram lidas (o cliente passa a ver os dois tiques azuis). Isso não zera unread_count: chame mark-read para isso. Em integrações que apenas espelham as conversas, evite abrir cada uma só para ler.

Contexto do cliente

GET/api/v1/vendor/whatsapp/inbox/threads/{id}/customer-contextSeller

Pedidos 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ório
Id da conversa.

Exemplo de requisição

bash
curl "$BASE_URL/api/v1/vendor/whatsapp/inbox/threads/$THREAD_ID/customer-context" \
  -H "Authorization: Bearer $TOKEN"

Resposta

200Contexto do cliente
json
{
  "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

phonestring
Telefone da conversa.
total_ordersinteger
Quantos pedidos o telefone tem na loja.
total_spent_centsinteger
Soma dos totais desses pedidos, em centavos.
first_order_atstring
RFC 3339. Primeiro pedido. Ausente sem pedidos.
last_order_atstring
RFC 3339. Último pedido. Ausente sem pedidos.
open_ordersarray
Os pedidos de recent_orders que ainda estão em aberto (is_open). Mesmo formato.
recent_ordersarray
Até 12 pedidos, do mais novo para o mais antigo.
recent_orders[].order_iduuid
Id do pedido. É o que send-payment espera.
recent_orders[].order_numberstring
Número de exibição do pedido.
recent_orders[].statusstring
Letra do status: O em aberto, I incompleto, C cancelado, P processado, F concluído, D entregue, B backorder.
recent_orders[].status_labelstring
Rótulo curto em português desse status. Outras letras voltam como vieram.
recent_orders[].payment_statusstring
Situação do pagamento, como gravada no pedido.
recent_orders[].is_openboolean
true para status O ou I.
recent_orders[].total_centsinteger
Total do pedido em centavos.
recent_orders[].item_countinteger
Quantidade de linhas de item.
recent_orders[].itemsarray
Itens: product_id, name, quantity, variation_label, image_url, unit_price_cents (centavos).
recent_orders[].reorder_linkstring
Link da mini-loja com os itens do pedido já no carrinho. Ausente quando o link não pôde ser gerado.
top_productsarray
Até 5 produtos mais pedidos pelo cliente: product_id, name, total_qty, order_count, image_url.

Erros

StatusQuandoCorpo
401 / 403Mesmos da listaveja acima
404Conversa de outro seller ou inexistente{"error":"thread not found"}
500Falha ao montar{"error":"failed to load customer context"}
Cliente sem pedido

Telefone sem nenhum pedido devolve 200 com contadores em zero e listas vazias, não 404.

Marcar como lida

POST/api/v1/vendor/whatsapp/inbox/threads/{id}/mark-readSeller

Zera 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ório
Id da conversa.

Exemplo de requisição

bash
curl -X POST "$BASE_URL/api/v1/vendor/whatsapp/inbox/threads/$THREAD_ID/mark-read" \
  -H "Authorization: Bearer $TOKEN"

Resposta

200Marcada como lida
json
{ "success": "ok" }

Erros

StatusQuandoCorpo
401 / 403Mesmos da listaveja acima
404Conversa de outro seller ou inexistente{"error":"thread not found"}
500Falha ao gravar{"error":"Failed to mark read: ..."}
success é texto, não booleano

Aqui success vem como a string "ok". Nas rotas de resposta, success é true. Não compare o valor; confira só o status HTTP.

Veja também

  • Responder
  • Carrinho e cobrança
  • Notas internas
Anterior
Caixa de entrada do WhatsApp
Próxima
Responder
Nesta página
  • Listar as conversas
  • Exemplo de requisição
  • Resposta
  • Erros
  • Abrir uma conversa
  • Exemplo de requisição
  • Resposta
  • Erros
  • Contexto do cliente
  • Exemplo de requisição
  • Resposta
  • Erros
  • Marcar como lida
  • Exemplo de requisição
  • Resposta
  • Erros
  • Veja também