Inbox — conversas e mensagens
Como consumir o inbox do PEPINO ZAP — listar conversas, carregar mensagens (com histórico paginado) e os padrões para uma interface de chat responsiva — cache por conversa, preservação de URLs de mídia, tempo real por polling ou WebSocket e rolagem para o fim.
O inbox é o sistema de registro das conversas: todo o histórico de mensagens, a mídia hospedada e os metadados de cada contato ficam acessíveis pela API /v1/inbox/*, independente de qual instância (número) recebeu cada mensagem.
As conversas não ficam sob a instância. Não procure por /instances/{id}/conversations — o
caminho é /v1/inbox/conversations. A instância é apenas o número que enviou/recebeu; o
histórico é centralizado no inbox.
As conversas seguem o modo (teste/produção) da instância — é o mesmo isolamento de dados por
modo das instâncias e webhooks. A
conversa de uma instância de teste só aparece pela API de teste
(sandbox.pepinozap.com.br + key pzk_test_); o Inbox do painel é sempre Produção, então
conversa de instância de teste não aparece lá — não é bug, é o modo. Para vê-la no painel, use
uma instância de produção (key pzk_live_ / host api.*).
Listar conversas
GET /v1/inbox/conversations devolve as conversas com o resumo (último trecho, não-lidas, status, etiquetas, atendente/departamento atribuído) — sem o corpo das mensagens. Aceita filtros por status (open/pending/resolved), label e department, e ecoa os contadores por status para os badges das abas.
Use essa lista para a coluna da esquerda do seu inbox e re-busque-a periodicamente (ou por evento de WebSocket) para manter os badges e o último trecho atualizados.
Carregar as mensagens de uma conversa
GET /v1/inbox/conversations/{id}/messages devolve a leva mais recente de mensagens da conversa (texto, mídia, direção, timestamps, status de entrega). Para o histórico mais antigo:
| Como | Endpoint |
|---|---|
| Paginar para trás | GET .../messages?before=<messageId> (mais antigas que aquela mensagem) |
| Puxar histórico do WhatsApp | POST /v1/inbox/conversations/{id}/history |
Cada mensagem tem uma direção (inbound/outbound). O outbound inclui tanto o que sua
integração/painel envia quanto o que a equipe responde direto no celular — o número é
multi-device, então o que sai de qualquer aparelho é espelhado aqui (e conta no tempo de resposta
dos relatórios). O webhook message.received dispara só para
inbound; mensagem que sai não gera message.received.
Padrões para um inbox responsivo
A diferença entre um inbox que "abre na hora" e um que pisca a cada clique está no cliente, não no endpoint. Quatro padrões que valem a pena seguir:
1. Cache por conversa (stale-while-revalidate)
Não re-busque do zero (com skeleton) toda vez que o usuário abre uma conversa que já viu nesta sessão. Guarde as mensagens por conversationId no cliente:
- Ao abrir: se há cache para aquela conversa, mostre-o na hora (sem skeleton) e dispare o fetch em background para revalidar — atualize a tela se algo mudou.
- Skeleton só na primeira abertura de cada conversa (cold load).
Isso mantém a navegação entre conversas instantânea e evita o "pisca-skeleton" a cada clique. Limpar tudo e mostrar skeleton em toda abertura é a causa nº 1 de inbox que "ficou lento".
2. Preserve as URLs de mídia
A mediaUrl de cada mensagem é uma URL presigned, reassinada a cada resposta (e que expira). Se você trocar o src de uma <img>/<video> a cada revalidação, o navegador recarrega a mídia — o vídeo trava reiniciando do zero.
Guarde a URL da primeira vez que carregou cada mensagem (por messageId) e reuse-a nas revalidações; só mensagens novas usam a URL fresca da resposta.
Porque a URL presigned expira, ela não serve como link durável. Para um link compartilhável ou para reter a mídia por conta própria, rehospede o arquivo do seu lado a partir do primeiro download. Veja Persistência.
3. Mantenha ao vivo — polling ou WebSocket
- Polling: re-busque as mensagens da conversa aberta a cada ~5s e a lista de conversas a cada ~10s. Simples e suficiente para a maioria dos casos.
- WebSocket (push): menor latência — em vez de esperar o próximo tick (num polling de 5s são ~2.5s de atraso médio), o evento
message.receivedchega em menos de 100ms e você recarrega na hora. Veja Tempo real por WebSocket.
Padrão recomendado (o que o próprio painel da PEPINO ZAP usa): WebSocket para o push instantâneo + um polling lento como rede de segurança. O WS entrega a latência baixa; o polling (mais espaçado) garante que nada se perca se a conexão cair entre um evento e a reconexão. Na prática: no message.received, recarregue a conversa aberta e a lista; mantenha um setInterval de fallback; e, num front multi-usuário, conecte o WS com o token efêmero, não com a API key.
Os dois combinam bem com o cache do item 1: o evento (ou o tick do polling) revalida a conversa aberta; o resto continua servido do cache.
4. Role para o fim ao abrir
Ao abrir uma conversa, role para o fim de forma instantânea (não suave) e re-cole no fim conforme cada mídia carrega:
- Imagem e vídeo mudam de altura depois de carregar e empurram o conteúdo para baixo — uma rolagem disparada cedo "para no meio" quando a mídia chega.
- Re-cole no fim com um
ResizeObserverno container das mensagens, não com oonloadde cada mídia. Ao reabrir uma conversa, o cache reusa a mesma URL de mídia → o navegador serve do cache dele e o eventoloadpode disparar antes do seu handler ser anexado, perdendo a re-rolagem (a conversa trava "no meio"). OResizeObserverpega qualquer mudança de altura, independente doonload. - Só auto-role se o usuário estiver colado no fim (distância até a última mensagem abaixo de um limiar, ex. 120px). Se ele rolou para cima lendo o histórico, não o arranque do lugar.
Combinado com o cache do item 1, reabrir uma conversa já vista é instantâneo e já no fim — sem skeleton e sem a rolagem visível "descendo até a última mensagem".
Visão geral do CRM
As ferramentas de gestão do atendimento do PEPINO ZAP — relatórios, etiquetas, justificativas de encerramento, equipe e permissões, e o construtor de chatbot. O que cada recurso é, onde fica no painel e quais endpoints o expõem.
Relatórios e métricas
O modelo de dados do relatório de gestão do PEPINO ZAP — total de atendimentos, receptivo×ativo, abertas/pendentes/resolvidas, tempo de primeira resposta, novos contatos e produtividade por atendente. Como a janela de datas funciona (fuso de Brasília), os filtros e o formato exato da resposta.