Saltar al contenido principal
14 min de lectura

API Externa

La API Externa te permite incrustar datos de análisis de Zenovay en sitios web orientados al cliente. Usa tu clave de API para obtener conteos de visitantes en vivo, resúmenes de análisis, estadísticas de páginas y más.

URL Base

Todos las solicitudes a la API Externa deben realizarse a:

https://api.zenovay.com/api/external/v1

Autenticación

Los puntos finales de la API Externa requieren una clave de API pasada en el encabezado de la solicitud:

Encabezado de Clave de APIBash
curl -X GET 'https://api.zenovay.com/api/external/v1/websites' \
-H 'X-API-Key: YOUR_API_KEY' \
-H 'Content-Type: application/json'

Genera tu clave de API en Settings → Security → API keys. Cada clave puede tener permisos específicos (lectura, escritura, administrador).

La API Externa requiere un plan de pago. Las cuentas de nivel gratuito reciben una respuesta 403 API_PAID_PLAN_REQUIRED en cada punto final. Actualiza a Pro, Scale o Enterprise para usar claves de API de forma programática.

Puntos Finales de Cuenta

Obtener Uso de Cuenta

Recupera las estadísticas de uso y límites de tu cuenta:

GET/api/external/v1/usage

Obtener uso de cuenta y límites

SolicitudBash
curl -X GET 'https://api.zenovay.com/api/external/v1/usage' \
-H 'X-API-Key: YOUR_API_KEY'
Respuesta (200 OK)JSON
{
"usage": {
  "websites": 5,
  "pageviews_this_month": 125000,
  "events_this_month": 45000
},
"limits": {
  "websites": 10,
  "pageviews_per_month": 500000,
  "events_per_month": 100000
},
"plan": "pro",
"period": {
  "start": "2025-01-01T00:00:00Z",
  "end": "2025-01-31T23:59:59Z"
}
}

Puntos Finales de Sitios Web

Listar Sitios Web

Obtén todos los sitios web vinculados a tu cuenta:

GET/api/external/v1/websites

Listar todos los sitios web rastreados

SolicitudBash
curl -X GET 'https://api.zenovay.com/api/external/v1/websites' \
-H 'X-API-Key: YOUR_API_KEY'
Respuesta (200 OK)JSON
{
"websites": [
  {
    "id": "ws_abc123",
    "domain": "example.com",
    "name": "Example Website",
    "tracking_code": "ZV_XXXXXXXXXXX",
    "created_at": "2025-01-01T00:00:00Z",
    "live_visitors": 42
  },
  {
    "id": "ws_def456",
    "domain": "shop.example.com",
    "name": "Example Shop",
    "tracking_code": "ZV_YYYYYYYYYYY",
    "created_at": "2025-01-10T00:00:00Z",
    "live_visitors": 18
  }
],
"total": 2
}

Obtener Detalles del Sitio Web

Recupera los detalles de un sitio web específico:

GET/api/external/v1/websites/:websiteId

Obtener detalles del sitio web

SolicitudBash
curl -X GET 'https://api.zenovay.com/api/external/v1/websites/ws_abc123' \
-H 'X-API-Key: YOUR_API_KEY'
Respuesta (200 OK)JSON
{
"website": {
  "id": "ws_abc123",
  "domain": "example.com",
  "name": "Example Website",
  "tracking_code": "ZV_XXXXXXXXXXX",
  "created_at": "2025-01-01T00:00:00Z",
  "settings": {
    "track_outbound_links": true,
    "track_downloads": true,
    "session_replay": true
  }
},
"stats": {
  "live_visitors": 42,
  "today_pageviews": 1234,
  "today_visitors": 567
}
}

Puntos Finales de Análisis

Obtener Resumen de Análisis

Recupera datos de análisis completos para un sitio web:

GET/api/external/v1/analytics/:websiteId

Obtener descripción general del análisis

Parámetros de Consulta:

ParámetroTipoRequeridoDescripción
timeRangestringNoRango de tiempo: today, 7d, 30d, 90d (predeterminado: 7d)
SolicitudBash
curl -X GET 'https://api.zenovay.com/api/external/v1/analytics/ws_abc123?timeRange=30d' \
-H 'X-API-Key: YOUR_API_KEY'
Respuesta (200 OK)JSON
{
"summary": {
  "visitors": 12543,
  "pageviews": 45231,
  "sessions": 15420,
  "bounce_rate": 0.42,
  "avg_session_duration": 185,
  "pages_per_session": 2.9
},
"period": {
  "start": "2024-12-21T00:00:00Z",
  "end": "2025-01-20T23:59:59Z"
},
"live_visitors": 42
}

