Ir al contenido

API · Estadísticas — lleva tus números a donde ya trabajas

Los endpoints de estadísticas te devuelven los mismos números que ves en la sección Estadísticas —leads, conversiones y rendimiento por publicación— para que los lleves a Looker Studio, Google Sheets, n8n o tu propio backend.

Esta página cubre solo esos endpoints. Cómo conseguir la clave, cómo autenticarte, la forma de las respuestas, el límite de peticiones y los errores comunes a toda la API están en API de ZeroChats. Empieza por ahí si es tu primera llamada.

La URL base es:

https://app.zerochats.com/api/statistics/v1

Todas las llamadas son GET y la clave viaja en la cabecera Authorization:

Ventana de terminal
curl -H "Authorization: Bearer zcst_tu_clave" \
https://app.zerochats.com/api/statistics/v1/overview

En estos endpoints meta viene siempre, y te dice qué periodo y qué zona horaria han producido los números:

{
"success": true,
"data": {},
"meta": {
"startDay": "2026-07-01",
"endDay": "2026-07-30",
"timezone": "Europe/Madrid"
}
}
EndpointAcepta fechasQué devuelve
/meNoEl negocio al que pertenece la clave y su zona horaria.
/overviewSíTotales históricos y reparto por etapa del embudo, separando entrantes y salientes.
/leads/dailySíUna fila por día: leads recibidos y hasta dónde llegaron.
/leads/by-weekdayNoReparto histórico de los leads inbound por día de la semana.
/leads/by-hourNoReparto histórico de los leads inbound por hora del día.
/conversions/goalsSíPor enlace de venta y día de envío: en Propuesta y convertidos.
/conversions/tagsSíLeads convertidos (Agendado o Pagado) por etiqueta y día.
/conversions/contentsSíPor contenido y día de envío: en Propuesta y convertidos.
/performanceSíRendimiento por publicación, anuncio u origen, con enlace al post.
/welcome-messagesSíMensajes de bienvenida enviados, respondidos y tasa de respuesta, por día.

Los tres endpoints que no aceptan fechas (/me, /leads/by-weekday y /leads/by-hour) cubren toda la historia del negocio. Si les mandas startDay y endDay no da error: simplemente los ignora, y lo notas porque meta viene sin fechas.

{
"lifetime": { "totalLeads": 1840, "positiveLeads": 213 },
"funnel": {
"inbound": [
{ "state": "OPEN_CONVERSATION", "count": 48 },
{ "state": "LEAD", "count": 21 },
{ "state": "CLIENT", "count": 7 }
],
"outbound": [{ "state": "IN_PROGRESS", "count": 12 }]
}
}

lifetime es histórico y no depende del rango que pidas: totalLeads son todos tus leads y positiveLeads los que están en Propuesta, Agendado o Pagado (la Propuesta realizada, no las conversiones).

funnel sí cubre el rango, y separa los leads entrantes (te escribieron ellos) de los salientes (empezaste tú la conversación). Van aparte a propósito: son dos formas distintas de captar y mezclarlas esconde cuál de las dos convierte.

Cada etapa llega por su nombre en inglés, igual que en el Webhook personalizado y en los endpoints de leads, y por el mismo motivo: los nombres son iguales en todas las cuentas trabajes en el idioma que trabajes, así que un filtro construido sobre ellos no se rompe.

Etapa en la appstate
AbiertaOPEN_CONVERSATION
DescubriendoIN_PROGRESS
CualificandoQUALIFYING
PropuestaLEAD
AgendadoBOOKED
PagadoCLIENT
PospuestoPOSTPONED
No cualificadoNO_QUALIFY
PerdidoLOST
[{ "date": "2026-07-01", "total": 34, "qualified": 6, "booked": 2, "paid": 1 }]
CampoQué es
dateEl día, en formato YYYY-MM-DD.
totalConversaciones de ese día: leads con los que habló tu IA, en el día de su último cambio de estado.
qualifiedDe esos, los que están hoy en Propuesta.
bookedDe esos, los que están hoy en Agendado.
paidDe esos, los que están hoy en Pagado.

Los días sin actividad vienen igualmente, con ceros, para que puedas pintar la serie tal cual sin rellenar huecos.

[{ "dayOfWeek": 0, "day": "MONDAY", "total": 240, "qualified": 31, "booked": 14 }]
[{ "hour": 9, "total": 88, "qualified": 12, "booked": 5 }]

dayOfWeek va de 0 (lunes) a 6 (domingo) y day te da el nombre para que no tengas que recordar la convención. hour va de 0 a 23. Ambos vienen siempre completos: los siete días y las veinticuatro horas, aunque alguna esté a cero.

