Sincronizar contactos con tu CRM
Creá o actualizá contactos sin duplicarlos, guardá datos propios en campos personalizados, leé sus etiquetas y traé la base completa página por página.
Vas a mantener los contactos de Funnelchat alineados con tu CRM. Usa Crear o actualizar un contacto para escribir sin duplicar, Listar campos personalizados y Asignar un campo personalizado a contactos para tus datos propios, Listar las etiquetas de un contacto para su segmento y Listar contactos para recorrer la base.
Al terminar esta guía, cada alta o cambio en tu CRM se refleja en Funnelchat con un solo contacto por teléfono, con sus campos personalizados cargados, y tu CRM conoce las etiquetas de cada contacto y la base completa de la cuenta.
Antes de empezar
- Una clave con
conversations:writeyconversations:read. Escribir, para crear contactos y cargar campos; leer, para listar. Si todavía no tenés una, seguí la guía rápida. - La clave en la variable
FC_API_KEY, entre comillas si la guardás en un.env(lleva un|). - El teléfono de cada contacto con código de país. Es lo que identifica al contacto en esta sincronización.
1. Creá o actualizá el contacto
Crear o actualizar un contacto busca el contacto por phone: si existe lo actualiza, si no lo crea. Es la opción segura para reintentos: llamarla dos veces con el mismo teléfono no duplica. Acepta phone (obligatorio), name y email, y pide conversations:write.
curl -X POST "https://api.funnelchat.com/api/v1/contacts/update-or-create" \
-H "Authorization: Bearer $FC_API_KEY" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"phone": "5491100000000",
"name": "Ana Pérez",
"email": "ana@example.com"
}'Respuesta de ejemplo (recortada a algunos campos):
{
"id": 102578466,
"name": "Ana Pérez",
"email": "ana@example.com",
"phone": "5491100000000",
"whatsapp_id": "",
"has_phone": true,
"country_code": "",
"status": 1,
"created_at": "2026-10-04T21:23:45.000000Z",
"active_conversation": 0,
"unread_messages": 0
}- Tratá
200y201como éxito. En las pruebas del 04-10 respondió201al crear el contacto y200cuando ya existía, con el mismoid; la especificación documenta solo200(conocido en v0). - El teléfono, con o sin
+. Los dos encuentran el mismo contacto, y la API lo guarda sin+(detalle). - Guardá el
iden tu CRM. Lo piden los pasos siguientes. Para otros datos de la ficha (notas, asesor, favorito), usá Actualizar un contacto con eseid.
2. Encontrá el campo personalizado
Los campos personalizados guardan datos propios de tu negocio, como plan, ciudad o fecha de compra. Para cargar un valor necesitás el id del campo: buscalo por nombre con Listar campos personalizados y quedate con el que coincida exacto.
curl -G "https://api.funnelchat.com/api/v1/custom-fields" \
--data-urlencode "name=plan" \
--data-urlencode "perPage=100" \
-H "Authorization: Bearer $FC_API_KEY" \
-H "Accept: application/json"Respuesta de ejemplo (recortada, sin links ni meta):
{
"data": [
{
"id": 3101,
"name": "plan",
"type": 0,
"description": null,
"created_at": "2026-09-01T10:00:00.000000Z"
}
]
}Si el campo no existe
Crealo con Crear un campo personalizado (name y type, obligatorios). type es un entero de 0 a 4 cuyo significado la especificación no documenta, y no se puede cambiar después. Para elegirlo, mirá el type de un campo existente del mismo tipo de dato en la respuesta de arriba.
3. Guardá el valor en el contacto
Asignar un campo personalizado a contactos recibe una lista: cada elemento lleva customFieldId, contactId y value (texto). Podés cargar varios campos y varios contactos en una sola llamada.
curl -X POST "https://api.funnelchat.com/api/v1/contacts/attach-custom-field" \
-H "Authorization: Bearer $FC_API_KEY" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '[
{ "customFieldId": 3101, "contactId": 102578466, "value": "Premium" }
]'Respuesta de ejemplo (según la especificación, un resultado por elemento):
[
{
"message": "Custom field value attached successfully.",
"status": 201
}
]Un elemento con status: 403 trae en message si el campo o el contacto no son de tu cuenta. Para borrar un valor, usá Quitar un campo personalizado de contactos.
4. Leé las etiquetas del contacto
Para reflejar en tu CRM el segmento de cada contacto, Listar las etiquetas de un contacto devuelve sus etiquetas, paginadas con perPage.
curl -G "https://api.funnelchat.com/api/v1/contacts/102578466/tags" \
--data-urlencode "perPage=100" \
-H "Authorization: Bearer $FC_API_KEY" \
-H "Accept: application/json"Respuesta de ejemplo (recortada, sin links ni meta; … marca valores cuyo formato la especificación no documenta):
{
"data": [
{
"id": 4001,
"name": "Cliente",
"description": "",
"color": "…",
"assigned_at": "…"
}
]
}Asignar etiquetas no está abierto a claves
Con una clave podés crear etiquetas (Crear una etiqueta) y leerlas, pero no agregárselas ni quitárselas a un contacto: contacts/add-tags y contacts/remove-tags responden 403 route_not_available con cualquier permiso, porque una etiqueta puede disparar un flujo que manda mensajes (Qué está abierto a claves). Hoy las etiquetas viajan de Funnelchat a tu CRM, no al revés.
5. Traé todos los contactos
Para la carga inicial, o para reconciliar, recorré Listar contactos página por página:
- Mandá siempre
perPage(hasta 100) y un orden estable, comoorderBy=idconorderByMethod=asc. - Para la página siguiente, seguí
links.next: conservaperPagey los filtros de tu consulta. - Pará cuando
links.nextseanull(o cuandometa.current_pagellegue ameta.last_page).
Para traer solo una parte, sumá filtros como created_from (fecha de alta) o tag_ids[] con tag_mode (all, any o exclude).
curl -G "https://api.funnelchat.com/api/v1/contacts" \
--data-urlencode "perPage=100" \
--data-urlencode "page=1" \
--data-urlencode "orderBy=id" \
--data-urlencode "orderByMethod=asc" \
-H "Authorization: Bearer $FC_API_KEY" \
-H "Accept: application/json"Respuesta de ejemplo (recortada a un contacto y sin links):
{
"data": [
{
"id": 102578466,
"name": "Ana Pérez",
"email": "ana@example.com",
"phone": "5491100000000",
"has_phone": true,
"status": 1,
"created_at": "2026-10-04T21:23:45.000000Z"
}
],
"meta": {
"current_page": 1,
"from": 1,
"last_page": 5,
"path": "https://api.funnelchat.com/api/v1/contacts",
"per_page": 100,
"to": 100,
"total": 419
}
}Enterate de los cambios sin consultar en bucle
Con el receptor de Recibir los mensajes de WhatsApp en tu sistema, suscribite en conversations a contact.created (un contacto nuevo), contact.tag_added y contact.tag_removed (cambió una etiqueta). contact.created llega por cualquier canal, también por los contactos que crea tu propia integración: si tu CRM escribe y escucha a la vez, evitá el eco. Los payloads están en el catálogo de eventos.
Si falla
| Qué ves | Qué pasó | Qué hacer |
|---|---|---|
401 | Falta la clave, no existe o fue revocada. | Revisá la cabecera Authorization: Bearer con la clave completa. |
403 con error: "permission_denied" | A la clave le falta el permiso: conversations:write para crear y cargar campos, conversations:read para listar. | Creá una clave con ese permiso. message dice cuál falta. |
403 con error: "route_not_available" | La ruta no está abierta a claves en el piloto, como contacts/add-tags. | No hay permiso que pedir: ninguna clave la habilita. |
422 | La validación falló: falta phone, email no es un email, perPage está fuera de 1 a 100 o el orden no es uno de los admitidos. | errors dice qué campo o parámetro corregir. |
404 al crear o actualizar | La especificación lo documenta con message «Contacto no encontrado.», sin detallar el caso. | Revisá el phone que mandaste. |
200 con elementos en status: 403 | Al asignar campos, el campo o el contacto de ese elemento no es de tu cuenta. | Revisá los id de ese elemento. Cada elemento trae su propio resultado: los que vienen con 201 se guardaron. |
503 | El portero no pudo evaluar la llamada (gate_unavailable). | Esperá lo que indica Retry-After y reintentá. Crear o actualizar se puede reintentar sin duplicar. |
El detalle de los códigos está en Errores.
Relacionado
- Mover un lead de etapa en un tablero: reflejá el avance de cada contacto en tu embudo.
- Leer conversaciones e historial de mensajes: qué conversó cada contacto.
- Listar los contactos con una etiqueta: exportá un segmento completo.
- Listar etiquetas: los
idde las etiquetas de la cuenta, para filtrar contag_ids[]. - Conocido en v0: diferencias ya identificadas entre las especificaciones y lo que responde la API.
Enviar mensajes
Mandar un mensaje con tu clave, saber qué pasó con él y qué hacer cuando una regla de WhatsApp lo frena o la llamada no responde.
Mover un lead de etapa en un tablero
Cuando algo pasa en tu sistema, como un pago o una demo agendada, mové al contacto a la etapa que corresponde y enterate de cada cambio de etapa.