Requisitos
Necesitas ser propietario o administrador de la cuenta y tener un sistema capaz de hacer solicitudes HTTPS. La API está disponible para las cuentas de Eva; cada llave pertenece a una sola cuenta.Qué se sincroniza
También puedes buscar registros y leer o añadir notas en oportunidades.
La API no elimina registros, no crea campos ni ofrece un
external_id propio. Guarda el id de Eva en tu sistema. Las llamadas a la API no consumen créditos.
Conectar
- Abre Ajustes → Integraciones → API de Eva y selecciona Crear llave.
- Escribe un nombre que identifique tu sistema y elige Solo lectura (
crm:read) o Lectura y escritura (crm:write). Una llave de escritura también puede leer. - Copia la llave
eva_sk_…en ese momento. Eva solo muestra el valor completo una vez. Guárdalo como secreto en el servidor de tu sistema; no lo pongas en una página web pública.
Authorization usa el formato Bearer <llave>. Envía un User-Agent real para que Cloudflare acepte la solicitud:
created: true para un contacto nuevo o false para uno ya encontrado. Usa GET /fields?entity=contact para conocer las claves válidas. Para campos de oportunidades, agrega entity=opportunity&pipeline_id=<id>.
source es Origen del contacto y va al nivel principal del JSON, no dentro de fields. Eva elimina espacios al principio y al final; acepta hasta 128 caracteres y rechaza una cadena vacía con 422. En POST, el origen llena un contacto encontrado solo si su origen estaba vacío; enviar null no lo cambia. PATCH /contacts/{id} con {"source":"Feria"} reemplaza el origen y con {"source":null} lo borra. Las respuestas de contacto incluyen source. Acepta cualquier otro texto, incluidas las opciones de origen del panel como website, referral o meta_ads. Solo estos valores de sistema, sin distinguir mayúsculas, devuelven 422 invalid_source: capture, personal_whatsapp_import, tokko_import, shopify y cualquiera que empiece con connected:. Si el origen guardado es uno de esos valores de sistema, PATCH con source devuelve 422 invalid_source y POST no lo cambia. Un mensaje entrante de WhatsApp conserva un origen ya registrado.
Endpoints y prueba
Todos empiezan por/api/v1/public/crm. Usa GET /contacts, GET /contacts/{id}, POST /contacts, PATCH /contacts/{id}, sus equivalentes /opportunities, y GET /fields, GET /owners, GET /pipelines. Las listas aceptan updated_since en ISO 8601, limit de 1 a 100 y un cursor opaco de la respuesta anterior. Las oportunidades también aceptan pipeline_id y stage_id. Para POST /opportunities, envía Idempotency-Key: <identificador-unico> y reutiliza el mismo valor en cada reintento; Eva respeta un reintento de la misma solicitud durante 30 días. POST /contacts necesita correo o teléfono: si alguno ya pertenece a un contacto, Eva actualiza ese contacto en lugar de crear otro.
Busca por nombre, correo, teléfono o campos de contacto marcados para búsqueda; en oportunidades, por título o contacto vinculado. q se recorta y debe tener entre 2 y 100 caracteres; type es contact u opportunity; limit va de 1 a 25. La respuesta contiene type y data con los mismos campos que las lecturas de contactos u oportunidades:
GET /opportunities/{id}/notes?limit=50 y pasa next_cursor como cursor para la página siguiente. Llegan de la más reciente a la más antigua. author.kind identifica api_key, member o system; author.name muestra el nombre de la llave o del miembro.
replayed: true; una solicitud distinta con esa clave devuelve 409.
Prueba primero GET /owners: 200 confirma que la llave funciona y muestra los miembros activos; 401 indica una llave ausente, inválida o revocada; 403 indica que faltan permisos para la operación.
Avisos de cambios
Configura Webhook personalizado en Integraciones con la URL HTTPS de tu sistema y un secreto de firma. Sus envíos incluyenX-Eva-Event-Id y, cuando hay secreto de firma, X-Eva-Timestamp y X-Eva-Signature-256. Verifica la firma antes de procesar el cuerpo y deduplica por ID de evento. Los eventos de cada registro llevan un revision creciente y pueden llegar en otro orden: conserva el de revision más alto por registro. Los cambios hechos por la API llegan con source: "api". El webhook es una conexión separada de la llave API; revocar la llave no desconecta el webhook.
Citas de Eva en tu CRM
GET /appointments devuelve las citas vinculadas a un contacto u oportunidad y GET /appointments/{id} devuelve una cita. Cada registro incluye su ID de Eva, eva_contact_id y eva_opportunity_id (cualquiera puede ser null, pero al menos uno es válido), inicio y fin en UTC, zona horaria, ubicación, responsable, status (active o cancelled) y updated_at; no incluye título ni notas. Por ejemplo, una cita vinculada solo a un contacto lleva "eva_contact_id": "44444444-4444-4444-8444-444444444444", "eva_opportunity_id": null. Una cancelación sigue disponible aunque Eva haya borrado la cita. La lista usa limit de 1 a 100, updated_since con zona horaria y el cursor de la página anterior. Recorre todas las páginas y solapa unos minutos entre lecturas incrementales. Estas rutas son de solo lectura: tu sistema no puede cambiar las citas de Eva.
Para recibir avisos, activa Citas → salida en Webhook personalizado. Empieza desactivado y requiere un secreto de firma. appointment.upserted lleva el mismo objeto que GET /appointments/{id}. status: "cancelled" indica que debes marcar la cita como cancelada en tu CRM. Verifica la firma HMAC-SHA256 sobre los bytes exactos de <X-Eva-Timestamp>.<cuerpo>, deduplica por X-Eva-Event-Id y aplica solo la revisión más alta de cada cita. Si pierdes un aviso, recupera con la lista paginada; al activar el webhook no se reenvían citas históricas.
Revocar y errores
En API de Eva, selecciona Revocar junto a la llave. La siguiente llamada con ella devuelve401. Los registros creados permanecen. Para cambiar permisos, crea otra llave y revoca la anterior cuando tu sistema ya use la nueva.
Privacidad y límites
Cada llave solo accede a su cuenta. El secreto se guarda como hash; Eva conserva el nombre, los permisos y la fecha del último uso. El límite es 120 solicitudes por minuto por llave. Usa paginación yupdated_since para leer cambios sin recorrer toda la cuenta en cada ciclo.