Igual que los gráficos por día de la semana y por hora de Estadísticas, solo cuentan los leads que te escribieron ellos (inbound) y con los que habló tu IA, en el momento en que escribieron. Aquí qualified son los leads en Propuesta y booked agrupa Agendado y Pagado. No intentes cuadrar estos dos endpoints fila a fila con /leads/daily: responden a otra pregunta —a qué hora y qué día te escribe la gente— y no al recorrido de una cohorte.

/conversions/goals, /conversions/tags y /conversions/contents

Sección titulada «/conversions/goals, /conversions/tags y /conversions/contents»

Los tres devuelven la misma forma, una fila por entidad y día:

[
{
"date": "2026-07-14",
"id": "9f1c8a4e-2b77-4d0a-9d1c-3f2b6a5c7e10",
"name": "Sesión de valoración",
"leads": 4,
"clients": 1
}
]

name te llega ya resuelto —el nombre del enlace de venta, de la etiqueta o del contenido— para que no tengas que hacer una segunda consulta ni mantener tu propia tabla de equivalencias.

Una conversión es un lead que hoy está en Agendado o Pagado; la Propuesta no cuenta.

  • En /conversions/goals y /conversions/contents, cada fila es un día de envío: leads son las personas que recibieron el enlace o el contenido ese día y hoy están en Propuesta, y clients las que hoy están en Agendado o Pagado, es decir, las conversiones.
  • En /conversions/tags, leads son los leads con esa etiqueta que hoy están en Agendado o Pagado, y clients vale lo mismo: una etiqueta está puesta o no lo está, no hay una distinción entre lead y cliente que reportar. Hasta el 15 de octubre de 2026 este endpoint también contaba a los leads en Propuesta.

Una fila por publicación, anuncio u origen de los leads del periodo:

[
{
"kind": "media",
"id": "17900000000000000",
"name": null,
"mediaId": "17900000000000000",
"mediaType": "REELS",
"url": "https://www.instagram.com/reel/CxYzAbCdEfG/",
"leads": 120,
"answered": 86,
"qualified": 24,
"booked": 9,
"paid": 4,
"rates": { "answered": 71.67, "qualified": 20, "booked": 7.5, "paid": 3.33 }
}
]
CampoQué es
kindmedia (una publicación o un anuncio), personalized (un origen que has definido tú), inbound, outbound.
idIdentificador de la fila. En media es el de la publicación en Instagram.
nameEl nombre del origen personalizado. Vacío en el resto de filas.
mediaIdIdentificador de la publicación. null si la fila no es una publicación.
mediaTypeSTORY, FEED, REELS o AD. null si la fila no es una publicación.
urlEnlace público al post en Instagram. null si no lo conocemos.
leadsLeads que tocaron esa publicación u origen.
answeredDe esos, los que te escribieron por privado después de un mensaje tuyo. Los comentarios no cuentan.
qualifiedDe esos, los que llegaron a Propuesta, Agendado o Pagado.
bookedLos que están hoy en Agendado.
paidLos que están hoy en Pagado.
ratesEsos mismos cuatro números en porcentaje sobre leads, con dos decimales.

El url es la pieza que convierte un informe en algo accionable: cada fila de tu panel puede enlazar al post real, así que quien lo lee pasa del número al contenido de un clic. Es un enlace normal de Instagram, estable y público — no caduca.

qualified incluye a los que agendaron y a los que pagaron, así que se lee como un embudo: qualified es más ancho que booked y paid, que son excluyentes entre sí (un lead en Pagado no cuenta en booked). answered usa la misma definición de «Respondió» que la app —un DM del lead después de un mensaje tuyo, cuente o no después como Perdido—, explicada en Estadísticas e informes. La fila outbound va por el día en que se envió la bienvenida; el resto, por el último cambio de estado.

[{ "date": "2026-07-01", "sent": 40, "responded": 11, "responseRate": 27.5 }]

responseRate es el porcentaje de sent con dos decimales, y vale 0 los días en que no enviaste nada. Cada bienvenida cuenta en el día en que se envió, y responded sigue la definición de Respondió: los envíos de un día ya no cambian, pero sus respuestas aún pueden subir.

Los endpoints marcados como «Acepta fechas» reciben dos parámetros:

ParámetroFormatoQué es
startDayYYYY-MM-DDPrimer día, incluido.
endDayYYYY-MM-DDÚltimo día, incluido.
Ventana de terminal
curl -H "Authorization: Bearer zcst_tu_clave" \
"https://app.zerochats.com/api/statistics/v1/leads/daily?startDay=2026-07-01&endDay=2026-07-31"

