API Reference

La API REST de Zeph CRM permite integrar tus datos de leads, contactos, empresas, oportunidades y actividades con sistemas externos. Todas las peticiones usan JSON y requieren autenticación mediante API Key. La API no expone endpoints DELETE -- las eliminaciones se realizan desde la UI.

Base URL: https://www.zephcrm.com/api/v1

Autenticación

Todas las peticiones deben incluir un header Authorization con tu API key en formato Bearer token. Podes crear y administrar tus claves desde Settings > API Keys.

Header de autenticación
Authorization: Bearer vk_live_tu_api_key_aqui

Importante

  • Las API keys se muestran una sola vez al crearlas. Guardalas en un lugar seguro.
  • Cada key tiene scopes especificos (ej: leads:read, contacts:write). Solo podrás acceder a los endpoints para los que tengas permiso.
  • Nunca compartas tus claves ni las incluyas en código del lado del cliente.

Rate Limiting

Cada API key tiene un límite de 100 peticiones por minuto. Si excedes el límite, recibirás una respuesta 429 Too Many Requests.

Los headers de respuesta incluyen información sobre tu uso:

Headers de rate limit
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1706745600
Response 429
{
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Has excedido el limite de 100 peticiones por minuto. Intenta de nuevo en 42 segundos.",
    "retryAfter": 42
  }
}

Formato de respuesta

Todas las respuestas son JSON. Los formatos varian según el tipo de operación:

Respuesta exitosa (objeto)

200 OK
{
  "data": {
    "id": "clx1234...",
    "firstName": "Juan",
    "lastName": "Perez",
    "email": "juan@empresa.com",
    "createdAt": "2025-01-15T10:30:00.000Z",
    "updatedAt": "2025-01-15T10:30:00.000Z"
  }
}

Respuesta de error

400 / 401 / 403 / 404 / 422 / 500
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Los datos enviados no son validos.",
    "details": {
      "email": ["El email no es valido"],
      "firstName": ["Este campo es obligatorio"]
    }
  }
}

Respuesta paginada (lista)

200 OK
{
  "data": [
    { "id": "clx1...", "firstName": "Juan", ... },
    { "id": "clx2...", "firstName": "Maria", ... }
  ],
  "pagination": {
    "nextCursor": "clx2...",
    "hasMore": true,
    "total": 150
  }
}

Paginación

La API usa paginación basada en cursor para listas. Usa el campo nextCursor de la respuesta como parámetro cursor en la siguiente peticion.

Ejemplo de paginación
# Primera pagina
curl "https://www.zephcrm.com/api/v1/leads?limit=20" \
  -H "Authorization: Bearer vk_live_..."

# Segunda pagina (usar nextCursor de la respuesta anterior)
curl "https://www.zephcrm.com/api/v1/leads?limit=20&cursor=clx2abc..." \
  -H "Authorization: Bearer vk_live_..."

Leads

GET/api/v1/leadsleads:read

Lista todos los leads de tu organización con paginación y filtros.

Query Parameters

ParamTipoDescripción
cursorstringCursor para paginación (ID del último item)
limitnumberItems por pagina (default 20, max 100)
sortstringCampo por el que ordenar
orderasc | descDirección del orden (default desc)
searchstringBuscar en nombre, email, etc.
created_afterISO 8601Filtrar por fecha de creación
created_beforeISO 8601Filtrar por fecha de creación
statusstringFiltrar por status: NEW, CONTACTED, QUALIFIED, CONVERTED, LOST
contact_idstringLeads vinculados a alguno de estos contactos (ids separados por coma, hasta 100). Consultalo con el lote entero antes de promover, para no crearle dos leads a nadie
tagstringLeads con alguno de estos tags (separados por coma, sin distinguir mayúsculas). Repetir el parámetro exige todos
industrystringLeads cuya empresa vinculada tenga alguna de estas industrias (separadas por coma)
custom.<field>stringIgualdad exacta sobre un campo personalizado, ej. custom.pipeline_state=pending. a,b = cualquiera de los dos; varias claves se combinan con AND. true/false y los números encuentran también el booleano o el número guardado
sortstringCampo de orden (default createdAt). Con order=asc, los más viejos primero
curl
curl "https://www.zephcrm.com/api/v1/leads?limit=20&status=NEW&tag=fintech&custom.pipeline_state=pending" \
  -H "Authorization: Bearer vk_live_..."
Response
{
  "data": [
    {
      "id": "clx1abc...",
      "firstName": "Juan",
      "lastName": "Perez",
      "email": "juan@empresa.com",
      "phone": "+54 11 1234-5678",
      "company": "Acme SRL",
      "position": "Gerente Comercial",
      "status": "NEW",
      "notes": "Interesado en plan Enterprise",
      "customFields": {},
      "assignedToId": "clxuser1...",
      "source": "Zapier",
      "leadSourceId": "clxsrc1...",
      "leadSource": { "id": "clxsrc1...", "name": "Zapier" },
      "sourceDetail": "Typeform signup",
      "contactId": "clxc1...",
      "companyId": "clxco1...",
      "tags": [{ "id": "clxtag1...", "name": "fintech", "color": "#6b7280" }],
      "companyRef": {
        "id": "clxco1...",
        "name": "Acme SRL",
        "website": "https://acme.com",
        "employeeCount": 120,
        "industry": { "id": "clxind1...", "name": "Software" },
        "country": { "id": "clxctry1...", "name": "Argentina" }
      },
      "createdAt": "2025-01-15T10:30:00.000Z",
      "updatedAt": "2025-01-15T10:30:00.000Z"
    }
  ],
  "pagination": {
    "nextCursor": "clx1abc...",
    "hasMore": true,
    "total": 85
  }
}
GET/api/v1/leads/:idleads:read

Obtiene un lead por su ID.

curl
curl "https://www.zephcrm.com/api/v1/leads/clx1abc..." \
  -H "Authorization: Bearer vk_live_..."
Response
{
  "data": {
    "id": "clx1abc...",
    "firstName": "Juan",
    "lastName": "Perez",
    "email": "juan@empresa.com",
    "phone": "+54 11 1234-5678",
    "company": "Acme SRL",
    "position": "Gerente Comercial",
    "status": "NEW",
    "notes": "Interesado en plan Enterprise",
    "customFields": {},
    "assignedToId": "clxuser1...",
    "createdAt": "2025-01-15T10:30:00.000Z",
    "updatedAt": "2025-01-15T10:30:00.000Z"
  }
}
POST/api/v1/leadsleads:write

Crea un nuevo lead.

Request Body (JSON)

