Contactos
Referencia de las rutas de contactos: la lista de todas las personas que ya hablaron con la central, con búsqueda y sincronización incremental, la consulta de un contacto con todas sus atenciones y el cambio del nombre que ve el equipo. Con el criterio de agrupación por teléfono (con y sin el noveno dígito), ejemplos en curl, PHP y Python y los errores de cada ruta.
Visión general
En ChatISP no existe un registro de contactos separado que mantener: el contacto es el conjunto de todas las conversaciones de un mismo teléfono, en cualquier número de WhatsApp de la empresa. Es la misma vista de la pantalla Contactos del panel (todos los contactos que ya pasaron por la central, con el historial de atenciones). Un contacto aparece en cuanto se crea la primera conversación con ese teléfono, ya sea porque el cliente escribió o por un envío o una apertura por la API.
| Ruta | Método | Permiso de la clave | Resumen |
|---|---|---|---|
contatos/listar | GET o POST | Contactos | Lista paginada, con búsqueda por nombre o teléfono y filtro de actividad reciente. |
contatos/consultar | GET o POST | Contactos | Un contacto, con el cliente identificado, los totales y las últimas 50 conversaciones. |
contatos/renomear | POST | Contactos | Guarda el nombre del contacto, en todas sus conversaciones y en las próximas. |
Casos típicos: alimentar el CRM con todos los números que ya buscaron al proveedor de internet, mostrar en el ERP cuántas atenciones tuvo el suscriptor, corregir en ChatISP el nombre del cliente a partir del registro oficial.
El permiso Contactos es independiente: una clave solo con Consultar conversaciones no lista contactos (403 permissao), y viceversa. La clave ve los contactos de toda la empresa; la restricción de historial de los perfiles de agente no se aplica a la API.
Un contacto por teléfono
El teléfono es la identidad del contacto. Dos detalles importan para quien integra:
- Con y sin el noveno dígito son el mismo contacto. El WhatsApp de algunos celulares brasileños todavía llega con 8 dígitos después del código de área. ChatISP une
5544999990000y554499990000en un solo contacto, tanto en la lista como en la consulta y en el cambio de nombre. Puede buscar por cualquiera de las dos formas. - Todas las conexiones juntas. Las conversaciones del mismo teléfono en números de WhatsApp diferentes de la empresa (por ejemplo, el número de soporte y el comercial) forman un solo contacto.
El campo telefone devuelto es el de la conversación más reciente del contacto, en la forma en que WhatsApp lo entregó, solo dígitos y con el código de país. Al guardarlo en su sistema, normalice los dos formatos brasileños a la misma clave, como hace ChatISP, para no duplicar al cliente.
| Teléfonos en las conversaciones | Contactos en la API |
|---|---|
5544999990000 y 554499990000 | Uno solo (celular brasileño, con y sin el noveno dígito). |
5544999990000 en soporte y en comercial | Uno solo (mismo teléfono, conexiones diferentes). |
351912345678 (Portugal) | Los números de otros países no se agrupan: cada forma es un contacto. |
Objeto contacto
{
"telefone": "5544999990000",
"nome": "Maria Souza",
"atendimentos": 7,
"abertos": 1,
"primeiro_contato_em": "2025-03-14T16:20:05-03:00",
"ultimo_contato_em": "2026-10-01T09:41:03-03:00",
"cliente": { "nome": "MARIA APARECIDA SOUZA", "origem": "IXC" }
}| Campo | Tipo | Descripción |
|---|---|---|
telefone | string | Teléfono de la conversación más reciente del contacto, solo dígitos, con el código de país. |
nome | string | Nombre como aparece en la atención: el guardado por el equipo (o por contatos/renomear) o, sin él, el nombre del perfil de WhatsApp. Vacío cuando es desconocido. |
atendimentos | entero | Total de conversaciones (protocolos) del contacto, abiertas y cerradas, incluidos los avisos enviados. |
abertos | entero | Cuántas de esas conversaciones están abiertas ahora. Solo en contatos/listar. |
primeiro_contato_em, ultimo_contato_em | fecha y hora | Apertura de la primera conversación y última actividad (último mensaje o, sin mensajes, la apertura de la conversación más reciente). Solo en contatos/listar. |
cliente | objeto o null | El cliente identificado en el ERP o en un sistema externo integrado, como aparece en la tarjeta del cliente durante la atención: nome (el del registro) y origem (el nombre del ERP o del sistema externo que lo identificó). null cuando ninguna conversación del contacto llegó a identificar un cliente. |
tickets | entero | Total de órdenes de servicio registradas para ese teléfono, en cualquier etapa (incluidos los concluidos). Solo en contatos/consultar. |
nome y cliente.nome son cosas diferentes: el primero es cómo el equipo llama a la persona en WhatsApp (puede ser un apodo, o el nombre de quien usa el teléfono); el segundo es el titular del registro en el ERP. Vea Ficha del cliente.
Listar contactos
/api_publica.php?r=contatos/listar
Lista paginada de los contactos, del que tuvo actividad más reciente al más antiguo.
Permiso: Contactos.
| Parámetro | Tipo | Descripción |
|---|---|---|
busca | string | Hasta 120 caracteres. Busca en cualquier parte del nombre del contacto (el de las conversaciones y el guardado por el equipo) y, cuando el texto tiene dígitos, en cualquier parte del teléfono. Maria, souza y 99999 funcionan. |
atualizados_desde | fecha | Solo contactos con actividad (conversación abierta o mensaje intercambiado) a partir de ese momento. Acepta ISO 8601, AAAA-MM-DD o AAAA-MM-DD HH:MM:SS; sin zona horaria, vale la zona horaria del servidor. |
pagina, limite | entero | Paginación: pagina a partir de 1; limite de 1 a 100, predeterminado 50. |
Sincronizar con el CRM
- En la primera carga, recorra todas las páginas sin filtro.
- En las siguientes, use
atualizados_desdecon la hora de la ronda anterior menos un pequeño margen, y guarde cada contacto por la clave del teléfono (normalizado con y sin el noveno dígito, como en Un contacto por teléfono). - Para el detalle de un contacto modificado (cliente identificado, órdenes de servicio, conversaciones), llame a
contatos/consultar.
El orden de la lista es por la última actividad. Si llegan mensajes mientras recorre las páginas, un contacto puede subir a la página 1 y usted saltarse otro. En la sincronización, el margen en atualizados_desde lo resuelve en la ronda siguiente.
# búsqueda por nombre curl -s "https://atendimento.seuprovedor.com.br/api_publica.php?r=contatos/listar&busca=souza" \ -H "Authorization: Bearer $CHATISP_CHAVE" # quienes tuvieron actividad desde ayer, 100 por página curl -s "https://atendimento.seuprovedor.com.br/api_publica.php?r=contatos/listar&atualizados_desde=2026-09-30&limite=100" \ -H "Authorization: Bearer $CHATISP_CHAVE"
<?php // carga completa de los contactos para el CRM $pagina = 1; do { $ch = curl_init('https://atendimento.seuprovedor.com.br/api_publica.php?' . http_build_query([ 'r' => 'contatos/listar', 'limite' => 100, 'pagina' => $pagina, ])); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('CHATISP_CHAVE')], ]); $r = json_decode(curl_exec($ch), true); curl_close($ch); foreach ($r['contatos'] as $c) { gravarNoCrm($c['telefone'], $c['nome'], $c['atendimentos']); // su código } $pagina++; } while ($pagina <= $r['paginacao']['paginas']);
import os, requests r = requests.get("https://atendimento.seuprovedor.com.br/api_publica.php", params={ "r": "contatos/listar", "busca": "99999", "limite": 20, }, headers={"Authorization": "Bearer " + os.environ["CHATISP_CHAVE"]}, timeout=30) for c in r.json()["contatos"]: titular = c["cliente"]["nome"] if c["cliente"] else "(sin registro)" print(c["telefone"], c["nome"], titular, c["abertos"])
{
"ok": true,
"contatos": [
{
"telefone": "5544999990000",
"nome": "Maria Souza",
"atendimentos": 7,
"abertos": 1,
"primeiro_contato_em": "2025-03-14T16:20:05-03:00",
"ultimo_contato_em": "2026-10-01T09:41:03-03:00",
"cliente": { "nome": "MARIA APARECIDA SOUZA", "origem": "IXC" }
},
{
"telefone": "554498887777",
"nome": "Paulo",
"atendimentos": 1,
"abertos": 0,
"primeiro_contato_em": "2026-09-30T18:02:44-03:00",
"ultimo_contato_em": "2026-09-30T18:10:12-03:00",
"cliente": null
}
],
"paginacao": { "pagina": 1, "limite": 50, "total": 2, "paginas": 1 }
}Errores específicos: parametro_invalido (limite o pagina fuera de lo aceptado), data_invalida.
Consultar contacto
/api_publica.php?r=contatos/consultar
Devuelve un contacto con el cliente identificado, el total de atenciones y de órdenes de servicio y las 50 conversaciones más recientes, de la más nueva a la más antigua. Sirve para armar la ficha del suscriptor en el ERP o en el CRM: "este cliente ya habló 7 veces con la central; la última fue hoy, por lentitud".
Permiso: Contactos.
| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
telefone | string | Sí | Teléfono del contacto, en cualquiera de las formas (con o sin 55, con o sin el noveno dígito). Misma regla de las otras rutas. |
curl -s "https://atendimento.seuprovedor.com.br/api_publica.php?r=contatos/consultar&telefone=44999990000" \ -H "Authorization: Bearer $CHATISP_CHAVE"
<?php $ch = curl_init('https://atendimento.seuprovedor.com.br/api_publica.php?' . http_build_query([ 'r' => 'contatos/consultar', 'telefone' => '44999990000', ])); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('CHATISP_CHAVE')], ]); $r = json_decode(curl_exec($ch), true); $status = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($status === 404) { echo 'Este teléfono nunca habló con la central.', PHP_EOL; } else { echo $r['contato']['atendimentos'], ' atenciones, ', $r['contato']['tickets'], ' OS', PHP_EOL; foreach ($r['conversas'] as $c) { echo $c['protocolo'], ' ', $c['resumo']['titulo'] ?? '(sin resumen)', PHP_EOL; } }
import os, requests r = requests.get("https://atendimento.seuprovedor.com.br/api_publica.php", params={"r": "contatos/consultar", "telefone": "44999990000"}, headers={"Authorization": "Bearer " + os.environ["CHATISP_CHAVE"]}, timeout=30) if r.status_code == 404: print("Sin historial") else: dados = r.json() for c in dados["conversas"]: print(c["protocolo"], c["estado"], c["motivo_encerramento"])
{
"ok": true,
"contato": {
"telefone": "5544999990000",
"nome": "Maria Souza",
"cliente": { "nome": "MARIA APARECIDA SOUZA", "origem": "IXC" },
"atendimentos": 7,
"tickets": 2
},
"conversas": [
{
"id": 18342,
"protocolo": "20261001-0042",
"conexao_id": 1,
"telefone": "5544999990000",
"nome": "Maria Souza",
"estado": "encerrada",
"aguardando_cliente": false,
"departamento_id": 1,
"departamento": "Soporte técnico",
"atendente_id": 7,
"atendente": "Carlos Lima",
"nao_lidas": 0,
"motivo_encerramento": "Resuelto",
"resumo": {
"titulo": "Sin internet después de un corte de energía",
"texto": "La clienta informó falta de internet desde la mañana. El agente identificó la ONU sin señal y programó una visita técnica para la tarde."
},
"criada_em": "2026-10-01T09:12:40-03:00",
"ultima_mensagem_em": "2026-10-01T09:41:03-03:00",
"encerrada_em": "2026-10-01T09:42:15-03:00"
}
]
}contato.atendimentoscuenta todas las conversaciones del teléfono; la listaconversastrae como máximo las 50 más recientes. Para las anteriores, useconversas/listarcontelefoney paginación.- Las conversaciones vienen en el formato de conversación, sin el campo
etiquetas(consulte una conversación para obtenerlas). contato.telefoneycontato.nomevienen de la conversación más reciente.
Errores específicos: parametro_obrigatorio (falta telefone), telefone_invalido, nao_encontrado (404: el teléfono nunca tuvo conversación).
Renombrar contacto
/api_publica.php?r=contatos/renomear
Guarda el nombre del contacto, como la edición de nombre que el agente hace en el panel. Úselo para cambiar el apodo de WhatsApp ("Mamá", "Pepe del campo") por el nombre del registro del ERP, para que el equipo sepa con quién está hablando.
Permiso: Contactos.
| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
telefone | string | Sí | Teléfono del contacto. Debe tener al menos una conversación. |
nome | string | Sí | De 1 a 120 caracteres; los espacios en los extremos se eliminan. |
Efecto
- En el panel, en el momento: el nombre pasa a valer en todas las conversaciones del teléfono, abiertas y cerradas, en todos los números de WhatsApp de la empresa y en las dos formas del número (con y sin el noveno dígito). La lista de conversaciones, el kanban, el historial y la pantalla Contactos muestran el nombre nuevo.
- En las próximas conversaciones: toda conversación nueva de ese teléfono ya nace con el nombre guardado. Este prevalece sobre el nombre del perfil de WhatsApp y sobre el parámetro
nomede las rutas de envío y deatendimentos/abrir. - El nombre se usa también donde los mensajes automáticos usan
{nome}(por ejemplo, el mensaje de atención cerrada). - El registro del cliente en el ERP no se modifica: sigue apareciendo en
cliente.nome.
curl -s -X POST "https://atendimento.seuprovedor.com.br/api_publica.php?r=contatos/renomear" \
-H "Authorization: Bearer $CHATISP_CHAVE" \
-H "Content-Type: application/json" \
-d '{"telefone": "44999990000", "nome": "Maria Aparecida Souza"}'<?php $ch = curl_init('https://atendimento.seuprovedor.com.br/api_publica.php?r=contatos/renomear'); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('CHATISP_CHAVE'), 'Content-Type: application/json'], CURLOPT_POSTFIELDS => json_encode(['telefone' => '44999990000', 'nome' => 'Maria Aparecida Souza']), ]); $r = json_decode(curl_exec($ch), true); curl_close($ch);
import os, requests r = requests.post("https://atendimento.seuprovedor.com.br/api_publica.php", params={"r": "contatos/renomear"}, headers={"Authorization": "Bearer " + os.environ["CHATISP_CHAVE"]}, json={"telefone": "44999990000", "nome": "Maria Aparecida Souza"}, timeout=30) print(r.status_code, r.json())
{"ok": true, "telefone": "5544999990000", "nome": "Maria Aparecida Souza"}El telefone devuelto es el de la conversación más reciente del contacto. Errores específicos: parametro_obrigatorio (falta telefone), telefone_invalido, nome_invalido (vacío o de más de 120 caracteres), nao_encontrado (404: el teléfono nunca tuvo conversación; para registrar un número nuevo, abra una atención o envíe un mensaje antes).
Errores por ruta
Además de los errores generales (rota, autenticacao, chave_invalida, plano, cota_excedida, permissao, json_invalido), descritos en Códigos de error:
error | HTTP | listar | consultar | renomear |
|---|---|---|---|---|
metodo | 405 | sí | ||
parametro_invalido | 400 | sí | sí | sí |
data_invalida | 400 | sí | ||
parametro_obrigatorio | 400 | sí | sí | |
telefone_invalido | 400 | sí | sí | |
nome_invalido | 400 | sí | ||
nao_encontrado | 404 | sí | sí |