ZynzapAPI

Sincronizar com um CRM externo

Mantenha contatos, etiquetas e oportunidades do Zynzap alinhados com o seu CRM ou ERP, nos dois sentidos.

Um desenho que funciona bem:

  • Do seu CRM para o Zynzap: quando um cliente é criado ou alterado no CRM, crie/atualize o contato no Zynzap (CreateContact / UpdateContact) e ajuste etiquetas e campos.
  • Do Zynzap para o seu CRM: ouça os webhooks ConversationUpdated e MessageUpserted e grave no CRM o que importa (última conversa, responsável, oportunidade).
  • Carga inicial e conciliação: percorra os contatos com paginação por cursor.

Permissões: product:contacts (contatos e CRM da empresa inteira) e events:read para os webhooks. Guarde o id do contato do Zynzap no seu CRM e o id do seu CRM no campo extra do contato do Zynzap.

1. Criar ou atualizar o contato

Procure pelo telefone antes de criar (evita CONTACT_ALREADY_EXISTS):

curl -X POST "https://api.zynzap.com.br/v1/rpc/ListContacts" \
  -H "Authorization: Bearer $ZYNZAP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "request": {
    "search": "5511987654321",
    "limit": 1
  }
}'

Não achou? Crie, guardando o id do seu CRM em extra:

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",
    "email": "[email protected]",
    "tags": [
      "cliente"
    ],
    "extra": {
      "crm_id": "CRM-4821"
    }
  }
}'

Achou? Atualize pelo id:

curl -X POST "https://api.zynzap.com.br/v1/rpc/UpdateContact" \
  -H "Authorization: Bearer $ZYNZAP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "request": {
    "id": "9a8b7c6d-5e4f-4321-8765-1a2b3c4d5e6f",
    "name": "Ana Souza",
    "phone": "5511987654321",
    "email": "[email protected]",
    "tags": [
      "cliente",
      "vip"
    ],
    "extra": {
      "crm_id": "CRM-4821"
    }
  }
}'

2. Etiquetas e campos do CRM

Etiquetas do CRM do Zynzap têm id (liste com ListCrmTags). Para aplicar ou remover em lote:

curl -X POST "https://api.zynzap.com.br/v1/rpc/ChangeCrmTags" \
  -H "Authorization: Bearer $ZYNZAP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "request": {
    "contact_ids": [
      "9a8b7c6d-5e4f-4321-8765-1a2b3c4d5e6f"
    ],
    "add_tag_ids": [
      "1f2e3d4c-5b6a-4789-8a9b-0c1d2e3f4a5b"
    ],
    "remove_tag_ids": [],
    "source": "crm-sync"
  }
}'

Temperatura, qualificação, responsável e campos personalizados (crie os campos com SaveCrmFieldDef):

curl -X POST "https://api.zynzap.com.br/v1/rpc/UpdateContactCrm" \
  -H "Authorization: Bearer $ZYNZAP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "request": {
    "contact_id": "9a8b7c6d-5e4f-4321-8765-1a2b3c4d5e6f",
    "temperature": "quente",
    "fields": {
      "plano_contratado": "Pro"
    },
    "source": "crm-sync"
  }
}'

3. Oportunidades

Liste funis e etapas uma vez (ListCrmPipelines) e crie a oportunidade no funil certo. Valores em centavos.

curl -X POST "https://api.zynzap.com.br/v1/rpc/CreateCrmOpportunity" \
  -H "Authorization: Bearer $ZYNZAP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "request": {
    "contact_id": "9a8b7c6d-5e4f-4321-8765-1a2b3c4d5e6f",
    "pipeline_id": "2b3c4d5e-6f70-4812-9a3b-4c5d6e7f8091",
    "stage_id": "3c4d5e6f-7081-4923-8b4c-5d6e7f809102",
    "title": "Plano Pro anual",
    "value_cents": "478800",
    "currency": "BRL",
    "source": "crm-sync"
  }
}'

Para mover de etapa, ganhar ou perder, use MoveCrmOpportunity (perder exige um motivo de perda, CRM_LOSS_REASON_REQUIRED).

4. Do Zynzap para o CRM

Assine ConversationUpdated (status, responsável, não lidas) e MessageUpserted (mensagens) no webhook. Exemplo de reação:

// Chamado pelo seu endpoint de webhook depois de conferir a assinatura.
export async function onZynzapEvent(event, crm) {
  if (event.type === "ConversationUpdated") {
    const conversation = event.data.ConversationUpdated.conversation;
    if (!conversation.contact_id) return;
    await crm.updateByZynzapId(conversation.contact_id, {
      lastConversationStatus: conversation.status,
      lastMessageAt: new Date(conversation.last_message_at_unix_ms ?? Date.now()),
      assignee: conversation.assignee_user_id,
    });
  }
}

Conciliação noturna

Webhooks podem atrasar ou ficar desativados após falhas. Uma vez por dia, percorra ListContacts e ListCrmOpportunities com cursor e corrija diferenças; para eventos, use ReplayEvents a partir do último cursor gravado.

curl -X POST "https://api.zynzap.com.br/v1/rpc/ListCrmOpportunities" \
  -H "Authorization: Bearer $ZYNZAP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "request": {
    "limit": 200
  }
}'