CampoTipoReqDescripción
firstNamestringSiNombre
lastNamestringSiApellido
emailstringNoEmail
phonestringNoTeléfono
companystringNoNombre de empresa
positionstringNoCargo
statusstringNoNEW (default), CONTACTED, QUALIFIED
notesstringNoNotas
customFieldsobjectNoCampos personalizados
assignedToIdstringNoID del usuario asignado
sourcestringNoNombre de la fuente del lead. Si no existe, se crea automáticamente.
sourceDetailstringNoDetalle adicional sobre el origen (ej: nombre de campaña, webhook).
tagsstring[]NoNombres de tags. Se buscan sin distinguir mayúsculas y se crean los que no existen. En PATCH reemplaza el conjunto completo
contactIdstringNoUUID del contacto del que sale el lead. Debe ser de tu organización (404 si no) y no estar dado de baja (422 CONTACT_OPTED_OUT). Si no mandás companyId, hereda la empresa del contacto
companyIdstringNoUUID de la empresa vinculada (no el texto de company). Debe ser de tu organización (404 si no). Si viene junto con contactId, gana esta
curl
curl -X POST "https://www.zephcrm.com/api/v1/leads" \
  -H "Authorization: Bearer vk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "firstName": "Maria",
    "lastName": "Garcia",
    "email": "maria@empresa.com",
    "company": "Tech SA",
    "status": "NEW",
    "source": "Zapier",
    "sourceDetail": "Typeform signup",
    "tags": ["fintech", "inbound"]
  }'
Response
{
  "data": {
    "id": "clxnew1...",
    "firstName": "Maria",
    "lastName": "Garcia",
    "email": "maria@empresa.com",
    "company": "Tech SA",
    "status": "NEW",
    "source": "Zapier",
    "leadSourceId": "clxsrc1...",
    "leadSource": { "id": "clxsrc1...", "name": "Zapier" },
    "sourceDetail": "Typeform signup",
    "createdAt": "2025-01-20T14:00:00.000Z",
    "updatedAt": "2025-01-20T14:00:00.000Z"
  }
}
PATCH/api/v1/leads/:idleads:write

Actualiza un lead existente. Solo enviar los campos a modificar.

Request Body (JSON)

CampoTipoReqDescripción
firstNamestringNoNombre
lastNamestringNoApellido
emailstringNoEmail
phonestringNoTeléfono
companystringNoNombre de empresa
positionstringNoCargo
statusstringNoNEW, CONTACTED, QUALIFIED, CONVERTED, LOST
notesstringNoNotas
customFieldsobjectNoCampos personalizados. Se MERGEA por clave con lo que ya tiene el lead: cada clave enviada pisa la anterior, null la elimina, las no enviadas quedan
assignedToIdstringNoID del usuario asignado
sourcestringNoNombre de la fuente del lead. Si no existe, se crea automáticamente.
sourceDetailstringNoDetalle adicional sobre el origen (ej: nombre de campaña, webhook).
tagsstring[]NoNombres de tags. Se buscan sin distinguir mayúsculas y se crean los que no existen. En PATCH reemplaza el conjunto completo
curl
curl -X PATCH "https://www.zephcrm.com/api/v1/leads/clx1abc..." \
  -H "Authorization: Bearer vk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "status": "CONTACTED",
    "notes": "Llamada realizada el 20/01"
  }'
Response
{
  "data": {
    "id": "clx1abc...",
    "firstName": "Juan",
    "lastName": "Perez",
    "status": "CONTACTED",
    "notes": "Llamada realizada el 20/01",
    "updatedAt": "2025-01-20T15:00:00.000Z"
  }
}
PATCH/api/v1/leads/bulkleads:write

Actualiza hasta 100 leads en una llamada: marcar estado, asignar, etiquetar o escribir campos personalizados en un lote sin una request por lead. Todo o nada: si un id no es de tu organización responde 404 con la lista y no toca ninguno.

Request Body (JSON)

CampoTipoReqDescripción
idsstring[]SiUUIDs de los leads (1 a 100)
data.statusstringNoNEW, CONTACTED, QUALIFIED, CONVERTED, LOST
data.assignedToIdstringNoID del usuario asignado
data.notesstringNoNotas
data.followUpDatestringNoFecha ISO 8601, o null para borrarla
data.customFieldsobjectNoCampos personalizados. Se MERGEA por clave con lo que ya tiene el lead: cada clave enviada pisa la anterior, null la elimina, las no enviadas quedan
data.addTagsstring[]NoTags a AGREGAR a cada lead (no reemplaza los que ya tiene). Se crean si no existen
curl
curl -X PATCH "https://www.zephcrm.com/api/v1/leads/bulk" \
  -H "Authorization: Bearer vk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "ids": ["clx1abc...", "clx2def..."],
    "data": {
      "status": "CONTACTED",
      "customFields": { "pipeline_status": "processing", "last_error": null },
      "addTags": ["lote-7"]
    }
  }'
Response
{
  "data": { "updated": 2 }
}

DELETE no disponible

La API no expone endpoints DELETE. Las eliminaciones se realizan exclusivamente desde la UI del CRM. Un DELETE a /api/v1/leads/:id retorna 405 Method Not Allowed.

Contactos

GET/api/v1/contactscontacts:read

Lista todos los contactos de tu organización.

Query Parameters

ParamTipoDescripción
cursorstringCursor para paginación (ID del último item)
limitnumberItems por pagina (default 20, max 100)
sortstringCampo por el que ordenar
orderasc | descDirección del orden (default desc)
searchstringBuscar en nombre, email, etc.
created_afterISO 8601Filtrar por fecha de creación
created_beforeISO 8601Filtrar por fecha de creación
company_idstringID de la empresa asociada
email_opt_outbooleanfalse = sólo quienes no se dieron de baja. Mandalo siempre que vayas a escribirle a alguien
tagstringContactos con alguno de estos tags (separados por coma, sin distinguir mayúsculas). Repetir el parámetro exige todos
custom.<field>stringIgualdad exacta sobre un campo personalizado, ej. custom.pipeline_state=pending. a,b = cualquiera de los dos; varias claves se combinan con AND. true/false y los números encuentran también el booleano o el número guardado
curl
curl "https://www.zephcrm.com/api/v1/contacts?limit=100&email_opt_out=false&custom.outbound_status=pending&sort=createdAt&order=asc" \
  -H "Authorization: Bearer vk_live_..."
