ZynzapAPI

n8n, Make e Zapier

Conecte o Zynzap a ferramentas de automação sem código, recebendo eventos por webhook e chamando a API com o nó de requisição HTTP.

A integração tem duas pontas, iguais nas três ferramentas:

  • Gatilho: um webhook da ferramenta recebe os eventos do Zynzap (mensagem recebida, status, conversa).
  • Ação: um nó de requisição HTTP chama a API (cotar e enviar, criar contato, mover oportunidade).

Crie uma chave só para a automação, com o mínimo de permissões (por exemplo events:read, product:inbox, messages:send), e guarde-a nas credenciais da ferramenta, nunca em texto aberto num nó.

Gatilho: receber eventos

  1. Crie o gatilho de webhook da ferramenta e copie a URL de produção (HTTPS público):
    • n8n: nó Webhook, método POST, Respond = Immediately, código 204.
    • Make: módulo Webhooks → Custom webhook.
    • Zapier: Webhooks by Zapier → Catch Raw Hook (o "raw" mantém o corpo bruto para conferir a assinatura).
  2. No painel do Zynzap, cadastre essa URL como webhook da chave e escolha os eventos.
  3. Clique em Enviar teste: o webhook.ping aparece na ferramenta e serve de amostra para mapear os campos.

Conferir a assinatura

Confira X-Zynzap-Signature antes de agir, principalmente se a automação envia mensagens ou altera dados. No n8n, ative Raw Body no nó Webhook e use um nó Code:

// n8n, nó Code ("Run Once for Each Item"). Requer o corpo bruto no nó Webhook (Options → Raw Body)
// e a variável de ambiente ZYNZAP_WEBHOOK_SECRET liberada para nós de código.
const crypto = require("crypto");

const headers = $json.headers;
const raw = Buffer.from($binary.data.data, "base64").toString("utf8");
const ts = headers["x-zynzap-timestamp"] ?? "";
const expected = crypto
  .createHmac("sha256", $env.ZYNZAP_WEBHOOK_SECRET)
  .update(`${ts}.${raw}`)
  .digest("hex");
const valid =
  /^\d+$/.test(ts) &&
  Math.abs(Date.now() / 1000 - Number(ts)) <= 300 &&
  (headers["x-zynzap-signature"] ?? "").split(",").some((part) => part.trim() === `v1=${expected}`);
if (!valid) throw new Error("Assinatura do Zynzap inválida");
return { json: JSON.parse(raw) };

No Make, o webhook personalizado não expõe o corpo bruto de forma confiável. Use uma URL difícil de adivinhar, filtre por X-Zynzap-Event-Type e, para ações sensíveis, passe o evento por uma função sua (por exemplo, uma função serverless com o código de Webhooks) antes do cenário.

Filtrar o que interessa

Use um filtro/roteador da ferramenta logo depois do gatilho:

  • type igual a MessageUpserted;
  • data.MessageUpserted.message.direction igual a inbound;
  • data.MessageUpserted.automation_eligible igual a true.

Ação: chamar a API

Configure o nó HTTP (HTTP Request no n8n, HTTP → Make a request no Make, Webhooks by Zapier → Custom Request no Zapier):

CampoValor
MétodoPOST
URLhttps://api.zynzap.com.br/v1/rpc/NomeDaOperacao
CabeçalhosAuthorization: Bearer <sua chave> (pela credencial), Content-Type: application/json
Corpo (JSON){"request": { ... }}

Exemplo: criar o contato de quem escreveu.

curl -X POST "https://api.zynzap.com.br/v1/rpc/CreateContact" \
  -H "Authorization: Bearer $ZYNZAP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "request": {
    "name": "Ana Souza",
    "phone": "5511987654321",
    "tags": [
      "lead-whatsapp"
    ]
  }
}'

Enviar uma resposta (duas chamadas)

Envios são pagos e pedem uma cotação antes. Faça dois nós HTTP em sequência: o primeiro cota, o segundo envia com o quoteId devolvido.

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": "Recebemos seu pedido! Já vamos responder.",
    "idempotency_key": "n8n-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": "Recebemos seu pedido! Já vamos responder.",
    "idempotency_key": "n8n-7e6d5c4b-3a29-4180-9f8e-7d6c5b4a3928"
  },
  "billing": {
    "quoteId": "0b8f2c1e-3a4d-4e5f-8a9b-1c2d3e4f5a6b"
  }
}'

No segundo nó, o corpo é o mesmo request do primeiro mais "billing": {"quoteId": "{{ $json.quoteId }}"} (n8n) ou o campo mapeado equivalente no Make/Zapier. Use idempotency_key com o id da mensagem recebida para que reexecuções da automação não respondam duas vezes.

Dicas

  • Prefira respostas pela conversa (SendConversationMessage): dentro de 24 horas da última mensagem do cliente elas saem de graça.
  • Configure novas tentativas da ferramenta só para 429 e 503, nunca para 4xx de validação.
  • Ferramentas que reexecutam cenários podem repetir eventos: o id do evento e o idempotency_key evitam duplicidade.
  • Para menus e atendimento automático completo, avalie os Fluxos do painel antes de montar tudo na ferramenta externa.