Obtener Datos de Visitantes

Recupera información de visitantes con filtrado opcional:

GET/api/external/v1/analytics/:websiteId/visitors

Obtener datos de visitantes

Parámetros de Consulta:

ParámetroTipoRequeridoDescripción
timeRangestringNoRango de tiempo: today, 7d, 30d, 90d
limitintegerNoResultados máximos (predeterminado: 50, máximo: 100)
offsetintegerNoDesplazamiento de paginación
SolicitudBash
curl -X GET 'https://api.zenovay.com/api/external/v1/analytics/ws_abc123/visitors?timeRange=7d&limit=10' \
-H 'X-API-Key: YOUR_API_KEY'
Respuesta (200 OK)JSON
{
"visitors": [
  {
    "visitor_id": "vis_abc123",
    "first_seen": "2025-01-15T10:00:00Z",
    "last_seen": "2025-01-20T14:30:00Z",
    "total_sessions": 8,
    "total_pageviews": 45,
    "value_score": 87,
    "country": "US",
    "device": "desktop"
  }
],
"total": 1234,
"limit": 10,
"offset": 0
}

Obtener Análisis de Páginas

Recupera estadísticas a nivel de página:

GET/api/external/v1/analytics/:websiteId/pages

Obtener páginas principales

Parámetros de Consulta:

ParámetroTipoRequeridoDescripción
timeRangestringNoRango de tiempo: today, 7d, 30d, 90d
limitintegerNoResultados máximos (predeterminado: 20)
SolicitudBash
curl -X GET 'https://api.zenovay.com/api/external/v1/analytics/ws_abc123/pages?timeRange=7d&limit=10' \
-H 'X-API-Key: YOUR_API_KEY'
Respuesta (200 OK)JSON
{
"pages": [
  {
    "path": "/",
    "title": "Home",
    "views": 5423,
    "unique_visitors": 3241,
    "avg_time_on_page": 125,
    "bounce_rate": 0.35
  },
  {
    "path": "/pricing",
    "title": "Pricing",
    "views": 2134,
    "unique_visitors": 1876,
    "avg_time_on_page": 210,
    "bounce_rate": 0.28
  }
]
}

Obtener Datos Geográficos

Recupera datos de visitantes por país:

GET/api/external/v1/analytics/:websiteId/countries

Obtener desglose geográfico

Parámetros de Consulta:

ParámetroTipoRequeridoDescripción
timeRangestringNoRango de tiempo: today, 7d, 30d, 90d
SolicitudBash
curl -X GET 'https://api.zenovay.com/api/external/v1/analytics/ws_abc123/countries?timeRange=30d' \
-H 'X-API-Key: YOUR_API_KEY'
Respuesta (200 OK)JSON
{
"countries": [
  {
    "code": "US",
    "name": "United States",
    "visitors": 4521,
    "percentage": 36.1
  },
  {
    "code": "GB",
    "name": "United Kingdom",
    "visitors": 1823,
    "percentage": 14.5
  },
  {
    "code": "DE",
    "name": "Germany",
    "visitors": 1456,
    "percentage": 11.6
  }
]
}

Obtener Desglose Tecnológico

Recupera estadísticas de dispositivos, navegadores y sistemas operativos:

GET/api/external/v1/analytics/:websiteId/technology

Obtener desglose tecnológico

Parámetros de Consulta:

ParámetroTipoRequeridoDescripción
timeRangestringNoRango de tiempo: today, 7d, 30d, 90d
SolicitudBash
curl -X GET 'https://api.zenovay.com/api/external/v1/analytics/ws_abc123/technology?timeRange=7d' \
-H 'X-API-Key: YOUR_API_KEY'
Respuesta (200 OK)JSON
{
"devices": [
  { "type": "desktop", "visitors": 7234, "percentage": 57.7 },
  { "type": "mobile", "visitors": 4521, "percentage": 36.1 },
  { "type": "tablet", "visitors": 788, "percentage": 6.3 }
],
"browsers": [
  { "name": "Chrome", "visitors": 6543, "percentage": 52.2 },
  { "name": "Safari", "visitors": 3421, "percentage": 27.3 },
  { "name": "Firefox", "visitors": 1234, "percentage": 9.8 }
],
"operating_systems": [
  { "name": "Windows", "visitors": 4521, "percentage": 36.1 },
  { "name": "macOS", "visitors": 3234, "percentage": 25.8 },
  { "name": "iOS", "visitors": 2876, "percentage": 22.9 }
]
}

Puntos Finales Avanzados

Obtener Páginas de Mapa de Calor