Response
{
  "data": [
    {
      "id": "clxc1...",
      "firstName": "Maria",
      "lastName": "Garcia",
      "email": "maria@techsa.com",
      "phone": "+54 11 9876-5432",
      "mobile": "+54 9 11 9876-5432",
      "position": "CTO",
      "companyId": "clxcomp1...",
      "companyRef": {
        "id": "clxcomp1...",
        "name": "Tech SA",
        "website": "https://techsa.com",
        "employeeCount": 120,
        "industry": { "id": "clxind1...", "name": "Software" },
        "country": { "id": "clxcty1...", "name": "Argentina" }
      },
      "ownerId": "clxuser1...",
      "emailOptOut": false,
      "tags": [{ "id": "clxtag1...", "name": "fintech", "color": "#6b7280" }],
      "customFields": { "outbound_status": "pending" },
      "createdAt": "2025-01-10T08:00:00.000Z",
      "updatedAt": "2025-01-18T12:00:00.000Z"
    }
  ],
  "pagination": {
    "nextCursor": "clxc1...",
    "hasMore": false,
    "total": 12
  }
}
GET/api/v1/contacts/:idcontacts:read

Obtiene un contacto por su ID.

curl
curl "https://www.zephcrm.com/api/v1/contacts/clxc1..." \
  -H "Authorization: Bearer vk_live_..."
Response
{
  "data": {
    "id": "clxc1...",
    "firstName": "Maria",
    "lastName": "Garcia",
    "email": "maria@techsa.com",
    "phone": "+54 11 9876-5432",
    "mobile": "+54 9 11 9876-5432",
    "position": "CTO",
    "companyId": "clxcomp1...",
    "company": { "id": "clxcomp1...", "name": "Tech SA" },
    "companyRef": {
      "id": "clxcomp1...",
      "name": "Tech SA",
      "website": "https://techsa.com",
      "employeeCount": 120,
      "industry": { "id": "clxind1...", "name": "Software" },
      "country": { "id": "clxcty1...", "name": "Argentina" }
    },
    "emailOptOut": false,
    "notes": null,
    "customFields": {},
    "createdAt": "2025-01-10T08:00:00.000Z",
    "updatedAt": "2025-01-18T12:00:00.000Z"
  }
}
POST/api/v1/contactscontacts:write

Crea un nuevo contacto. El email debe ser unico dentro de la organización.

Request Body (JSON)

CampoTipoReqDescripción
firstNamestringSiNombre
lastNamestringSiApellido
emailstringNoEmail (unico por org)
phonestringNoTeléfono fijo
mobilestringNoCelular
positionstringNoCargo
companyIdstringNoID de la empresa
notesstringNoNotas
customFieldsobjectNoCampos personalizados
curl
curl -X POST "https://www.zephcrm.com/api/v1/contacts" \
  -H "Authorization: Bearer vk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "firstName": "Carlos",
    "lastName": "Lopez",
    "email": "carlos@empresa.com",
    "companyId": "clxcomp1..."
  }'
Response
{
  "data": {
    "id": "clxcnew1...",
    "firstName": "Carlos",
    "lastName": "Lopez",
    "email": "carlos@empresa.com",
    "companyId": "clxcomp1...",
    "createdAt": "2025-01-20T14:00:00.000Z",
    "updatedAt": "2025-01-20T14:00:00.000Z"
  }
}
PATCH/api/v1/contacts/:idcontacts:write

Actualiza un contacto existente.

Request Body (JSON)

CampoTipoReqDescripción
firstNamestringNoNombre
lastNamestringNoApellido
emailstringNoEmail (unico por org)
phonestringNoTeléfono fijo
mobilestringNoCelular
positionstringNoCargo
companyIdstringNoID de la empresa
notesstringNoNotas
customFieldsobjectNoCampos personalizados
emailOptOutbooleanNoSólo true: da de baja al contacto y desde ahí POST /emails se niega a escribirle (422 EMAIL_OPT_OUT). Volver a darlo de alta se hace desde la UI
curl
curl -X PATCH "https://www.zephcrm.com/api/v1/contacts/clxc1..." \
  -H "Authorization: Bearer vk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "position": "VP Engineering",
    "mobile": "+54 9 11 5555-0000"
  }'
Response
{
  "data": {
    "id": "clxc1...",
    "firstName": "Maria",
    "lastName": "Garcia",
    "position": "VP Engineering",
    "mobile": "+54 9 11 5555-0000",
    "updatedAt": "2025-01-20T16:00:00.000Z"
  }
}
PATCH/api/v1/contacts/bulkcontacts:write

Actualiza hasta 100 contactos en una llamada: reclamar un lote escribiendo un estado en campos personalizados, asignar dueño o etiquetar. Todo o nada: si un id no es de tu organización responde 404 con la lista y no toca ninguno.

Request Body (JSON)

CampoTipoReqDescripción
idsstring[]SiUUIDs de los contactos (1 a 100)
data.customFieldsobjectNoCampos personalizados. Se MERGEA por clave con lo que ya tiene el contacto: cada clave enviada pisa la anterior, null la elimina, las no enviadas quedan
data.addTagsstring[]NoTags a AGREGAR a cada contacto (no reemplaza los que ya tiene). Se crean si no existen
data.ownerIdstringNoUUID del usuario dueño. Debe ser de tu organización
curl
curl -X PATCH "https://www.zephcrm.com/api/v1/contacts/bulk" \
  -H "Authorization: Bearer vk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "ids": ["clxc1...", "clxc2..."],
    "data": {
      "customFields": { "outbound_status": "processing" },
      "addTags": ["lote-7"]
    }
  }'
Response
{
  "data": { "updated": 2 }
}
POST/api/v1/contacts/bulkcontacts:write

Crea hasta 100 contactos en una llamada, deduplicando por email sin distinguir mayúsculas. Un email que ya existe no es error: la fila vuelve como existing con el id del contacto que ya estaba. Responde 201 si se creó al menos uno, 200 si no.

Request Body (JSON)

CampoTipoReqDescripción
contactsobject[]SiDe 1 a 100 contactos, cada uno con los mismos campos que el POST individual. results trae una entrada por fila en el mismo orden: created, existing (ya estaba) o duplicate (repite el email de otra fila del lote)
curl
curl -X POST "https://www.zephcrm.com/api/v1/contacts/bulk" \
  -H "Authorization: Bearer vk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "contacts": [
      { "firstName": "Carlos", "lastName": "Lopez", "email": "carlos@empresa.com" },
      { "firstName": "Maria", "lastName": "Garcia", "email": "MARIA@techsa.com" }
    ]
  }'
Response
{
  "data": {
    "created": 1,
    "existing": 1,
    "duplicate": 0,
    "results": [
      { "index": 0, "id": "clxcnew1...", "status": "created", "email": "carlos@empresa.com" },
      { "index": 1, "id": "clxc1...", "status": "existing", "email": "MARIA@techsa.com" }
    ]
  }
}

DELETE no disponible

La API no expone endpoints DELETE. Las eliminaciones se realizan exclusivamente desde la UI del CRM.

Empresas

GET/api/v1/companiescompanies:read

Lista todas las empresas de tu organización.

Query Parameters

