Campañas
Endpoints para iniciar, controlar, programar y listar campañas de llamadas.
La misma referencia, en otras dos formas
· Probar los endpoints — esta misma información,
desplegable y con botón para ejecutar las consultas de lectura contra tu
organización.
· Ciclo de vida de una campaña — si
buscabas el recorrido completo en orden en vez del contrato suelto.
Base URL: https://api.neuronstudio.ai
Autenticación: API Key (X-API-Key) o JWT (Authorization: Bearer).
Las mutaciones (start, start-upload, stop, pause, resume, schedule, delete)
requieren scope full; una key con scope read recibe 403.
No existe modo sandbox / dry-run. Un start exitoso dispara llamadas reales
de inmediato. Para probar sin impacto, usa una lista de 1 contacto con tu propio
número, fuera de horario productivo.
Cómo detectar éxito: cualquier código 2xx. Los códigos exactos de éxito
pueden variar entre endpoints y cambiar entre versiones de la API (por ejemplo,
un endpoint que acepta trabajo asincrónico puede responder 200, 201 o 202).
No compares el código por igualdad exacta (if status == 200). Verifica el
rango: if 200 <= status < 300, o usa el helper de tu cliente HTTP
(resp.ok en JavaScript, resp.raise_for_status() en requests). Los códigos
de éxito que aparecen en los ejemplos de abajo son ilustrativos, no un contrato.
Índice
Columnas CSV requeridas por tipo de campaña
La lista de leads se entrega como CSV. Las columnas requeridas dependen del
campaign_type:
campaign_type |
Columnas requeridas |
collections (default) |
to_number, lead_id, client_name, debt |
sdr |
to_number, lead_id, client_name |
cx |
to_number, lead_id, client_name |
interviewer |
to_number, lead_id, client_name, position |
Reglas del CSV:
to_number: teléfono en formato E.164 (+525512345678 — empieza con +,
incluye código de país, sin espacios ni guiones).
lead_id: identificador único por lead.
client_name: nombre del cliente.
debt: monto de deuda (solo collections).
- Las columnas extra (ej.
Fecha_Limite_Pago) se preservan y se pasan al
motor de llamadas.
- Tamaño máximo del CSV: 10 MB.
- Las filas sin
to_number o sin lead_id se saltan.
- Puedes descargar la plantilla con
GET /api/csv-template?type=<tipo>.
POST /api/campaign/start
Inicia una campaña con el CSV embebido como texto en el body JSON.
| Atributo |
Valor |
| URL completa |
https://api.neuronstudio.ai/api/campaign/start |
| Autenticación |
API Key / JWT |
| Scope |
full |
| Rate limit |
5 solicitudes / min por organización |
Body (JSON)
| Campo |
Tipo |
Requerido |
Descripción |
name |
string |
Sí |
Nombre de la campaña (1–255 caracteres). |
csv_content |
string |
Sí |
Texto CSV literal (con saltos de línea \n). No base64, no ruta. Máx 10 MB. |
agent_id |
string |
No |
Agente a usar. Si se omite, usa el agente por defecto de la organización. |
campaign_type |
string |
No |
collections (default), sdr, cx o interviewer. |
customer_email |
string |
No |
Email para notificaciones al finalizar. |
Ejemplo de request
API_BASE_URL="https://api.neuronstudio.ai"
curl -s -X POST "$API_BASE_URL/api/campaign/start" \
-H "X-API-Key: nrn_live_0123456789abcdef0123456789abcdef" \
-H "Content-Type: application/json" \
-d '{
"name": "Cobranza Enero",
"csv_content": "to_number,lead_id,client_name,debt\n+525512345678,L001,Juan,5000",
"agent_id": "agent_abc123",
"campaign_type": "collections",
"customer_email": "ops@cliente.com"
}'
Ejemplo de response (éxito — 2xx)
{
"success": true,
"campaign_id": 123,
"total_leads": 150,
"agent_id": "agent_abc123",
"campaign_type": "collections",
"message": "Campaign 'Cobranza Enero' started"
}
Trata cualquier 2xx como éxito y lee el body; no compares el código por
igualdad exacta.
Guarda el campaign_id: lo necesitas para monitorear, controlar y consultar
resultados. La campaña empieza a llamar de inmediato.
Códigos de error
| Código |
Cuándo ocurre |
400 |
CSV inválido, name ausente, o body mal formado. |
401 |
No autenticado. |
403 |
Scope read (se requiere full), o el agent_id no está asignado a tu organización. |
409 |
Ya hay una campaña corriendo (límite de campañas activas). |
422 |
El tipo de campaña no está habilitado para tu organización. |
429 |
Más de 5 inicios en un minuto. No incluye Retry-After — usa backoff exponencial. |
POST /api/campaign/start-upload
Igual que start, pero subiendo un archivo .csv vía multipart/form-data en
lugar de pegar el texto. Validación y comportamiento idénticos.
| Atributo |
Valor |
| URL completa |
https://api.neuronstudio.ai/api/campaign/start-upload |
| Autenticación |
API Key / JWT |
| Scope |
full |
| Rate limit |
5 solicitudes / min por organización |
| Campo |
Tipo |
Requerido |
Descripción |
file |
archivo |
Sí |
Archivo .csv binario (máx 10 MB). |
name |
string |
Sí |
Nombre de la campaña. |
agent_id |
string |
No |
Agente a usar (default de la org si se omite). |
campaign_type |
string |
No |
collections (default), sdr, cx o interviewer. |
customer_email |
string |
No |
Email para notificaciones. |
Ejemplo de request
API_BASE_URL="https://api.neuronstudio.ai"
curl -s -X POST "$API_BASE_URL/api/campaign/start-upload" \
-H "X-API-Key: nrn_live_0123456789abcdef0123456789abcdef" \
-F "file=@leads.csv" \
-F "name=Cobranza Enero" \
-F "agent_id=agent_abc123" \
-F "campaign_type=collections"
Con Python:
import requests
API_BASE_URL = "https://api.neuronstudio.ai"
headers = {"X-API-Key": "nrn_live_0123456789abcdef0123456789abcdef"}
with open("leads.csv", "rb") as f:
resp = requests.post(
f"{API_BASE_URL}/api/campaign/start-upload",
headers=headers,
files={"file": ("leads.csv", f, "text/csv")},
data={"name": "Cobranza Enero", "agent_id": "agent_abc123"},
)
print(resp.json())
Ejemplo de response (éxito — 2xx)
Idéntica a start (mismo criterio: cualquier 2xx es éxito):
{
"success": true,
"campaign_id": 123,
"total_leads": 150,
"agent_id": "agent_abc123",
"campaign_type": "collections",
"message": "Campaign 'Cobranza Enero' started"
}
Códigos de error
Mismas semánticas que start (400 / 401 / 403 / 409 / 422 / 429).
El 400 incluye el caso de archivo vacío, ilegible o mayor a 10 MB.
GET /api/campaign/status
Estado en tiempo real de la campaña activa de tu organización.
| Atributo |
Valor |
| URL completa |
https://api.neuronstudio.ai/api/campaign/status |
| Autenticación |
API Key / JWT |
| Scope |
lectura |
| Rate limit |
— |
Ejemplo de request
API_BASE_URL="https://api.neuronstudio.ai"
curl -s "$API_BASE_URL/api/campaign/status" \
-H "X-API-Key: nrn_live_0123456789abcdef0123456789abcdef"
Ejemplo de response (200)
{
"success": true,
"status": {
"state": "running",
"campaign_id": 123,
"active_calls": 3,
"queue_size": 45
},
"campaign": {
"id": 123,
"name": "Cobranza Enero",
"total_leads": 150,
"leads_called": 105,
"leads_pending": 45,
"status": "running"
},
"global_status": {
"total_active_calls": 15,
"available_slots": 35
}
}
Cuando no hay campaña activa, status.state es "idle" y campaign es null.
| Campo |
Significado |
status.state |
running o idle. |
status.active_calls |
Llamadas en curso en este momento. |
status.queue_size |
Leads esperando en cola. |
Códigos de error
| Código |
Cuándo ocurre |
401 |
No autenticado. |
POST /api/campaign/stop
Detiene la campaña activa de forma permanente. No se puede reanudar; los
resultados generados hasta ese momento quedan guardados.
| Atributo |
Valor |
| URL completa |
https://api.neuronstudio.ai/api/campaign/stop |
| Autenticación |
API Key / JWT |
| Scope |
full |
| Rate limit |
— |
Body (JSON)
| Campo |
Tipo |
Requerido |
Descripción |
campaign_id |
integer |
Sí |
ID de la campaña a detener. |
Ejemplo de request
API_BASE_URL="https://api.neuronstudio.ai"
curl -s -X POST "$API_BASE_URL/api/campaign/stop" \
-H "X-API-Key: nrn_live_0123456789abcdef0123456789abcdef" \
-H "Content-Type: application/json" \
-d '{ "campaign_id": 123 }'
Ejemplo de response (200)
{ "success": true, "message": "Campaign stopped", "campaign_id": 123 }
Códigos de error
| Código |
Cuándo ocurre |
401 |
No autenticado. |
403 |
Scope read (se requiere full). |
404 |
No existe una campaña con ese campaign_id en tu organización. |
POST /api/campaign/pause
Pausa la campaña activa. Las llamadas en curso terminan normalmente, no se inician
nuevas y la cola se preserva. Se puede reanudar con resume.
| Atributo |
Valor |
| URL completa |
https://api.neuronstudio.ai/api/campaign/pause |
| Autenticación |
API Key / JWT |
| Scope |
full |
| Rate limit |
— |
Body (JSON)
| Campo |
Tipo |
Requerido |
Descripción |
campaign_id |
integer |
Sí |
ID de la campaña a pausar. |
Ejemplo de request
API_BASE_URL="https://api.neuronstudio.ai"
curl -s -X POST "$API_BASE_URL/api/campaign/pause" \
-H "X-API-Key: nrn_live_0123456789abcdef0123456789abcdef" \
-H "Content-Type: application/json" \
-d '{ "campaign_id": 123 }'
Ejemplo de response (200)
{ "success": true, "message": "Campaign paused", "campaign_id": 123 }
Códigos de error
| Código |
Cuándo ocurre |
401 |
No autenticado. |
403 |
Scope read (se requiere full). |
404 |
No existe una campaña con ese campaign_id en tu organización. |
POST /api/campaign/resume
Reanuda una campaña pausada.
| Atributo |
Valor |
| URL completa |
https://api.neuronstudio.ai/api/campaign/resume |
| Autenticación |
API Key / JWT |
| Scope |
full |
| Rate limit |
— |
Body (JSON)
| Campo |
Tipo |
Requerido |
Descripción |
campaign_id |
integer |
Sí |
ID de la campaña a reanudar. |
Ejemplo de request
API_BASE_URL="https://api.neuronstudio.ai"
curl -s -X POST "$API_BASE_URL/api/campaign/resume" \
-H "X-API-Key: nrn_live_0123456789abcdef0123456789abcdef" \
-H "Content-Type: application/json" \
-d '{ "campaign_id": 123 }'
Ejemplo de response (200)
{ "success": true, "message": "Campaign resumed", "campaign_id": 123 }
Códigos de error
| Código |
Cuándo ocurre |
401 |
No autenticado. |
403 |
Scope read (se requiere full). |
404 |
No existe una campaña pausada con ese campaign_id en tu organización. |
POST /api/campaign/schedule
Programa una campaña para que arranque en una fecha/hora futura.
| Atributo |
Valor |
| URL completa |
https://api.neuronstudio.ai/api/campaign/schedule |
| Autenticación |
API Key / JWT |
| Scope |
full |
| Rate limit |
10 solicitudes / 5 min por organización |
Body (JSON)
| Campo |
Tipo |
Requerido |
Descripción |
name |
string |
Sí |
Nombre de la campaña (1–255 caracteres). |
csv_content |
string |
Sí |
Texto CSV literal (máx 10 MB). |
scheduled_at |
string |
Sí |
Fecha/hora de inicio en ISO 8601 (ej. 2026-02-20T09:00:00Z). |
agent_id |
string |
No |
Agente a usar (default de la org si se omite). |
campaign_type |
string |
No |
collections (default), sdr, cx o interviewer. |
customer_email |
string |
No |
Email para notificaciones. |
Ejemplo de request
API_BASE_URL="https://api.neuronstudio.ai"
curl -s -X POST "$API_BASE_URL/api/campaign/schedule" \
-H "X-API-Key: nrn_live_0123456789abcdef0123456789abcdef" \
-H "Content-Type: application/json" \
-d '{
"name": "Cobranza Febrero",
"csv_content": "to_number,lead_id,client_name,debt\n+525512345678,L001,Juan,5000",
"scheduled_at": "2026-02-20T09:00:00Z",
"agent_id": "agent_abc123",
"campaign_type": "collections"
}'
Ejemplo de response (201)
{
"success": true,
"campaign_id": 124,
"scheduled_at": "2026-02-20T09:00:00+00:00",
"total_leads": 150
}
Estos cuatro campos son todo lo que devuelve el endpoint: no hay
campaign_type ni message en la respuesta. El scheduled_at que te devolvemos
es el que mandaste, normalizado a ISO 8601 con offset numérico (+00:00), no
con sufijo Z; si lo enviaste sin zona horaria, se interpreta como UTC.
Códigos de error
| Código |
Cuándo ocurre |
400 |
CSV inválido, name o scheduled_at ausente, o fecha mal formada. |
401 |
No autenticado. |
403 |
Scope read (se requiere full), o agent_id no asignado a tu organización. |
422 |
El tipo de campaña no está habilitado para tu organización. |
429 |
Más de 10 programaciones en 5 minutos. No incluye Retry-After — usa backoff exponencial. |
GET /api/campaign/scheduled
Lista las campañas programadas (aún no iniciadas) de tu organización.
| Atributo |
Valor |
| URL completa |
https://api.neuronstudio.ai/api/campaign/scheduled |
| Autenticación |
API Key / JWT |
| Scope |
lectura |
| Rate limit |
— |
Ejemplo de request
API_BASE_URL="https://api.neuronstudio.ai"
curl -s "$API_BASE_URL/api/campaign/scheduled" \
-H "X-API-Key: nrn_live_0123456789abcdef0123456789abcdef"
Ejemplo de response (200)
⚠️ Este endpoint devuelve un array JSON directo, no un objeto envolvente.
No hay campo success ni campo scheduled: el cuerpo es la lista. Si tu
cliente hace resp.json()["scheduled"] va a fallar. Usa resp.json() tal cual
y recórrelo. Cuando no hay campañas programadas, el cuerpo es [].
[
{
"id": 124,
"name": "Cobranza Febrero",
"status": "scheduled",
"scheduled_at": "2026-02-20T09:00:00+00:00",
"total_leads": 150,
"campaign_type": "collections",
"agent_id": "agent_abc123",
"created_at": "2026-02-14T18:32:05+00:00"
}
]
Campos de cada elemento
| Campo |
Tipo |
Descripción |
id |
integer |
ID de la campaña programada. Se llama id, no campaign_id. Es el valor que va en el path de DELETE /api/campaign/scheduled/{campaign_id}. |
name |
string |
Nombre de la campaña. |
status |
string |
Siempre "scheduled" — el endpoint sólo lista campañas programadas que aún no arrancaron. |
scheduled_at |
string |
Fecha/hora de arranque en ISO 8601 con offset numérico (+00:00), no con sufijo Z. Parsea con un parser ISO 8601 real; no compares strings. |
total_leads |
integer |
Cantidad de leads cargados. |
campaign_type |
string |
collections, sdr, cx o interviewer. |
agent_id |
string | null |
Agente asignado. Es null si la campaña se programó sin agente explícito. |
created_at |
string |
Fecha/hora de creación de la campaña, mismo formato que scheduled_at. |
La lista viene ordenada por scheduled_at ascendente (la próxima a arrancar,
primero).
Códigos de error
| Código |
Cuándo ocurre |
401 |
No autenticado. |
DELETE /api/campaign/scheduled/{campaign_id}
Cancela una campaña programada antes de que arranque.
| Atributo |
Valor |
| URL completa |
https://api.neuronstudio.ai/api/campaign/scheduled/{campaign_id} |
| Autenticación |
API Key / JWT |
| Scope |
full |
| Rate limit |
— |
Parámetros de path
| Parámetro |
Tipo |
Requerido |
Descripción |
campaign_id |
integer |
Sí |
ID de la campaña programada a cancelar. |
Ejemplo de request
API_BASE_URL="https://api.neuronstudio.ai"
curl -s -X DELETE "$API_BASE_URL/api/campaign/scheduled/124" \
-H "X-API-Key: nrn_live_0123456789abcdef0123456789abcdef"
Ejemplo de response (200)
{ "success": true, "message": "Scheduled campaign cancelled", "campaign_id": 124 }
Códigos de error
| Código |
Cuándo ocurre |
401 |
No autenticado. |
403 |
Scope read (se requiere full). |
404 |
No existe una campaña programada con ese campaign_id en tu organización. |
GET /api/campaigns
Lista las campañas de tu organización. Se puede filtrar por tipo.
| Atributo |
Valor |
| URL completa |
https://api.neuronstudio.ai/api/campaigns |
| Autenticación |
API Key / JWT |
| Scope |
lectura |
| Rate limit |
100 solicitudes / min |
Parámetros de query
| Parámetro |
Tipo |
Requerido |
Descripción |
type |
string |
No |
Filtra por campaign_type: collections, sdr, cx o interviewer. |
Ejemplo de request
API_BASE_URL="https://api.neuronstudio.ai"
curl -s "$API_BASE_URL/api/campaigns?type=collections" \
-H "X-API-Key: nrn_live_0123456789abcdef0123456789abcdef"
Ejemplo de response (200)
{
"success": true,
"campaigns": [
{
"campaign_id": 123,
"name": "Cobranza Enero",
"campaign_type": "collections",
"status": "completed",
"total_leads": 150
},
{
"campaign_id": 124,
"name": "Cobranza Febrero",
"campaign_type": "collections",
"status": "scheduled",
"total_leads": 150
}
]
}
Códigos de error
| Código |
Cuándo ocurre |
401 |
No autenticado. |
429 |
Más de 100 solicitudes en un minuto. Incluye Retry-After. |
GET /api/csv-template
Descarga una plantilla CSV con las columnas correctas para un tipo de campaña.
| Atributo |
Valor |
| URL completa |
https://api.neuronstudio.ai/api/csv-template |
| Autenticación |
API Key / JWT |
| Scope |
lectura |
| Rate limit |
— |
Parámetros de query
| Parámetro |
Tipo |
Requerido |
Descripción |
type |
string |
No |
Tipo de campaña: collections (default), sdr, cx o interviewer. |
Ejemplo de request
API_BASE_URL="https://api.neuronstudio.ai"
curl -s "$API_BASE_URL/api/csv-template?type=collections" \
-H "X-API-Key: nrn_live_0123456789abcdef0123456789abcdef" \
-o plantilla_collections.csv
Ejemplo de response (200)
Cuerpo: texto CSV con la fila de cabecera correspondiente al tipo. Por ejemplo,
para collections:
to_number,lead_id,client_name,debt
+525512345678,L001,Juan Pérez,5000
Códigos de error
| Código |
Cuándo ocurre |
401 |
No autenticado. |
400 |
type no es un tipo de campaña válido. |
GET /api/campaigns/{campaign_id}/skip-log
Devuelve a quién no se llamó y por qué, para una campaña dada.
Antes de armar la cola de discado, la plataforma descarta contactos que no corresponde llamar:
quien ya se comprometió a pagar, quien tiene una devolución agendada, quien pidió no ser
contactado. Cada descarte queda registrado con su motivo.
Es el endpoint que responde la pregunta "subí 5.000 contactos y veo 4.200 llamadas, ¿qué pasó
con los otros 800?".
Parámetros de path
| Parámetro |
Tipo |
Descripción |
campaign_id |
integer |
ID de la campaña, el que devolvió start. |
Parámetros de query
| Parámetro |
Tipo |
Default |
Descripción |
limit |
integer |
500 |
Máximo de filas de detalle a devolver. No afecta a counts ni a total_skipped. |
Ejemplo de request
curl "https://api.neuronstudio.ai/api/campaigns/123/skip-log" \
-H "X-API-Key: nrn_live_abcdef1234567890abcdef1234567890"
Ejemplo de response (200)
{
"rows": [
{
"id": 9012,
"campaign_id": 123,
"contact_phone": "+525512345678",
"contact_id": "3f1c8a2e-1b4d-4c7a-9f21-8e0b5d6a7c93",
"reason": "promise_future",
"detail": "Payment promised for 2026-08-25",
"skipped_at": "2026-08-17T14:02:11+00:00"
}
],
"counts": {
"promise_future": 512,
"callback_pending": 203,
"refused": 85
},
"total_skipped": 800
}
Campos de la respuesta
| Campo |
Descripción |
rows |
Detalle contacto por contacto, del más reciente al más antiguo, acotado por limit. |
counts |
Desglose agregado por motivo. Sin acotar por limit — es el número real. |
total_skipped |
Suma de counts. El total de descartes de la campaña. |
Para reportar, usa counts y total_skipped. rows sirve para auditar casos puntuales.
Campos de cada fila de rows:
| Campo |
Tipo |
Descripción |
id |
integer |
Identificador del registro de descarte. |
campaign_id |
integer |
La campaña que intentó llamar. |
contact_phone |
string |
Teléfono en formato E.164. |
contact_id |
string | null |
Identificador interno del contacto. Puede venir nulo. |
reason |
string |
Motivo, en formato de máquina. Ver tabla abajo. |
detail |
string | null |
Explicación en texto de ese caso puntual. |
skipped_at |
string |
Fecha y hora del descarte, ISO 8601 con zona. |
Motivos posibles (reason)
| Valor |
Qué pasó |
promise_future |
Ya se comprometió a pagar en una fecha futura. |
promise_recent |
Se comprometió sin fecha, y sigue dentro del plazo de gracia. |
callback_pending |
Tiene una devolución de llamada agendada. |
cooldown_answered |
Ya atendió una llamada por ese mismo crédito en las últimas 24 horas. |
refused |
Pidió no ser contactado. |
unreachable |
Marcado como inalcanzable de forma permanente. |
retry_backoff |
Agotó los reintentos, o está esperando el próximo turno. |
Códigos de error
| Código |
Cuándo ocurre |
401 |
No autenticado. |
403 |
La credencial no alcanza para esa campaña. |
404 |
No existe una campaña con ese ID en tu organización. |
Un total_skipped en 0 significa que no se descartó a nadie, no que el registro haya
fallado. Si tu CSV y tus llamadas no cuadran y el skip-log está vacío, la diferencia está en el
CSV: las filas sin to_number o sin lead_id se descartan antes de llegar a este registro.