Pular para o conteúdo principal

Inbox pela API

A inbox é onde a equipe atende pelo painel. A API dá acesso às mesmas conversas, para ligar um helpdesk, um CRM ou um bot: o que a sua integração responde aparece para a equipe, e o que a equipe responde aparece para a sua integração.

Ler as conversas

curl 'https://api.joinotify.com/inbox/conversations?folder=open&unread=true' \
-H 'Authorization: Bearer sk_live_xxx'

A lista é paginada por cursor: mande o nextCursor da resposta em cursor para a próxima página, até ele vir null. As mensagens de uma conversa vêm em GET /inbox/conversations/{id}/messages, da mais recente à mais antiga, com o cursor em before.

Cada conversa diz se a janela de 24 horas está aberta (windowOpen) e até quando (windowExpiresAt). É isso que decide o que dá para responder.

Responder

curl -X POST https://api.joinotify.com/inbox/conversations/cm1c0nv000001/messages \
-H 'Authorization: Bearer sk_live_xxx' \
-H 'Content-Type: application/json' \
-d '{ "kind": "text", "text": "Oi, Ana! Seu pedido saiu para entrega." }'
kindQuando usar
textTexto livre, com a janela aberta
mediaUm arquivo, com a janela aberta — suba antes em /media
templateJanela fechada: um template aprovado reabre a conversa
noteNota interna para a equipe; nunca vai para o WhatsApp

Com a janela fechada, text e media são recusados antes de sair, com 422 window_closed — diferente de POST /messages, que aceita e falha depois. Responder reabre uma conversa fechada ou adiada e pausa as automações daquela conversa por um tempo, como quando alguém da equipe assume.

Para mandar um arquivo, envie os bytes em POST /inbox/conversations/{id}/media (o corpo é o arquivo, não multipart, com o nome em X-File-Name) e responda com { "kind": "media", "assetId": "..." }.

Organizar

PATCH /inbox/conversations/{id} fecha, reabre, deixa pendente, adia até uma data, atribui a alguém da equipe (os ids vêm de GET /inbox/agents) ou pausa as automações. Cada mudança fica registrada na conversa, e fechar e atribuir disparam os eventos conversation.closed e conversation.assigned.

Uma API key não é uma pessoa da equipe: a pasta mine vem sempre vazia, e nos eventos assigned_by e closed_by vêm null quando quem agiu foi a chave.

Tempo real

GET /inbox/stream é um stream Server-Sent Events. Ele avisa o que mudou — mensagem nova, status de mensagem, conversa atualizada, alguém digitando —, sem o conteúdo:

event: message.created
id: 12
data: {"type":"message.created","conversationId":"cm1c0nv000001","phoneNumberId":"106540352242922","messageId":"cm1m3ss4g3001","direction":"in"}

Ao receber um evento, busque a conversa ou as mensagens. Três cuidados:

  • Não há reenvio. Um evento perdido durante uma queda não volta, e Last-Event-ID não recupera nada. A cada reconexão, releia as conversas que importam.
  • O EventSource do navegador não manda o header Authorization. Use um cliente que mande — o stream foi feito para servidores.
  • Cada API key abre no máximo 5 streams ao mesmo tempo.

Se você só precisa reagir a mensagens recebidas, o webhook de messages continua sendo o caminho mais simples.

Escopo da chave

Uma API key restrita a alguns números só vê as conversas desses números — uma conversa de outro número responde 404, como se não existisse. GET /inbox/agents, que lista a equipe da conta com os e-mails, responde 403 para ela.