ParamTipoDescripción
cursorstringCursor para paginación (ID del último item)
limitnumberItems por pagina (default 20, max 100)
sortstringCampo por el que ordenar
orderasc | descDirección del orden (default desc)
searchstringBuscar en nombre, email, etc.
created_afterISO 8601Filtrar por fecha de creación
created_beforeISO 8601Filtrar por fecha de creación
curl
curl "https://www.zephcrm.com/api/v1/companies?limit=20&search=tech" \
  -H "Authorization: Bearer vk_live_..."
Response
{
  "data": [
    {
      "id": "clxcomp1...",
      "name": "Tech SA",
      "website": "https://techsa.com",
      "phone": "+54 11 4000-0000",
      "address": "Av. Corrientes 1234",
      "city": "Buenos Aires",
      "employeeCount": 50,
      "customFields": {},
      "createdAt": "2025-01-05T09:00:00.000Z",
      "updatedAt": "2025-01-15T11:00:00.000Z"
    }
  ],
  "pagination": {
    "nextCursor": "clxcomp1...",
    "hasMore": false,
    "total": 8
  }
}
GET/api/v1/companies/:idcompanies:read

Obtiene una empresa por su ID.

curl
curl "https://www.zephcrm.com/api/v1/companies/clxcomp1..." \
  -H "Authorization: Bearer vk_live_..."
Response
{
  "data": {
    "id": "clxcomp1...",
    "name": "Tech SA",
    "website": "https://techsa.com",
    "phone": "+54 11 4000-0000",
    "address": "Av. Corrientes 1234",
    "city": "Buenos Aires",
    "employeeCount": 50,
    "customFields": {},
    "createdAt": "2025-01-05T09:00:00.000Z",
    "updatedAt": "2025-01-15T11:00:00.000Z"
  }
}
POST/api/v1/companiescompanies:write

Crea una nueva empresa. El nombre se deduplica (case-insensitive) dentro de la organización.

Request Body (JSON)

CampoTipoReqDescripción
namestringSiNombre de la empresa
websitestringNoSitio web
phonestringNoTeléfono
addressstringNoDirección
citystringNoCiudad
employeeCountnumberNoCantidad de empleados
customFieldsobjectNoCampos personalizados
curl
curl -X POST "https://www.zephcrm.com/api/v1/companies" \
  -H "Authorization: Bearer vk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Innovatech SRL",
    "website": "https://innovatech.com.ar",
    "city": "Cordoba",
    "employeeCount": 25
  }'
Response
{
  "data": {
    "id": "clxcompnew...",
    "name": "Innovatech SRL",
    "website": "https://innovatech.com.ar",
    "city": "Cordoba",
    "employeeCount": 25,
    "createdAt": "2025-01-20T14:00:00.000Z",
    "updatedAt": "2025-01-20T14:00:00.000Z"
  }
}
PATCH/api/v1/companies/:idcompanies:write

Actualiza una empresa existente.

Request Body (JSON)

CampoTipoReqDescripción
namestringNoNombre de la empresa
websitestringNoSitio web
phonestringNoTeléfono
addressstringNoDirección
citystringNoCiudad
employeeCountnumberNoCantidad de empleados
customFieldsobjectNoCampos personalizados
curl
curl -X PATCH "https://www.zephcrm.com/api/v1/companies/clxcomp1..." \
  -H "Authorization: Bearer vk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "employeeCount": 75,
    "address": "Av. del Libertador 5000"
  }'
Response
{
  "data": {
    "id": "clxcomp1...",
    "name": "Tech SA",
    "employeeCount": 75,
    "address": "Av. del Libertador 5000",
    "updatedAt": "2025-01-20T16:00:00.000Z"
  }
}

DELETE no disponible

La API no expone endpoints DELETE. Las eliminaciones se realizan exclusivamente desde la UI del CRM.

Oportunidades

GET/api/v1/opportunitiesopportunities:read

Lista todas las oportunidades de tu organización.

Query Parameters

ParamTipoDescripción
cursorstringCursor para paginación (ID del último item)
limitnumberItems por pagina (default 20, max 100)
sortstringCampo por el que ordenar
orderasc | descDirección del orden (default desc)
searchstringBuscar en nombre, email, etc.
created_afterISO 8601Filtrar por fecha de creación
created_beforeISO 8601Filtrar por fecha de creación
curl
curl "https://www.zephcrm.com/api/v1/opportunities?limit=20&sort=value&order=desc" \
  -H "Authorization: Bearer vk_live_..."
Response
{
  "data": [
    {
      "id": "clxopp1...",
      "title": "Implementacion CRM Enterprise",
      "value": 50000,
      "currency": "USD",
      "expectedCloseDate": "2025-03-15",
      "description": "Proyecto de implementacion completa",
      "stageId": "clxstage3...",
      "contactId": "clxc1...",
      "companyId": "clxcomp1...",
      "assignedToId": "clxuser1...",
      "customFields": {},
      "createdAt": "2025-01-12T10:00:00.000Z",
      "updatedAt": "2025-01-19T14:00:00.000Z"
    }
  ],
  "pagination": {
    "nextCursor": "clxopp1...",
    "hasMore": true,
    "total": 34
  }
}
GET/api/v1/opportunities/:idopportunities:read

Obtiene una oportunidad por su ID.

curl
curl "https://www.zephcrm.com/api/v1/opportunities/clxopp1..." \
  -H "Authorization: Bearer vk_live_..."
Response
{
  "data": {
    "id": "clxopp1...",
    "title": "Implementacion CRM Enterprise",
    "value": 50000,
    "currency": "USD",
    "expectedCloseDate": "2025-03-15",
    "description": "Proyecto de implementacion completa",
    "stageId": "clxstage3...",
    "contactId": "clxc1...",
    "companyId": "clxcomp1...",
    "assignedToId": "clxuser1...",
    "customFields": {},
    "createdAt": "2025-01-12T10:00:00.000Z",
    "updatedAt": "2025-01-19T14:00:00.000Z"
  }
}
POST/api/v1/opportunitiesopportunities:write

Crea una nueva oportunidad.

Request Body (JSON)

CampoTipoReqDescripción
titlestringSiTítulo de la oportunidad
valuenumberNoValor monetario
currencystringNoMoneda (default: USD)
expectedCloseDatestringNoFecha esperada de cierre (YYYY-MM-DD)
descriptionstringNoDescripción
stageIdstringSiID de la etapa del pipeline
contactIdstringNoID del contacto
companyIdstringNoID de la empresa
assignedToIdstringNoID del usuario asignado
customFieldsobjectNoCampos personalizados
curl
curl -X POST "https://www.zephcrm.com/api/v1/opportunities" \
  -H "Authorization: Bearer vk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Renovacion anual",
    "value": 12000,
    "currency": "USD",
    "expectedCloseDate": "2025-04-01",
    "stageId": "clxstage1...",
    "contactId": "clxc1...",
    "companyId": "clxcomp1..."
  }'
