Pular para o conteúdo principal
14 min de leitura

API Externa

A API Externa permite incorporar dados de análise do Zenovay em sites voltados ao cliente. Use sua chave de API para buscar contagens de visitantes em tempo real, resumos de análise, estatísticas de página e muito mais.

URL Base

Todas as solicitações da API Externa devem ser feitas para:

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

Autenticação

Os endpoints da API Externa requerem uma chave de API passada no cabeçalho da solicitação:

Cabeçalho da Chave 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'

Gere sua chave de API em Settings → Security → API keys. Cada chave pode ter permissões específicas (leitura, escrita, admin).

A API Externa requer um plano pago. Contas de camada gratuita recebem uma resposta 403 API_PAID_PLAN_REQUIRED em todos os endpoints. Atualize para Pro, Scale ou Enterprise para usar chaves de API programaticamente.

Endpoints de Conta

Obter Uso da Conta

Recupere estatísticas de uso e limites da sua conta:

GET/api/external/v1/usage

Obter uso da conta e limites

SolicitaçãoBash
curl -X GET 'https://api.zenovay.com/api/external/v1/usage' \
-H 'X-API-Key: YOUR_API_KEY'
Resposta (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"
}
}

Endpoints de Site

Listar Sites

Obtenha todos os sites vinculados à sua conta:

GET/api/external/v1/websites

Listar todos os sites rastreados

SolicitaçãoBash
curl -X GET 'https://api.zenovay.com/api/external/v1/websites' \
-H 'X-API-Key: YOUR_API_KEY'
Resposta (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
}

Obter Detalhes do Site

Recupere detalhes de um site específico:

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

Obter detalhes do site

SolicitaçãoBash
curl -X GET 'https://api.zenovay.com/api/external/v1/websites/ws_abc123' \
-H 'X-API-Key: YOUR_API_KEY'
Resposta (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
}
}

Endpoints de Análise

Obter Resumo de Análise

Recupere dados abrangentes de análise de um site:

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

Obter visão geral de análise

Parâmetros de Consulta:

ParâmetroTipoObrigatórioDescrição
timeRangestringNãoIntervalo de tempo: today, 7d, 30d, 90d (padrão: 7d)
SolicitaçãoBash
curl -X GET 'https://api.zenovay.com/api/external/v1/analytics/ws_abc123?timeRange=30d' \
-H 'X-API-Key: YOUR_API_KEY'
Resposta (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
}

Obter Dados de Visitantes

Recupere informações de visitantes com filtragem opcional:

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

Obter dados de visitantes

Parâmetros de Consulta:

ParâmetroTipoObrigatórioDescrição
timeRangestringNãoIntervalo de tempo: today, 7d, 30d, 90d
limitintegerNãoMáximo de resultados (padrão: 50, máximo: 100)
offsetintegerNãoDeslocamento de paginação
SolicitaçãoBash
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'
Resposta (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
}

Obter Análise de Página

Recupere estatísticas no nível da página:

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

Obter páginas principais

Parâmetros de Consulta:

ParâmetroTipoObrigatórioDescrição
timeRangestringNãoIntervalo de tempo: today, 7d, 30d, 90d
limitintegerNãoMáximo de resultados (padrão: 20)
SolicitaçãoBash
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'
Resposta (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
  }
]
}

Obter Dados Geográficos

Recupere dados de visitantes por país:

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

Obter decomposição geográfica

Parâmetros de Consulta:

ParâmetroTipoObrigatórioDescrição
timeRangestringNãoIntervalo de tempo: today, 7d, 30d, 90d
SolicitaçãoBash
curl -X GET 'https://api.zenovay.com/api/external/v1/analytics/ws_abc123/countries?timeRange=30d' \
-H 'X-API-Key: YOUR_API_KEY'
Resposta (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
  }
]
}

Obter Decomposição Tecnológica

Recupere estatísticas de dispositivo, navegador e SO:

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

Obter decomposição tecnológica

Parâmetros de Consulta:

ParâmetroTipoObrigatórioDescrição
timeRangestringNãoIntervalo de tempo: today, 7d, 30d, 90d
SolicitaçãoBash
curl -X GET 'https://api.zenovay.com/api/external/v1/analytics/ws_abc123/technology?timeRange=7d' \
-H 'X-API-Key: YOUR_API_KEY'
Resposta (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 }
]
}

