ZynzapAPI

Receber mensagens

Receba as mensagens dos clientes por webhook, entenda o evento e responda pela conversa, de graça dentro da janela de 24 horas.

1. Escolha os eventos

Crie (ou use) uma chave com events:read, product:inbox e messages:send e cadastre um webhook com:

EventoPara quê
MessageUpsertedMensagem gravada no histórico do atendimento, com conversation_id. O melhor para responder.
MessageReceivedToda mensagem que chega no número (inclusive de grupos), no formato bruto do WhatsApp.
MessageStatusUpdatedEntregue, lida, reproduzida (para as suas mensagens).

2. Entenda o evento

MessageUpserted (resumido)
{
  "id": "6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
  "type": "MessageUpserted",
  "cursor": "1042",
  "session_id": "8c1f7a52-4d1e-4b8a-9a43-2f6f5d0c9e11",
  "data": {
    "MessageUpserted": {
      "session_id": "8c1f7a52-4d1e-4b8a-9a43-2f6f5d0c9e11",
      "conversation_id": "5f0e1d2c-3b4a-4596-8877-66554433aa11",
      "automation_eligible": true,
      "message": {
        "id": "7e6d5c4b-3a29-4180-9f8e-7d6c5b4a3928",
        "direction": "inbound",
        "message_type": "text",
        "body": "Qual o horário de vocês?",
        "sender_jid": "[email protected]",
        "media": null
      }
    }
  }
}
  • direction: inbound (cliente) ou outbound (você, o painel, campanhas, bots). Para responder, filtre inbound.
  • message_type: text, image, video, audio, voice, document, sticker, reaction, revoked ou unsupported. Em mídias, caption e media vêm preenchidos (baixe com GetConversationMediaUrl).
  • automation_eligible: true só para mensagem recebida de terceiro em conversa individual (nunca grupos, nem mensagens suas ou de outro aparelho). Use como filtro para automações.
  • O evento também é emitido quando a mensagem muda (status, edição, revogação). Responda uma vez por message.id.
export function inboundText(event) {
  if (event.type !== "MessageUpserted") return null;
  const upsert = event.data.MessageUpserted;
  const message = upsert.message;
  if (message.direction !== "inbound" || !upsert.automation_eligible) return null;
  return {
    sessionId: upsert.session_id,
    conversationId: upsert.conversation_id,
    messageId: message.id,
    from: message.sender_jid,
    text: message.body ?? message.caption ?? "",
    type: message.message_type,
  };
}

3. Responda pela conversa

Cote e envie com SendConversationMessage. Se o cliente escreveu nas últimas 24 horas, a cotação volta com coverage: "inbox_window" e custo zero. Use idempotency_key derivada do id da mensagem recebida: se o seu webhook receber o mesmo evento duas vezes, a resposta não é enviada duas vezes.

curl -X POST "https://api.zynzap.com.br/v1/billing/quotes" \
  -H "Authorization: Bearer $ZYNZAP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "method": "SendConversationMessage",
  "request": {
    "conversation_id": "5f0e1d2c-3b4a-4596-8877-66554433aa11",
    "session_id": "8c1f7a52-4d1e-4b8a-9a43-2f6f5d0c9e11",
    "message_type": "text",
    "text": "Atendemos de segunda a sexta, das 9h às 18h.",
    "idempotency_key": "reply-7e6d5c4b-3a29-4180-9f8e-7d6c5b4a3928"
  }
}'
curl -X POST "https://api.zynzap.com.br/v1/rpc/SendConversationMessage" \
  -H "Authorization: Bearer $ZYNZAP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "request": {
    "conversation_id": "5f0e1d2c-3b4a-4596-8877-66554433aa11",
    "session_id": "8c1f7a52-4d1e-4b8a-9a43-2f6f5d0c9e11",
    "message_type": "text",
    "text": "Atendemos de segunda a sexta, das 9h às 18h.",
    "idempotency_key": "reply-7e6d5c4b-3a29-4180-9f8e-7d6c5b4a3928"
  },
  "billing": {
    "quoteId": "0b8f2c1e-3a4d-4e5f-8a9b-1c2d3e4f5a6b"
  }
}'

4. Marque como lida (opcional)

curl -X POST "https://api.zynzap.com.br/v1/rpc/MarkConversationRead" \
  -H "Authorization: Bearer $ZYNZAP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "request": {
    "conversation_id": "5f0e1d2c-3b4a-4596-8877-66554433aa11"
  }
}'

Sem webhook: histórico e stream

  • Consulte as conversas com ListConversations (filtre unread_only: true) e o histórico com ListMessages.
  • Ou mantenha um processo no stream /events.
curl -X POST "https://api.zynzap.com.br/v1/rpc/ListConversations" \
  -H "Authorization: Bearer $ZYNZAP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "request": {
    "unread_only": true,
    "limit": 20
  }
}'

Próximo passo: junte tudo num bot simples.