Response
{
  "data": {
    "id": "clxoppnew...",
    "title": "Renovacion anual",
    "value": 12000,
    "currency": "USD",
    "expectedCloseDate": "2025-04-01",
    "stageId": "clxstage1...",
    "contactId": "clxc1...",
    "companyId": "clxcomp1...",
    "createdAt": "2025-01-20T14:00:00.000Z",
    "updatedAt": "2025-01-20T14:00:00.000Z"
  }
}
PATCH/api/v1/opportunities/:idopportunities:write

Actualiza una oportunidad existente. Cambiar stageId mueve la oportunidad en el pipeline.

Request Body (JSON)

CampoTipoReqDescripción
titlestringNoTítulo
valuenumberNoValor monetario
currencystringNoMoneda
expectedCloseDatestringNoFecha esperada de cierre
descriptionstringNoDescripción
stageIdstringNoID de la etapa del pipeline
contactIdstringNoID del contacto
companyIdstringNoID de la empresa
assignedToIdstringNoID del usuario asignado
customFieldsobjectNoCampos personalizados
curl
curl -X PATCH "https://www.zephcrm.com/api/v1/opportunities/clxopp1..." \
  -H "Authorization: Bearer vk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "value": 55000,
    "stageId": "clxstage4..."
  }'
Response
{
  "data": {
    "id": "clxopp1...",
    "title": "Implementacion CRM Enterprise",
    "value": 55000,
    "stageId": "clxstage4...",
    "updatedAt": "2025-01-20T16:00:00.000Z"
  }
}

DELETE no disponible

La API no expone endpoints DELETE. Las eliminaciones se realizan exclusivamente desde la UI del CRM.

Actividades

GET/api/v1/activitiesactivities:read

Lista todas las actividades de tu organización con paginación y filtros.

Query Parameters

ParamTipoDescripción
cursorstringCursor para paginación (ID del último item)
limitnumberItems por pagina (default 20, max 100)
sortstringCampo por el que ordenar
orderasc | descDirección del orden (default desc)
searchstringBuscar en nombre, email, etc.
created_afterISO 8601Filtrar por fecha de creación
created_beforeISO 8601Filtrar por fecha de creación
typestringFiltrar por tipo: TASK, CALL, MEETING, EMAIL, NOTE
statusstringPENDING o COMPLETED
assigned_tostringID del usuario asignado
contact_idstringID del contacto asociado
company_idstringID de la empresa asociada
opportunity_idstringID de la oportunidad asociada
due_afterISO 8601Actividades con vencimiento después de esta fecha
due_beforeISO 8601Actividades con vencimiento antes de esta fecha
curl
curl "https://www.zephcrm.com/api/v1/activities?type=TASK&status=PENDING&limit=20" \
  -H "Authorization: Bearer vk_live_..."
Response
{
  "data": [
    {
      "id": "clxact1...",
      "type": "TASK",
      "title": "Llamar a Juan Perez",
      "description": "Seguimiento de propuesta",
      "dueDate": "2025-02-01T10:00:00.000Z",
      "completedAt": null,
      "priority": "HIGH",
      "contactId": "clxc1...",
      "opportunityId": "clxopp1...",
      "assignedToId": "clxuser1...",
      "createdAt": "2025-01-20T14:00:00.000Z",
      "updatedAt": "2025-01-20T14:00:00.000Z"
    }
  ],
  "pagination": {
    "nextCursor": "clxact1...",
    "hasMore": true,
    "total": 42
  }
}
GET/api/v1/activities/:idactivities:read

Obtiene una actividad por su ID con relaciones (contacto, oportunidad, usuario asignado).

curl
curl "https://www.zephcrm.com/api/v1/activities/clxact1..." \
  -H "Authorization: Bearer vk_live_..."
Response
{
  "data": {
    "id": "clxact1...",
    "type": "TASK",
    "title": "Llamar a Juan Perez",
    "description": "Seguimiento de propuesta",
    "dueDate": "2025-02-01T10:00:00.000Z",
    "completedAt": null,
    "priority": "HIGH",
    "contact": { "id": "clxc1...", "firstName": "Juan", "lastName": "Perez", "email": "juan@empresa.com" },
    "opportunity": { "id": "clxopp1...", "title": "Implementacion CRM" },
    "assignedTo": { "id": "clxuser1...", "name": "Admin" },
    "createdAt": "2025-01-20T14:00:00.000Z",
    "updatedAt": "2025-01-20T14:00:00.000Z"
  }
}
POST/api/v1/activitiesactivities:write

Crea una nueva actividad. Las tareas (TASK) requieren dueDate.

Request Body (JSON)

CampoTipoReqDescripción
typestringSiTASK, CALL, MEETING, EMAIL, NOTE
titlestringSiTítulo de la actividad
descriptionstringNoDescripción
dueDateISO 8601NoFecha de vencimiento (requerido para TASK)
prioritystringNoLOW, MEDIUM (default), HIGH
contactIdstringNoID del contacto asociado
opportunityIdstringNoID de la oportunidad asociada
assignedToIdstringNoID del usuario asignado (default: usuario de la key)
curl
curl -X POST "https://www.zephcrm.com/api/v1/activities" \
  -H "Authorization: Bearer vk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "type": "TASK",
    "title": "Enviar propuesta a cliente",
    "dueDate": "2025-02-05T10:00:00.000Z",
    "priority": "HIGH",
    "contactId": "clxc1...",
    "opportunityId": "clxopp1..."
  }'
Response
{
  "data": {
    "id": "clxactnew...",
    "type": "TASK",
    "title": "Enviar propuesta a cliente",
    "dueDate": "2025-02-05T10:00:00.000Z",
    "priority": "HIGH",
    "completedAt": null,
    "createdAt": "2025-01-20T14:00:00.000Z",
    "updatedAt": "2025-01-20T14:00:00.000Z"
  }
}
PATCH/api/v1/activities/:idactivities:write

Actualiza una actividad. Para marcar como completada, enviar completedAt con la fecha actual.

Request Body (JSON)

CampoTipoReqDescripción
titlestringNoTítulo
descriptionstringNoDescripción
dueDateISO 8601NoFecha de vencimiento
prioritystringNoLOW, MEDIUM, HIGH
typestringNoTASK, CALL, MEETING, EMAIL, NOTE
contactIdstringNoID del contacto asociado
opportunityIdstringNoID de la oportunidad asociada
assignedToIdstringNoID del usuario asignado
completedAtISO 8601 | nullNoFecha de completado (null para reabrir)
curl
curl -X PATCH "https://www.zephcrm.com/api/v1/activities/clxact1..." \
  -H "Authorization: Bearer vk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "completedAt": "2025-01-20T16:00:00.000Z"
  }'