Endpoints Avançados

Obter Páginas de Mapa de Calor

Liste páginas com dados de mapa de calor:

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

Listar páginas de mapa de calor

SolicitaçãoBash
curl -X GET 'https://api.zenovay.com/api/external/v1/heatmaps/ws_abc123/pages' \
-H 'X-API-Key: YOUR_API_KEY'
Resposta (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"
  }
]
}

Obter Reproduções de Sessão

Liste sessões registradas:

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

Listar reproduções de sessão

SolicitaçãoBash
curl -X GET 'https://api.zenovay.com/api/external/v1/replays/ws_abc123/sessions' \
-H 'X-API-Key: YOUR_API_KEY'
Resposta (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
}

Obter Grupos de Erro

Liste grupos de erro JavaScript:

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

Listar grupos de erro

SolicitaçãoBash
curl -X GET 'https://api.zenovay.com/api/external/v1/errors/ws_abc123/groups' \
-H 'X-API-Key: YOUR_API_KEY'
Resposta (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 Estatísticas (compatibilidade com Plausible, Pro+)

A API de Estatísticas expõe três endpoints compatíveis com Plausible para consultas de análise programáticas. Use-a para construir dashboards personalizados, incorporar métricas em tempo real em ferramentas de BI ou migrar do Plausible com alterações mínimas no código.

Plano obrigatório: Pro, Scale ou Enterprise. Como o resto da API Externa, contas de camada gratuita recebem uma resposta 403 API_PAID_PLAN_REQUIRED em todos os endpoints.

Endpoints

EndpointPropósito
GET /stats/aggregateMétricas de número único em um período (totais, taxas, durações).
GET /stats/timeseriesSérie dividida em buckets de tempo (uma linha por dia, hora ou mês).
GET /stats/breakdownMétricas agrupadas (páginas principais, países principais, navegadores principais, …).

Especificação OpenAPI: /api/external/v1/openapi.json (ao vivo, público, sem autenticação necessária para a especificação em si).

Parâmetros comuns

ParâmetroObrigatórioDescrição
site_idsimUUID do site. Encontre em sua URL do dashboard ou via GET /websites.
periodsimday, 7d, 30d, month, 6mo, 12mo ou custom:YYYY-MM-DD,YYYY-MM-DD (máximo 366 dias).
datenãoÂncora ISO 8601 para o período (padrão = hoje).
metricssimSeparados por vírgula. Permitidos: visitors, pageviews, visit_duration, bounce_rate, events.
filtersnãoEstilo Plausible: country==US;browser==Chrome;page!=/admin. Veja Filtros abaixo.

GET /stats/aggregate

Retorna valores de número único para cada métrica solicitada em um período.

GET/api/external/v1/stats/aggregate

Métricas agregadas em um período

Solicitação — visitantes e visualizações de página nos últimos 7 diasBash
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'
Resposta (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

Retorna uma linha por bucket em um período. O padrão é interval=day; interval=hour requer period=day; interval=month requer um period de 6mo, 12mo, month ou custom.

GET/api/external/v1/stats/timeseries

Série de métrica dividida em buckets de tempo

Solicitação — visitantes diários nos últimos 30 diasBash
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'
Resposta (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"
}

A resposta é densa — dias com zero tráfego ainda aparecem com visitors: 0. Isso mantém as bibliotecas de gráficos felizes sem preenchimento de lacunas no lado do cliente.

GET /stats/breakdown

Retorna métricas agrupadas por uma dimensão, classificadas por visitantes em ordem decrescente.

GET/api/external/v1/stats/breakdown

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

Solicitação — 10 principais páginas por visitantes nos últimos 7 diasBash
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'
Resposta (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 permitidos de property: event:page, visit:country, visit:browser, visit:device, visit:os, visit:source.

Paginação: limit é 1–1000 (padrão 100); page é indexado a partir de 1 (padrão 1).

Filtros

Cláusulas de filtro no estilo Plausible, unidas com ;:

  • country==US — igual
  • country==US,CA,GB — igual a um de
  • browser!=Safari — não igual

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

Limitação V1: Quando filters é fornecido, apenas a métrica visitors é calculada; outras métricas retornam null com um sinalizador meta.note. O suporte total de filtros em todas as métricas é lançado em V2.

Exemplo JavaScript

Buscar métricas agregadas com 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 erro

A API de Estatísticas retorna códigos que você pode usar para UX graciosa:

CódigoHTTPQuando
MISSING_SITE_ID400O parâmetro de consulta site_id é obrigatório.
MISSING_METRICS400O parâmetro de consulta metrics é obrigatório.
MISSING_PERIOD400O parâmetro de consulta period é obrigatório.
MISSING_PROPERTY400/stats/breakdown requer property.
INVALID_METRIC400Uma das métricas separadas por vírgula não está na lista de permitidos.
INVALID_PROPERTY400A propriedade de decomposição não é permitida.
INVALID_PERIOD400O período não é day/7d/30d/month/6mo/12mo/custom:....
INVALID_CUSTOM_PERIOD400Sintaxe custom: malformada ou data(s) inválida(s).
PERIOD_TOO_LONG400Período customizado > 366 dias.
INTERVAL_PERIOD_MISMATCH400Por exemplo, interval=hour com period=7d.
UNKNOWN_FILTER_KEY400A chave de filtro não está na lista de permitidos.
EMPTY_FILTER_VALUE400A cláusula de filtro não tem valor.
FORBIDDEN403Chave de camada gratuita chamando um endpoint Pro+, ou site_id fora do escopo da chave de API.
NOT_FOUND404O site não existe ou está oculto para esta chave.
(limite de taxa)429Limite de taxa por camada excedido. O cabeçalho Retry-After indica o tempo de espera.

Migrando do Plausible

O formato de parâmetro é intencionalmente compatível com Plausible:

PlausibleZenovayNotas
site_idsite_idPlausible usa uma string de domínio; Zenovay usa um UUID. Mapeie domain → site_id uma vez via GET /websites.
period, dateperiod, dateA mesma lista de permitidos + custom:YYYY-MM-DD,YYYY-MM-DD.
metricsmetricsvisitors, pageviews, bounce_rate, visit_duration do Plausible mapeiam 1:1 todas. events é aproximado em V1 como pageviews.
propertypropertyA mesma forma: event:page, visit:country, etc.
filters (v1 string)filtersA mesma forma key==value;key!=value. Filtros de array JSON v2 chegam em Zenovay V2.

Exemplo JavaScript

Incorpore dados de análise em seu site usando JavaScript:

Buscar e Exibir AnáliseJavaScript
// Buscar dados de análise do seu backend
async function fetchAnalytics() {
const response = await fetch('/api/analytics', {
  headers: {
    'X-API-Key': 'YOUR_API_KEY' // Use proxy no lado do servidor para proteger sua chave
  }
});

const data = await response.json();

// Atualizar sua UI
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) + '%';
}

// Atualizar a cada 30 segundos
fetchAnalytics();
setInterval(fetchAnalytics, 30000);

Nota de Segurança: Nunca exponha sua chave de API no código do lado do cliente. Crie um endpoint proxy no lado do servidor que chame a API do Zenovay com sua chave, depois tenha seu frontend chamar seu proxy.

Limites de Taxa

Limites de taxa da API Externa por plano:

PlanoSolicitações/Minuto (meta)Limite Mensal (limite máximo)
GratuitoN/A (API não disponível)N/A
Pro3010.000
Scale60100.000
Enterprise1201.000.000

Como a limitação de taxa é aplicada. O número por minuto é uma meta, não um limite máximo rígido. Usamos a limitação de taxa de borda do Cloudflare, que é por data center com uma pequena margem de explosão — um cliente sustentado pode transientemente ver 1,5–3× o número do título antes de ser limitado, especialmente quando as solicitações se espalham entre regiões. O limite máximo é a cota mensal, aplicada atomicamente em sua conta, independentemente de qual POP de borda sirva a solicitação. Planeje cargas de trabalho sensíveis à capacidade em relação à cota mensal; trate a meta por minuto como um sinal de suavização.

Respostas de Erro

Código de StatusDescrição
200Sucesso
400Solicitação Inválida - Parâmetros inválidos
401Não Autorizado - Chave de API inválida ou ausente
403Proibido - Permissões insuficientes
404Não Encontrado - Site não encontrado
429Muitas Solicitações - Limite de taxa excedido
500Erro Interno do Servidor
Exemplo de Resposta de ErroJSON
{
"error": {
  "code": "unauthorized",
  "message": "Invalid API key provided"
}
}

Próximos Passos

Esta página foi útil?