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
ConversationUpdatedeMessageUpsertede 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
}
}'