Response
{
  "data": {
    "id": "clxact1...",
    "type": "TASK",
    "title": "Llamar a Juan Perez",
    "completedAt": "2025-01-20T16:00:00.000Z",
    "updatedAt": "2025-01-20T16:00:00.000Z"
  }
}

DELETE no disponible

La API no expone endpoints DELETE para actividades.

Pipeline Stages

GET/api/v1/pipeline-stagespipeline:read

Lista las etapas del pipeline de ventas ordenadas por posición. Usa esto para obtener los stageId al crear o mover oportunidades.

curl
curl "https://www.zephcrm.com/api/v1/pipeline-stages" \
  -H "Authorization: Bearer vk_live_..."
Response
{
  "data": [
    {
      "id": "clxstage1...",
      "name": "Prospeccion",
      "order": 0,
      "color": "#3b82f6",
      "probability": 10,
      "isDefault": true,
      "isWon": false,
      "isLost": false
    },
    {
      "id": "clxstage2...",
      "name": "Propuesta",
      "order": 1,
      "color": "#f59e0b",
      "probability": 50,
      "isDefault": false,
      "isWon": false,
      "isLost": false
    },
    {
      "id": "clxstage3...",
      "name": "Ganada",
      "order": 2,
      "color": "#22c55e",
      "probability": 100,
      "isDefault": false,
      "isWon": true,
      "isLost": false
    }
  ]
}

Secuencias de seguimiento

GET/api/v1/sequencessequences:read

Lista las secuencias de seguimiento de la organización.

curl
curl "https://www.zephcrm.com/api/v1/sequences" \
  -H "Authorization: Bearer vk_live_..."
Response
{
  "data": [
    {
      "id": "6f1b2c3d-...",
      "name": "Seguimiento leads nuevos",
      "description": "Para leads del formulario web",
      "isActive": true,
      "reviewMode": false,
      "language": "es",
      "stepCount": 3,
      "activeEnrollments": 12,
      "createdAt": "2026-07-01T12:00:00.000Z"
    }
  ]
}
GET/api/v1/sequences/{id}sequences:read

Detalle de una secuencia con sus pasos: mode (AI, TEMPLATE o MANUAL), briefing (sólo AI), templateId (sólo TEMPLATE), subject (sólo el primer paso; los demás responden en el hilo) y delay. Los campos que no aplican al modo vienen en null.

curl
curl "https://www.zephcrm.com/api/v1/sequences/6f1b2c3d-..." \
  -H "Authorization: Bearer vk_live_..."
Response
{
  "data": {
    "id": "6f1b2c3d-...",
    "name": "Seguimiento leads nuevos",
    "isActive": true,
    "reviewMode": false,
    "tone": "profesional cercano",
    "language": "es",
    "sendWindow": { "days": [1, 2, 3, 4, 5], "startHour": 9, "endHour": 18 },
    "steps": [
      { "order": 1, "mode": "MANUAL", "briefing": null, "templateId": null, "subject": "Una idea para {{company}}", "delayValue": 1, "delayUnit": "hours" },
      { "order": 2, "mode": "AI", "briefing": "Reforzar valor con un caso de éxito", "templateId": null, "subject": null, "delayValue": 3, "delayUnit": "days" },
      { "order": 3, "mode": "TEMPLATE", "briefing": null, "templateId": "9a8b7c6d-...", "subject": null, "delayValue": 5, "delayUnit": "days" }
    ]
  }
}
POST/api/v1/sequences/{id}/enrollmentssequences:write

Enrola contactos en la secuencia, hasta 100 por pedido. Los emails se envían desde la casilla del dueño de la API key. Quienes no se pueden enrolar vuelven en skipped con su code (NOT_FOUND, NO_EMAIL, OPT_OUT, ALREADY_ACTIVE, LEAD_CLOSED).

curl
curl -X POST "https://www.zephcrm.com/api/v1/sequences/6f1b2c3d-.../enrollments" \
  -H "Authorization: Bearer vk_live_..." \
  -H "Content-Type: application/json" \
  -d '{ "contactIds": ["c4d5e6f7-...", "d8e9f0a1-..."] }'
Response
{
  "data": {
    "enrolled": 1,
    "skipped": [
      {
        "leadId": null,
        "contactId": "d8e9f0a1-...",
        "code": "ALREADY_ACTIVE",
        "reason": "Ya tiene una secuencia activa"
      }
    ]
  }
}

El seguimiento es del contacto: mandá contactIds. Un contacto no necesita lead para ser enrolado. Los ids repetidos o los campos desconocidos responden 400; una secuencia que pertenece a una campaña responde 422 SEQUENCE_OWNED_BY_CAMPAIGN.

leadIds está deprecado: se sigue aceptando, pero la respuesta lleva el header Deprecation: true y un Link a esta documentación. Pasá a contactIds.

GET/api/v1/enrollmentssequences:read

Estado de los seguimientos, los 50 más recientes. Estados: ACTIVE, WAITING_APPROVAL, REPLIED, COMPLETED, CANCELLED, FAILED.

Query Parameters

ParamTipoDescripción
contactIduuidSeguimientos de un contacto
campaignIduuidSeguimientos que puso en marcha una campaña
sequenceIduuidSeguimientos de una secuencia
leadIduuidSeguimientos del lead y de su contacto
statusstringACTIVE | WAITING_APPROVAL | REPLIED | COMPLETED | CANCELLED | FAILED
curl
curl "https://www.zephcrm.com/api/v1/enrollments?contactId=c4d5e6f7-..." \
  -H "Authorization: Bearer vk_live_..."

curl "https://www.zephcrm.com/api/v1/enrollments?campaignId=3f9a1b2c-...&status=REPLIED" \
  -H "Authorization: Bearer vk_live_..."
Response
{
  "data": [
    {
      "id": "9c8d7e6f-...",
      "status": "ACTIVE",
      "currentStep": 1,
      "totalSteps": 3,
      "nextSendAt": "2026-07-25T13:00:00.000Z",
      "repliedAt": null,
      "repliedAfterStep": null,
      "campaignId": "3f9a1b2c-...",
      "sequence": { "id": "6f1b2c3d-...", "name": "Seguimiento leads nuevos", "reviewMode": false },
      "contact": { "id": "c4d5e6f7-...", "firstName": "Ana", "lastName": "García", "email": "ana@empresa.com" },
      "lead": null
    }
  ]
}