Listar páginas con datos de mapa de calor:

GET/api/external/v1/heatmaps/:websiteId/pages

Listar páginas del mapa de calor

SolicitudBash
curl -X GET 'https://api.zenovay.com/api/external/v1/heatmaps/ws_abc123/pages' \
-H 'X-API-Key: YOUR_API_KEY'
Respuesta (200 OK)JSON
{
"pages": [
  {
    "url": "/",
    "title": "Home",
    "total_clicks": 12543,
    "total_sessions": 4521,
    "last_updated": "2025-01-20T14:30:00Z"
  },
  {
    "url": "/pricing",
    "title": "Pricing",
    "total_clicks": 8765,
    "total_sessions": 2134,
    "last_updated": "2025-01-20T14:25:00Z"
  }
]
}

Obtener Reproducciones de Sesión

Listar sesiones grabadas:

GET/api/external/v1/replays/:websiteId/sessions

Listar reproducciones de sesión

SolicitudBash
curl -X GET 'https://api.zenovay.com/api/external/v1/replays/ws_abc123/sessions' \
-H 'X-API-Key: YOUR_API_KEY'
Respuesta (200 OK)JSON
{
"sessions": [
  {
    "session_id": "sess_abc123",
    "visitor_id": "vis_xyz789",
    "started_at": "2025-01-20T14:00:00Z",
    "duration": 245,
    "pages_visited": 5,
    "country": "US",
    "device": "desktop"
  }
],
"total": 156
}

Obtener Grupos de Errores

Listar grupos de errores de JavaScript:

GET/api/external/v1/errors/:websiteId/groups

Listar grupos de errores

SolicitudBash
curl -X GET 'https://api.zenovay.com/api/external/v1/errors/ws_abc123/groups' \
-H 'X-API-Key: YOUR_API_KEY'
Respuesta (200 OK)JSON
{
"groups": [
  {
    "fingerprint": "err_abc123",
    "message": "Cannot read property 'length' of undefined",
    "type": "TypeError",
    "occurrences": 45,
    "affected_users": 23,
    "first_seen": "2025-01-15T10:00:00Z",
    "last_seen": "2025-01-20T14:30:00Z"
  }
],
"total": 12
}

API de Estadísticas (compatibilidad con Plausible, Pro+)

La API de Estadísticas expone tres puntos finales compatibles con Plausible para consultas de análisis programáticas. Úsalos para crear paneles personalizados, incrustar métricas en vivo en herramientas de BI o migrar desde Plausible con cambios de código mínimos.

Plan requerido: Pro, Scale o Enterprise. Al igual que el resto de la API Externa, las cuentas de nivel gratuito reciben una respuesta 403 API_PAID_PLAN_REQUIRED.

Puntos Finales

Punto FinalPropósito
GET /stats/aggregateMétricas de un único número durante un período (totales, tasas, duraciones).
GET /stats/timeseriesSeries agrupadas por tiempo (una fila por día, hora o mes).
GET /stats/breakdownMétricas agrupadas por dimensión (páginas principales, países principales, navegadores principales, …).

Especificación OpenAPI: /api/external/v1/openapi.json (en vivo, público, no requiere autenticación para la especificación en sí).

Parámetros comunes

ParámetroRequeridoDescripción
site_idUUID del sitio web. Encuéntralo en la URL de tu panel o mediante GET /websites.
periodday, 7d, 30d, month, 6mo, 12mo, o custom:YYYY-MM-DD,YYYY-MM-DD (máximo 366 días).
datenoAncla ISO 8601 para el período (predeterminado = hoy).
metricsSeparados por comas. Permitidos: visitors, pageviews, visit_duration, bounce_rate, events.
filtersnoEstilo Plausible: country==US;browser==Chrome;page!=/admin. Ver Filtros abajo.

GET /stats/aggregate

Devuelve valores de un solo número para cada métrica solicitada durante un período.

GET/api/external/v1/stats/aggregate

Métricas agregadas durante un período

Solicitud — visitantes y páginas vistas en los últimos 7 díasBash
curl -G 'https://api.zenovay.com/api/external/v1/stats/aggregate' \
-H 'X-API-Key: YOUR_API_KEY' \
--data-urlencode 'site_id=00000000-0000-0000-0000-000000000001' \
--data-urlencode 'period=7d' \
--data-urlencode 'metrics=visitors,pageviews,bounce_rate'
Respuesta (200 OK)JSON
{
"success": true,
"data": {
  "results": {
    "visitors":    { "value": 12453 },
    "pageviews":   { "value": 38219 },
    "bounce_rate": { "value": 42.1 }
  },
  "meta": {
    "period": "7d",
    "period_start": "2026-05-07T00:00:00.000Z",
    "period_end":   "2026-05-13T23:59:59.999Z",
    "filters_applied": []
  }
},
"timestamp": "2026-05-14T08:30:00.000Z"
}

