Actividades
Gestiona las actividades de tu CRM — llamadas, tareas, reuniones, correos, notas y más. Las actividades pueden asociarse a cualquier entidad (contacto, empresa, negocio, producto, etc.).
Autenticación
Requiere header Authorization: Bearer {token}. Ver .
Listar Actividades
GET /activitiesRetorna una lista paginada de actividades del workspace, con soporte para filtros y búsqueda.
Parámetros de consulta
| Parámetro | Tipo | Requerido | Descripción |
|---|---|---|---|
cursor | string | No | Cursor de paginación retornado en la respuesta anterior |
limit | integer | No | Resultados por página. Mín: 1, máx: 100. Default: 25 |
sort | string | No | Campo de ordenamiento: created_at, due_date, title. Default: created_at |
order | string | No | Dirección: asc o desc. Default: desc |
search | string | No | Búsqueda por texto en título y descripción |
type | string | No | Tipo de actividad: call, task, meeting, email, note, lunch, deadline |
status | string | No | Estado: pending, completed, overdue |
owner_id | string | No | Filtra por ID del responsable |
entity_type | string | No | Filtra por tipo de entidad asociada: contact, company, deal, product, subscription, booking, quote, order, invoice |
entity_id | string | No | Filtra por ID de la entidad asociada. Requiere entity_type |
Permisos
Requiere permiso activities:read. Los usuarios con permiso de alcance propio (activities:read:own) solo ven actividades asignadas a ellos.
Ejemplo
curl -X GET "https://api-crm.zelta.dev/public/v1/activities?type=task&status=pending&limit=25" \
-H "Authorization: Bearer tu-api-token-aqui"Ejemplo JS
const params = new URLSearchParams({
type: 'task',
status: 'pending',
limit: '25'
});
const response = await fetch(
`https://api-crm.zelta.dev/public/v1/activities?${params}`,
{
headers: {
'Authorization': `Bearer ${process.env.ZELTA_API_TOKEN}`
}
}
);
const result = await response.json();
console.log(result.data); // array de actividadesEjemplo Py
import requests
response = requests.get(
'https://api-crm.zelta.dev/public/v1/activities',
params={
'type': 'task',
'status': 'pending',
'limit': 25
},
headers={
'Authorization': 'Bearer tu-api-token-aqui'
}
)
result = response.json()
print(result['data'])Respuesta exitosa
HTTP 200 OK
{
"data": [
{
"id": "V1StGXR8_Z5jdHi6B-myT",
"title": "Llamada de seguimiento",
"description": "Revisar propuesta enviada la semana pasada",
"type": "call",
"priority": "high",
"status": "pending",
"ownerId": "aB3kLmNpQrSt",
"ownerName": "María González",
"entityType": "deal",
"entityId": "xY9wVuTsRqPo",
"dueDate": "2026-04-15T10:00:00.000Z",
"durationMinutes": 30,
"location": null,
"meetingUrl": null,
"notes": null,
"completedAt": null,
"customData": {},
"createdAt": "2026-04-01T14:22:00.000Z",
"updatedAt": "2026-04-01T14:22:00.000Z"
}
],
"pagination": {
"nextCursor": "eyJjcmVhdGVkQXQiOiIyMDI2LTA0LTAxVDE0OjIyOjAwLjAwMFoiLCJpZCI6IlYxU3RHWFIyX1o1amRIaTZCLW15VCJ9",
"hasMore": true
}
}Obtener Actividad
GET /activities/:idRetorna el detalle completo de una actividad por su ID.
Parámetros de ruta
| Parámetro | Tipo | Requerido | Descripción |
|---|---|---|---|
id | string | Sí | ID de la actividad |
Ejemplo
curl -X GET "https://api-crm.zelta.dev/public/v1/activities/V1StGXR8_Z5jdHi6B-myT" \
-H "Authorization: Bearer tu-api-token-aqui"Ejemplo JS
const id = 'V1StGXR8_Z5jdHi6B-myT';
const response = await fetch(
`https://api-crm.zelta.dev/public/v1/activities/${id}`,
{
headers: {
'Authorization': `Bearer ${process.env.ZELTA_API_TOKEN}`
}
}
);
const result = await response.json();
console.log(result.data);Ejemplo Py
import requests
activity_id = 'V1StGXR8_Z5jdHi6B-myT'
response = requests.get(
f'https://api-crm.zelta.dev/public/v1/activities/{activity_id}',
headers={
'Authorization': 'Bearer tu-api-token-aqui'
}
)
result = response.json()
print(result['data'])Respuesta exitosa
HTTP 200 OK
{
"data": {
"id": "V1StGXR8_Z5jdHi6B-myT",
"title": "Llamada de seguimiento",
"description": "Revisar propuesta enviada la semana pasada",
"type": "call",
"priority": "high",
"status": "pending",
"ownerId": "aB3kLmNpQrSt",
"ownerName": "María González",
"entityType": "deal",
"entityId": "xY9wVuTsRqPo",
"dueDate": "2026-04-15T10:00:00.000Z",
"durationMinutes": 30,
"location": null,
"meetingUrl": null,
"notes": null,
"completedAt": null,
"customData": {},
"createdAt": "2026-04-01T14:22:00.000Z",
"updatedAt": "2026-04-01T14:22:00.000Z"
}
}Crear Actividad
POST /activitiesCrea una nueva actividad en el workspace.
Cuerpo de la solicitud
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
title | string | Sí | Título de la actividad. Máx: 200 caracteres |
type | string | Sí | Tipo: call, task, meeting, email, note, lunch, deadline |
description | string | No | Descripción detallada |
priority | string | No | Prioridad: low, medium, high. Default: medium |
ownerId | string | No | ID del usuario responsable. Default: el usuario de la API key |
entityType | string | No | Tipo de entidad principal: contact, company, deal, product, subscription, booking, quote, order, invoice |
entityId | string | Condicional | ID de la entidad principal. Requerido cuando se envía entityType |
entities | array | No | Entidades adicionales asociadas (máx. 10). Ver objeto entities[] |
dueDate | string | No | Fecha y hora de vencimiento en formato ISO 8601 |
durationMinutes | integer | No | Duración estimada en minutos. Debe ser mayor a 0 |
location | string | No | Ubicación física de la actividad |
meetingUrl | string | No | URL de videoconferencia (formato URL válida) |
notes | string | No | Notas internas de la actividad |
customData | object | No | Datos adicionales en formato clave-valor libre |
Objeto en entities[]
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
entityType | string | Sí | Tipo de entidad: contact, company, deal, product, subscription, booking, quote, order, invoice |
entityId | string | Sí | ID de la entidad a asociar |
Entidad principal vs. entidades adicionales
entityType + entityId definen la entidad principal de la actividad (aparece en el timeline de esa entidad). El array entities permite asociar la actividad a múltiples entidades adicionales simultáneamente, por ejemplo: un contacto y el negocio relacionado.
Ejemplo
curl -X POST "https://api-crm.zelta.dev/public/v1/activities" \
-H "Authorization: Bearer tu-api-token-aqui" \
-H "Content-Type: application/json" \
-d '{
"title": "Reunión de presentación de propuesta",
"type": "meeting",
"priority": "high",
"entityType": "deal",
"entityId": "xY9wVuTsRqPo",
"entities": [
{ "entityType": "contact", "entityId": "cZ2mNbKpLqRs" }
],
"dueDate": "2026-04-20T15:00:00.000Z",
"durationMinutes": 60,
"meetingUrl": "https://meet.google.com/abc-defg-hij",
"notes": "Llevar demo del módulo de reportes"
}'Ejemplo JS
const response = await fetch('https://api-crm.zelta.dev/public/v1/activities', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.ZELTA_API_TOKEN}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
title: 'Reunión de presentación de propuesta',
type: 'meeting',
priority: 'high',
entityType: 'deal',
entityId: 'xY9wVuTsRqPo',
entities: [
{ entityType: 'contact', entityId: 'cZ2mNbKpLqRs' }
],
dueDate: '2026-04-20T15:00:00.000Z',
durationMinutes: 60,
meetingUrl: 'https://meet.google.com/abc-defg-hij',
notes: 'Llevar demo del módulo de reportes'
})
});
const result = await response.json();
console.log(result.data.id);Ejemplo Py
import requests
response = requests.post(
'https://api-crm.zelta.dev/public/v1/activities',
headers={
'Authorization': 'Bearer tu-api-token-aqui',
'Content-Type': 'application/json'
},
json={
'title': 'Reunión de presentación de propuesta',
'type': 'meeting',
'priority': 'high',
'entityType': 'deal',
'entityId': 'xY9wVuTsRqPo',
'entities': [
{'entityType': 'contact', 'entityId': 'cZ2mNbKpLqRs'}
],
'dueDate': '2026-04-20T15:00:00.000Z',
'durationMinutes': 60,
'meetingUrl': 'https://meet.google.com/abc-defg-hij',
'notes': 'Llevar demo del módulo de reportes'
}
)
result = response.json()
print(result['data']['id'])Respuesta exitosa
HTTP 201 Created
{
"data": {
"id": "nP7qRsWxYzAb",
"title": "Reunión de presentación de propuesta",
"type": "meeting",
"priority": "high",
"status": "pending",
"ownerId": "aB3kLmNpQrSt",
"ownerName": "María González",
"entityType": "deal",
"entityId": "xY9wVuTsRqPo",
"dueDate": "2026-04-20T15:00:00.000Z",
"durationMinutes": 60,
"meetingUrl": "https://meet.google.com/abc-defg-hij",
"notes": "Llevar demo del módulo de reportes",
"completedAt": null,
"customData": {},
"createdAt": "2026-04-09T10:00:00.000Z",
"updatedAt": "2026-04-09T10:00:00.000Z"
}
}Actualizar Actividad
PUT /activities/:idActualiza los campos de una actividad existente. Todos los campos son opcionales — solo se modifican los campos enviados.
Parámetros de ruta
| Parámetro | Tipo | Requerido | Descripción |
|---|---|---|---|
id | string | Sí | ID de la actividad |
Cuerpo de la solicitud
Los mismos campos que en , todos opcionales.
Ejemplo
curl -X PUT "https://api-crm.zelta.dev/public/v1/activities/nP7qRsWxYzAb" \
-H "Authorization: Bearer tu-api-token-aqui" \
-H "Content-Type: application/json" \
-d '{
"dueDate": "2026-04-21T15:00:00.000Z",
"notes": "Reprogramada para el día siguiente. Llevar también caso de éxito."
}'Ejemplo JS
const id = 'nP7qRsWxYzAb';
const response = await fetch(`https://api-crm.zelta.dev/public/v1/activities/${id}`, {
method: 'PUT',
headers: {
'Authorization': `Bearer ${process.env.ZELTA_API_TOKEN}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
dueDate: '2026-04-21T15:00:00.000Z',
notes: 'Reprogramada para el día siguiente. Llevar también caso de éxito.'
})
});
const result = await response.json();Ejemplo Py
import requests
activity_id = 'nP7qRsWxYzAb'
response = requests.put(
f'https://api-crm.zelta.dev/public/v1/activities/{activity_id}',
headers={
'Authorization': 'Bearer tu-api-token-aqui',
'Content-Type': 'application/json'
},
json={
'dueDate': '2026-04-21T15:00:00.000Z',
'notes': 'Reprogramada para el día siguiente. Llevar también caso de éxito.'
}
)
result = response.json()Respuesta exitosa
HTTP 200 OK — Retorna la actividad con los campos actualizados.
Eliminar Actividad
DELETE /activities/:idElimina una actividad de forma permanente (soft delete). La actividad deja de aparecer en listados y timelines.
Parámetros de ruta
| Parámetro | Tipo | Requerido | Descripción |
|---|---|---|---|
id | string | Sí | ID de la actividad |
Ejemplo
curl -X DELETE "https://api-crm.zelta.dev/public/v1/activities/nP7qRsWxYzAb" \
-H "Authorization: Bearer tu-api-token-aqui"Ejemplo JS
const id = 'nP7qRsWxYzAb';
const response = await fetch(`https://api-crm.zelta.dev/public/v1/activities/${id}`, {
method: 'DELETE',
headers: {
'Authorization': `Bearer ${process.env.ZELTA_API_TOKEN}`
}
});
const result = await response.json();
console.log(result.success); // trueEjemplo Py
import requests
activity_id = 'nP7qRsWxYzAb'
response = requests.delete(
f'https://api-crm.zelta.dev/public/v1/activities/{activity_id}',
headers={
'Authorization': 'Bearer tu-api-token-aqui'
}
)
result = response.json()
print(result['success']) # TrueRespuesta exitosa
HTTP 200 OK
{
"success": true
}Marcar como Completada
PATCH /activities/:id/completeMarca una actividad como completada. Establece completedAt a la fecha y hora actual y cambia el status a completed. No requiere cuerpo en la solicitud.
Parámetros de ruta
| Parámetro | Tipo | Requerido | Descripción |
|---|---|---|---|
id | string | Sí | ID de la actividad |
Sin cuerpo
Este endpoint no requiere body. Simplemente realiza el PATCH al path con autenticación.
Ejemplo
curl -X PATCH "https://api-crm.zelta.dev/public/v1/activities/V1StGXR8_Z5jdHi6B-myT/complete" \
-H "Authorization: Bearer tu-api-token-aqui"Ejemplo JS
const id = 'V1StGXR8_Z5jdHi6B-myT';
const response = await fetch(
`https://api-crm.zelta.dev/public/v1/activities/${id}/complete`,
{
method: 'PATCH',
headers: {
'Authorization': `Bearer ${process.env.ZELTA_API_TOKEN}`
}
}
);
const result = await response.json();
console.log(result.data.status); // "completed"
console.log(result.data.completedAt); // "2026-04-09T10:35:00.000Z"Ejemplo Py
import requests
activity_id = 'V1StGXR8_Z5jdHi6B-myT'
response = requests.patch(
f'https://api-crm.zelta.dev/public/v1/activities/{activity_id}/complete',
headers={
'Authorization': 'Bearer tu-api-token-aqui'
}
)
result = response.json()
print(result['data']['status']) # completed
print(result['data']['completedAt']) # 2026-04-09T10:35:00.000ZRespuesta exitosa
HTTP 200 OK
{
"data": {
"id": "V1StGXR8_Z5jdHi6B-myT",
"title": "Llamada de seguimiento",
"type": "call",
"priority": "high",
"status": "completed",
"ownerId": "aB3kLmNpQrSt",
"ownerName": "María González",
"entityType": "deal",
"entityId": "xY9wVuTsRqPo",
"dueDate": "2026-04-15T10:00:00.000Z",
"durationMinutes": 30,
"completedAt": "2026-04-09T10:35:00.000Z",
"createdAt": "2026-04-01T14:22:00.000Z",
"updatedAt": "2026-04-09T10:35:00.000Z"
}
}Campos de la respuesta
| Campo | Tipo | Descripción |
|---|---|---|
id | string | Identificador único de la actividad (nanoid) |
title | string | Título de la actividad |
description | string | null | Descripción detallada |
type | string | Tipo: call, task, meeting, email, note, lunch, deadline |
priority | string | Prioridad: low, medium, high |
status | string | Estado actual: pending, completed, overdue |
ownerId | string | null | ID del responsable |
ownerName | string | null | Nombre completo del responsable (resuelto por JOIN) |
entityType | string | null | Tipo de la entidad principal asociada |
entityId | string | null | ID de la entidad principal asociada |
dueDate | string | null | Fecha y hora de vencimiento (ISO 8601) |
durationMinutes | integer | null | Duración estimada en minutos |
location | string | null | Ubicación física |
meetingUrl | string | null | URL de videoconferencia |
notes | string | null | Notas internas |
completedAt | string | null | Fecha y hora de completado (ISO 8601). null si está pendiente |
customData | object | Datos personalizados adicionales |
createdAt | string | Fecha de creación (ISO 8601) |
updatedAt | string | Fecha de última actualización (ISO 8601) |
Problemas comunes
| Error | Causa | Solución |
|---|---|---|
401 Unauthorized | Token ausente, inválido o expirado | Verifica tu API token en Configuración > API Keys |
403 Forbidden | Sin permiso activities:read/create/update/delete | Revisa los permisos de la API key en tu workspace |
404 Not Found | La actividad no existe o fue eliminada | Verifica que el ID sea correcto y pertenezca a tu workspace |
400 — title requerido | Se omitió el campo title en la creación | Incluye un title de hasta 200 caracteres |
400 — type inválido | Se envió un tipo no reconocido | Usa uno de: call, task, meeting, email, note, lunch, deadline |
400 — entityId requerido | Se envió entityType sin entityId | Ambos campos deben enviarse juntos |
400 — meetingUrl inválido | La URL de videoconferencia no es válida | Asegúrate de incluir el protocolo (https://) |
400 — límite de entidades | El array entities supera 10 elementos | Reduce la cantidad de entidades adicionales a máx. 10 |
Siguientes pasos
- — Asocia actividades a tus contactos
- — Vincula actividades al pipeline de ventas
- — Encuentra actividades con el buscador unificado