Requiere al menos uno de contactId, campaignId, sequenceId o leadId. Cada seguimiento trae su contact; lead puede venir en null porque el contacto no necesita lead. Con ?leadId= devuelve los del lead y los de su contacto, y responde 404 si el lead no existe. Una campaña que el dueño de la key no ve (un ADMIN ve todas; otro rol, sólo las que creó) responde 404 por campaignId o por su secuencia propia, y en el listado su campaignId y el id y el nombre de su secuencia vienen en null.

DELETE/api/v1/enrollments/{id}sequences:write

Cancela un seguimiento en curso. No se le envían más emails a esa persona.

curl
curl -X DELETE "https://www.zephcrm.com/api/v1/enrollments/9c8d7e6f-..." \
  -H "Authorization: Bearer vk_live_..."
Response
{
  "data": { "id": "9c8d7e6f-...", "status": "CANCELLED" }
}

Campañas

Una campaña se envía esperando respuesta. La API devuelve sus métricas y, sobre todo, permite listar a quiénes respondieron para seguirlos.

GET/api/v1/campaignscampaigns:read

Lista las campañas con sus métricas y tasas ya calculadas. No incluye newsletters.

Query Parameters

ParamTipoDescripción
cursorstringCursor para paginación (ID del último item)
limitnumberItems por pagina (default 20, max 100)
sortstringCampo por el que ordenar
orderasc | descDirección del orden (default desc)
searchstringBuscar en nombre, email, etc.
created_afterISO 8601Filtrar por fecha de creación
created_beforeISO 8601Filtrar por fecha de creación
statusstringDRAFT | SENDING | COMPLETED | CANCELLED
curl
curl "https://www.zephcrm.com/api/v1/campaigns" \
  -H "Authorization: Bearer vk_live_..."
Response
{
  "data": [
    {
      "id": "3f9a1b2c-...",
      "name": "Outreach Q3",
      "version": 2,
      "subject": null,
      "status": "COMPLETED",
      "sentAt": "2026-08-09T13:00:00.000Z",
      "totalRecipients": 120,
      "totalSent": 118,
      "totalOpened": 64,
      "totalClicked": 21,
      "totalBounced": 2,
      "totalReplied": 9,
      "openRate": 54.2,
      "clickRate": 17.8,
      "replyRate": 7.6,
      "repliesCheckedAt": "2026-08-12T10:15:00.000Z",
      "followUpSequence": {
        "id": "7d6e5f4a-...",
        "name": "Seguimiento outbound",
        "stepCount": 3
      },
      "followUp": {
        "running": 42,
        "awaitingApproval": 0,
        "replied": 9,
        "completed": 61,
        "cancelled": 3,
        "failed": 0,
        "total": 115
      },
      "steps": [
        { "order": 1, "mode": "AI", "sent": 118, "repliedAfter": 5 },
        { "order": 2, "mode": "TEMPLATE", "sent": 96, "repliedAfter": 3 },
        { "order": 3, "mode": "MANUAL", "sent": 61, "repliedAfter": 1 }
      ]
    }
  ]
}

version indica si la campaña es v1 (un solo email) o v2 (pasos propios). En una v2, steps trae un elemento por paso con su mode (AI, TEMPLATE, MANUAL), cuántos lo recibieron (sent) y cuántos respondieron después de ese paso (repliedAfter); en una v1 viene vacío. subject viene en null cuando el paso 1 de una v2 es AI: cada email lleva su propio asunto.

followUpSequence y followUp vienen en null si la campaña no tiene seguimiento configurado: no es lo mismo que tenerlo y no haber enrolado a nadie. Los conteos son de los seguimientos que ese envío puso en marcha, no de la secuencia completa.

GET/api/v1/campaigns/{id}/recipientscampaigns:read

Destinatarios de una campaña. Con ?replied=true devuelve sólo a quienes respondieron, con su contactId y leadId para encadenar con el resto de la API.

Query Parameters

ParamTipoDescripción
cursorstringCursor para paginación (ID del último item)
limitnumberItems por pagina (default 20, max 100)
sortstringCampo por el que ordenar
orderasc | descDirección del orden (default desc)
searchstringBuscar en nombre, email, etc.
created_afterISO 8601Filtrar por fecha de creación
created_beforeISO 8601Filtrar por fecha de creación
repliedtrue | falsetrue: sólo los que respondieron
curl
curl "https://www.zephcrm.com/api/v1/campaigns/3f9a1b2c-.../recipients?replied=true" \
  -H "Authorization: Bearer vk_live_..."
Response
{
  "data": [
    {
      "id": "b7c8d9e0-...",
      "status": "SENT",
      "sentAt": "2026-08-09T13:00:00.000Z",
      "openedAt": "2026-08-09T15:22:00.000Z",
      "repliedAt": "2026-08-10T09:41:00.000Z",
      "replied": true,
      "email": "ana@acme.test",
      "contactId": "a1b2c3d4-...",
      "contactName": "Ana Gómez",
      "leadId": "e5f6a7b8-...",
      "leadStatus": "CONTACTED",
      "enrollment": { "id": "9c8d7e6f-...", "status": "REPLIED", "currentStep": 2 },
      "skippedReason": null
    }
  ]
}

enrollment es el seguimiento del destinatario ({ id, status, currentStep }) o null si no se lo enroló; skippedReason dice por qué se lo omitió. leadId es el lead del seguimiento o, si no tiene, el último lead del contacto.

Templates de email

Los templates son el contenido reutilizable de campañas y de los pasos de una secuencia.

GET/api/v1/templatestemplates:read

Lista los templates de la organización.

Query Parameters

ParamTipoDescripción
cursorstringCursor para paginación (ID del último item)
limitnumberItems por pagina (default 20, max 100)
sortstringCampo por el que ordenar
orderasc | descDirección del orden (default desc)
searchstringBuscar en nombre, email, etc.
created_afterISO 8601Filtrar por fecha de creación
created_beforeISO 8601Filtrar por fecha de creación
activetrue | falseFiltra por estado
curl
curl "https://www.zephcrm.com/api/v1/templates" \
  -H "Authorization: Bearer vk_live_..."
Response
{
  "data": [
    {
      "id": "9c8b7a6d-...",
      "name": "Outreach inicial",
      "subject": "Propuesta para {{company}}",
      "variables": ["company", "firstName"],
      "isActive": true
    }
  ]
}
POST/api/v1/templatestemplates:write

Crea un template. Las variables se derivan del asunto y del cuerpo; no se envían.

curl
curl -X POST "https://www.zephcrm.com/api/v1/templates" \
  -H "Authorization: Bearer vk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Outreach inicial",
    "subject": "Propuesta para {{company}}",
    "body": "<p>Hola {{firstName}}, te escribo por…</p>"
  }'
Response
{
  "data": {
    "id": "9c8b7a6d-...",
    "name": "Outreach inicial",
    "subject": "Propuesta para {{company}}",
    "variables": ["company", "firstName"],
    "isActive": true
  }
}