GET /stats/timeseries

Devuelve una fila por cubo durante el período. El predeterminado es interval=day; interval=hour requiere period=day; interval=month requiere un period de 6mo, 12mo, month, o custom.

GET/api/external/v1/stats/timeseries

Series de métricas agrupadas por tiempo

Solicitud — visitantes diarios en los últimos 30 díasBash
curl -G 'https://api.zenovay.com/api/external/v1/stats/timeseries' \
-H 'X-API-Key: YOUR_API_KEY' \
--data-urlencode 'site_id=00000000-0000-0000-0000-000000000001' \
--data-urlencode 'period=30d' \
--data-urlencode 'metrics=visitors,pageviews' \
--data-urlencode 'interval=day'
Respuesta (200 OK)JSON
{
"success": true,
"data": {
  "results": [
    { "date": "2026-04-14", "visitors": 1820, "pageviews": 5640 },
    { "date": "2026-04-15", "visitors": 1933, "pageviews": 5921 }
  ],
  "meta": {
    "period": "30d",
    "interval": "day",
    "period_start": "2026-04-14T00:00:00.000Z",
    "period_end":   "2026-05-13T23:59:59.999Z",
    "filters_applied": []
  }
},
"timestamp": "2026-05-14T08:30:00.000Z"
}

La respuesta es densa — los días con cero tráfico aún aparecen con visitors: 0. Esto mantiene felices las bibliotecas de gráficos sin necesidad de llenar espacios en el lado del cliente.

GET /stats/breakdown

Devuelve métricas agrupadas por una dimensión, ordenadas por visitantes en orden descendente.

GET/api/external/v1/stats/breakdown

Métricas agrupadas (páginas principales, países principales, …)

Solicitud — 10 páginas principales por visitantes en los últimos 7 díasBash
curl -G 'https://api.zenovay.com/api/external/v1/stats/breakdown' \
-H 'X-API-Key: YOUR_API_KEY' \
--data-urlencode 'site_id=00000000-0000-0000-0000-000000000001' \
--data-urlencode 'period=7d' \
--data-urlencode 'property=event:page' \
--data-urlencode 'metrics=visitors,pageviews' \
--data-urlencode 'limit=10'
Respuesta (200 OK)JSON
{
"success": true,
"data": {
  "results": [
    { "page": "/pricing",      "visitors": 4421, "pageviews": 4421 },
    { "page": "/blog/launch",  "visitors": 2018, "pageviews": 2018 }
  ],
  "meta": {
    "period": "7d",
    "property": "event:page",
    "pagination": { "page": 1, "limit": 10, "total": 47, "has_more": true }
  }
},
"timestamp": "2026-05-14T08:30:00.000Z"
}

Valores de property permitidos: event:page, visit:country, visit:browser, visit:device, visit:os, visit:source.

Paginación: limit es 1–1000 (predeterminado 100); page es 1-indexado (predeterminado 1).

Filtros

Cláusulas de filtro estilo Plausible, unidas con ;:

  • country==US — igual a
  • country==US,CA,GB — igual a uno de
  • browser!=Safari — no es igual a

Claves permitidas: country, browser, device, os, source, utm_source, utm_medium, utm_campaign, page.

Limitación de V1: Cuando se proporciona filters, solo se calcula la métrica visitors; otras métricas devuelven null con una bandera meta.note. El soporte de filtros completo en todas las métricas llega en V2.

Ejemplo de JavaScript

Obtener métricas agregadas con fetch()JavaScript
async function getAggregate(siteId, period = '7d', metrics = ['visitors', 'pageviews']) {
const url = new URL('https://api.zenovay.com/api/external/v1/stats/aggregate');
url.searchParams.set('site_id', siteId);
url.searchParams.set('period', period);
url.searchParams.set('metrics', metrics.join(','));

const res = await fetch(url, {
  headers: { 'X-API-Key': process.env.ZENOVAY_API_KEY }
});
if (!res.ok) {
  const err = await res.json();
  throw new Error(`${err.error.code}: ${err.error.message}`);
}
return res.json();
}

const data = await getAggregate('00000000-0000-0000-0000-000000000001', '7d');
console.log(`Visitors: ${data.data.results.visitors.value}`);

Códigos de error

La API de Estadísticas devuelve códigos en los que puedes cambiar para una UX elegante:

CódigoHTTPCuándo
MISSING_SITE_ID400El parámetro de consulta site_id es requerido.
MISSING_METRICS400El parámetro de consulta metrics es requerido.
MISSING_PERIOD400El parámetro de consulta period es requerido.
MISSING_PROPERTY400/stats/breakdown requiere property.
INVALID_METRIC400Una de las métricas separadas por comas no está en la lista permitida.
INVALID_PROPERTY400La propiedad de desglose no está permitida.
INVALID_PERIOD400El período no es day/7d/30d/month/6mo/12mo/custom:....
INVALID_CUSTOM_PERIOD400Sintaxis de custom: con formato incorrecto o fechas inválidas.
PERIOD_TOO_LONG400Período personalizado > 366 días.
INTERVAL_PERIOD_MISMATCH400Por ejemplo, interval=hour con period=7d.
UNKNOWN_FILTER_KEY400La clave de filtro no está en la lista permitida.
EMPTY_FILTER_VALUE400La cláusula de filtro no tiene valor.
FORBIDDEN403Cuenta de nivel gratuito (la API Externa requiere un plan de pago), o site_id fuera del ámbito de la clave de API.
NOT_FOUND404El sitio no existe u está oculto para esta clave.
(límite de velocidad)429Límite de velocidad por nivel excedido. El encabezado Retry-After indica el tiempo de espera.

Migración desde Plausible

La forma de los parámetros es intencionalmente compatible con Plausible:

PlausibleZenovayNotas
site_idsite_idPlausible usa una cadena de dominio; Zenovay usa un UUID. Mapea domain → site_id una vez mediante GET /websites.
period, dateperiod, dateMisma lista permitida + custom:YYYY-MM-DD,YYYY-MM-DD.
metricsmetricsLos visitors, pageviews, bounce_rate, visit_duration de Plausible se asignan 1:1. events se aproxima como pageviews en V1.
propertypropertyMisma forma: event:page, visit:country, etc.
filters (cadena v1)filtersMisma forma key==value;key!=value. Los filtros de matriz JSON v2 llegan en Zenovay V2.

Ejemplo de JavaScript

Incrustar datos de análisis en tu sitio web usando JavaScript:

Obtener y Mostrar AnálisisJavaScript
// Obtener datos de análisis desde tu backend
async function fetchAnalytics() {
const response = await fetch('/api/analytics', {
  headers: {
    'X-API-Key': 'YOUR_API_KEY' // Usa un proxy del lado del servidor para proteger tu clave
  }
});

const data = await response.json();

// Actualizar tu interfaz
document.getElementById('live-visitors').textContent = data.live_visitors;
document.getElementById('total-pageviews').textContent = data.summary.pageviews.toLocaleString();
document.getElementById('bounce-rate').textContent = (data.summary.bounce_rate * 100).toFixed(1) + '%';
}

// Actualizar cada 30 segundos
fetchAnalytics();
setInterval(fetchAnalytics, 30000);

Nota de Seguridad: Nunca expongas tu clave de API en código del lado del cliente. Crea un punto final proxy del lado del servidor que llame a la API de Zenovay con tu clave, luego haz que tu frontend llame a tu proxy.

Límites de Velocidad

Límites de velocidad de la API Externa por plan:

PlanSolicitudes/Minuto (objetivo)Límite Mensual (límite estricto)
GratuitoN/A (API no disponible)N/A
Pro3010,000
Scale60100,000
Enterprise1201,000,000

Cómo se aplica la limitación de velocidad. El número por minuto es un objetivo, no un techo duro. Usamos el límite de velocidad de borde de Cloudflare, que es por centro de datos con una pequeña tolerancia de ráfaga — un cliente sostenido puede ver transitoriamente 1.5–3× el número del titular antes de ser limitado, especialmente cuando las solicitudes se distribuyen en regiones. El límite estricto es la cuota mensual, aplicada atómicamente contra tu cuenta independientemente de qué POP de borde sirva la solicitud. Planifica cargas de trabajo sensibles a la capacidad contra la cuota mensual; trata el objetivo por minuto como una señal de suavizado.

Respuestas de Error

Código de EstadoDescripción
200Éxito
400Solicitud Incorrecta - Parámetros inválidos
401No Autorizado - Clave de API inválida o faltante
403Prohibido - Permisos insuficientes
404No Encontrado - Sitio web no encontrado
429Demasiadas Solicitudes - Límite de velocidad excedido
500Error Interno del Servidor
Ejemplo de Respuesta de ErrorJSON
{
"error": {
  "code": "unauthorized",
  "message": "Invalid API key provided"
}
}

Siguientes Pasos

¿Fue útil esta página?