Las reglas son cuatro:

  • Los dos días son días de calendario en la zona horaria de tu negocio, no marcas de tiempo. Si tu negocio está en Madrid, el 1 de julio va de las 00:00 a las 23:59 de Madrid, aunque tú lances la consulta desde México. Ese es el motivo de que meta.timezone viaje en todas las respuestas.
  • O mandas los dos, o no mandas ninguno. Mandar solo uno da error en vez de suponer el otro.
  • Si no mandas ninguno, te damos los últimos 30 días, hoy incluido.
  • El máximo son 366 días. Un rango más largo da error; parte la consulta en trozos.

Un ejemplo de las dos primeras reglas juntas: pedir startDay=2026-07-01&endDay=2026-07-31 te da julio entero, los 31 días, con la primera y la última fila incluidas. Pedir startDay=2026-07-31&endDay=2026-07-01 da error, porque el inicio tiene que ir antes que el final. Y pedir solo startDay=2026-07-01 también da error, con el mensaje startDay and endDay must be provided together.

Todos esos errores llegan como 400 con error.code a invalid_request: fecha con formato incorrecto, solo uno de los dos días, orden invertido o rango de más de 366 días.

Si necesitas muchos días, pide un rango amplio en una sola llamada en vez de un día por petición: los endpoints por día ya te devuelven la serie completa, y una llamada de 30 días es más rápida y más barata que 30 llamadas de un día.

Ejemplo práctico: informe semanal de contenido

Sección titulada «Ejemplo práctico: informe semanal de contenido»

Un caso real y completo: cada lunes quieres saber qué publicaciones te trajeron clientes la semana pasada, con enlace a cada post para poder repasarlas.

  1. Calcula el rango. Del lunes anterior al domingo anterior, en formato YYYY-MM-DD. Por ejemplo startDay=2026-08-17 y endDay=2026-08-23.

  2. Llama a /performance con ese rango.

    Ventana de terminal
    curl -H "Authorization: Bearer zcst_tu_clave" \
    "https://app.zerochats.com/api/statistics/v1/performance?startDay=2026-08-17&endDay=2026-08-23"
  3. Quédate con las filas kind: "media". Son las publicaciones y los anuncios; inbound y outbound son las bolsas generales y no te sirven para este informe.

  4. Ordena por paid —o por rates.paid si te interesa más la eficiencia que el volumen— y quédate con las cinco primeras.

  5. Monta el mensaje usando url. Cada línea lleva el enlace al post, así que quien lo lee puede abrirlo sin buscarlo.

    Top contenidos del 17 al 23 de agosto
    1. REELS — 120 leads · 4 clientes (3,33 %) → https://www.instagram.com/reel/CxYzAbCdEfG/
    2. FEED — 86 leads · 3 clientes (3,49 %) → https://www.instagram.com/p/CxAbCdEfGhI/
  6. Publícalo donde lo vayas a leer: un canal de Slack, un email o una fila nueva en una hoja de cálculo.

Si quieres añadir contexto de negocio a ese mismo informe, llama también a /leads/daily con el mismo rango para el volumen total de la semana, y a /conversions/goals para saber qué enlace de venta cerró esos clientes.

  • Guarda la zona horaria de meta junto a los datos si los almacenas. Un número sin saber en qué calendario está medido no se puede comparar con otro más adelante.
  • Usa id como clave, no name. Los nombres de etiquetas, contenidos y enlaces de venta se pueden cambiar desde la app; los identificadores no.
  • Pide rangos, no días sueltos. Una llamada de 30 días es más rápida y más barata que 30 llamadas de un día.

Los problemas con la clave —un 401 recién copiada, una clave que deja de funcionar— están en API de ZeroChats. Estos son los propios de las estadísticas.

Los números no coinciden con lo que veo en Estadísticas

Sección titulada «Los números no coinciden con lo que veo en Estadísticas»

Casi siempre es el rango. Repasa que estés pidiendo los mismos días —recuerda que ambos extremos van incluidos— y mira meta.timezone: si tu herramienta calcula las fechas en su propia zona horaria y tu negocio está en otra, estarás comparando periodos ligeramente distintos.

En /leads/by-weekday y /leads/by-hour hay además una diferencia de criterio deliberada, explicada más arriba: booked incluye ahí también a los que ya han pagado.

/performance me devuelve más leads de los que tengo

Sección titulada «/performance me devuelve más leads de los que tengo»

Es lo esperado y está explicado más arriba: un lead que ha tocado varias publicaciones cuenta en todas. Para el total del negocio, usa /overview o /leads/daily.

Algunas filas de /performance traen url a null

Sección titulada «Algunas filas de /performance traen url a null»

Significa que no tenemos el enlace público de esa publicación —suele pasar con contenidos antiguos o eliminados—. Muestra la fila igual usando mediaType como etiqueta, pero sin enlace.