Emails

Envío de emails sueltos, de a uno. Es lo mismo que "Redactar email" desde un lead o contacto: sale por la casilla Gmail/Outlook conectada del dueño de la API key y queda registrado en el CRM. Para campañas masivas y secuencias, ver sus secciones.

POST/api/v1/emailsemails:write

Envía un email real y lo registra. Con leadId/contactId queda en el timeline de esa entidad. Devuelve threadId para poder responder en el mismo hilo después. Para un preview, mandalo a tu propia casilla sin vincular nada.

Request Body (JSON)

CampoTipoReqDescripción
tostringSiUna dirección, o un atajo: "lead" (el email del lead de leadId), "contact" (el de contactId) u "owner" (tu propia casilla, para un preview)
idempotencyKeystringNoRecomendada. La misma clave dentro de tu organización devuelve el envío original con 200 en vez de mandar otra vez. Ej: outbound-{leadId}-{runId}
subjectstringSiAsunto (máx. 300)
bodystringSiCuerpo en HTML. Se normaliza al guardar (colores a hexadecimal)
toNamestringNoNombre para mostrar del destinatario
ccstringNoDirecciones en copia, separadas por coma
bccstringNoDirecciones en copia oculta, separadas por coma
leadIdstringNoUUID del lead al que vincular el envío (debe ser de tu organización)
contactIdstringNoUUID del contacto al que vincular el envío
opportunityIdstringNoUUID de la oportunidad a la que vincular el envío
emailAccountIdstringNoCasilla a usar. Si se omite, la primera activa del dueño de la key
threadIdstringNothreadId devuelto por un envío anterior, para responder en ese hilo
inReplyTostringNoMessage-ID RFC 2822 al que se responde
curl
curl -X POST "https://www.zephcrm.com/api/v1/emails" \
  -H "Authorization: Bearer vk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "to": "lead",
    "subject": "Sobre su consulta",
    "body": "<p>Hola Maria,</p><p>Gracias por escribirnos...</p>",
    "leadId": "clxnew1...",
    "idempotencyKey": "outbound-clxnew1-run42"
  }'
Response
{
  "data": {
    "id": "8c2f...",
    "subject": "Sobre su consulta",
    "toEmail": "maria@empresa.com",
    "toName": "Maria Garcia",
    "messageId": "18f3a2...",
    "threadId": "18f3a2...",
    "idempotencyKey": "outbound-clxnew1-run42",
    "source": "CRM",
    "leadId": "clxnew1...",
    "contactId": null,
    "opportunityId": null,
    "sentAt": "2025-01-20T14:00:00.000Z",
    "openedAt": null,
    "openCount": 0,
    "emailAccount": { "id": "acc1...", "email": "vendedor@miempresa.com", "provider": "GOOGLE" }
  }
}

El envío usa la casilla del usuario dueño de la API key. Si no tiene Gmail u Outlook conectado (Configuración → Integraciones) responde 422 NO_EMAIL_ACCOUNT. Si el proveedor rechaza el mensaje, 502 SEND_FAILED. Si el destinatario se dio de baja (el contacto, el contacto del lead o la dirección de to), responde 422 EMAIL_OPT_OUT y no envía.

Mandá siempre idempotencyKey: enviar es lo único irreversible de la API, y con la clave guardada en el CRM un reintento (timeout, corte de red, corrida repetida) no duplica el email. Si otro request con la misma clave está enviando en ese momento, 409 IN_PROGRESS.

Si el proveedor aceptó el email pero no devolvió su id, messageId viene como "unconfirmed:<id>": el email salió, pero ese valor no es un id del proveedor y no sirve para buscar el mensaje ni el hilo.

GET/api/v1/emailsemails:read

Emails enviados (los 50 más recientes). Hay que pasar al menos un filtro. Sirve para saber qué se le mandó ya a alguien antes de volver a escribirle.

Query Parameters

ParamTipoDescripción
leadIdstringEnviados vinculados a este lead
contactIdstringEnviados vinculados a este contacto
opportunityIdstringEnviados vinculados a esta oportunidad
tostringEnviados a esta dirección (sin distinguir mayúsculas)
curl
curl "https://www.zephcrm.com/api/v1/emails?leadId=clxnew1..." \
  -H "Authorization: Bearer vk_live_..."
Response
{
  "data": [
    {
      "id": "8c2f...",
      "subject": "Sobre su consulta",
      "toEmail": "maria@empresa.com",
      "threadId": "18f3a2...",
      "leadId": "clxnew1...",
      "sentAt": "2025-01-20T14:00:00.000Z",
      "openedAt": "2025-01-20T16:12:00.000Z",
      "openCount": 2,
      "emailAccount": { "id": "acc1...", "email": "vendedor@miempresa.com", "provider": "GOOGLE" }
    }
  ]
}
GET/api/v1/search(cualquier :read)

Busca en todas las entidades para las que la API key tenga scope de lectura. Retorna resultados agrupados por tipo.

Query Parameters

ParamTipoDescripción
qstringTexto de búsqueda (requerido, mínimo 2 caracteres)
typesstringTipos a buscar separados por coma (ej: leads,contacts). Por defecto busca en todos.
limitnumberMax resultados por tipo (default 5, max 20)
curl
curl "https://www.zephcrm.com/api/v1/search?q=garcia&limit=5" \
  -H "Authorization: Bearer vk_live_..."
Response
{
  "data": {
    "leads": [
      { "id": "clx1...", "firstName": "Maria", "lastName": "Garcia", "email": "maria@empresa.com", "status": "QUALIFIED" }
    ],
    "contacts": [
      { "id": "clxc1...", "firstName": "Maria", "lastName": "Garcia", "email": "maria@techsa.com", "position": "CTO" }
    ],
    "companies": [],
    "opportunities": [],
    "activities": []
  }
}

Agentes de IA

Zeph CRM expone una skill pública (SKILL.md) que puede usar cualquier agente de IA (OpenClaw, Muse, Dots, Grok y otros). El endpoint no requiere autenticación: describe las herramientas disponibles para que el agente las descubra solo. Los agentes que importan una API pueden usar la especificación OpenAPI.

URL de la skill: https://www.zephcrm.com/api/agents/skill

curl
curl "https://www.zephcrm.com/api/agents/skill"

Especificación OpenAPI: https://www.zephcrm.com/api/v1/openapi.json

Para conectar un agente, creá una API key con los scopes necesarios en Settings > API Keys y configurá tu agente con la URL de la skill o la especificación OpenAPI. La URL anterior, /api/openclaw/skill, sigue funcionando.

Necesitas ayuda? Contacta a soporte o visita el Centro de Ayuda.

API Reference — Zeph