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:
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:
/api/external/v1/usageObter uso da conta e limites
curl -X GET 'https://api.zenovay.com/api/external/v1/usage' \
-H 'X-API-Key: YOUR_API_KEY'{
"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:
/api/external/v1/websitesListar todos os sites rastreados
curl -X GET 'https://api.zenovay.com/api/external/v1/websites' \
-H 'X-API-Key: YOUR_API_KEY'{
"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:
/api/external/v1/websites/:websiteIdObter detalhes do site
curl -X GET 'https://api.zenovay.com/api/external/v1/websites/ws_abc123' \
-H 'X-API-Key: YOUR_API_KEY'{
"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:
/api/external/v1/analytics/:websiteIdObter visão geral de análise
Parâmetros de Consulta:
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
timeRange | string | Não | Intervalo de tempo: today, 7d, 30d, 90d (padrão: 7d) |
curl -X GET 'https://api.zenovay.com/api/external/v1/analytics/ws_abc123?timeRange=30d' \
-H 'X-API-Key: YOUR_API_KEY'{
"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:
/api/external/v1/analytics/:websiteId/visitorsObter dados de visitantes
Parâmetros de Consulta:
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
timeRange | string | Não | Intervalo de tempo: today, 7d, 30d, 90d |
limit | integer | Não | Máximo de resultados (padrão: 50, máximo: 100) |
offset | integer | Não | Deslocamento de paginação |
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'{
"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:
/api/external/v1/analytics/:websiteId/pagesObter páginas principais
Parâmetros de Consulta:
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
timeRange | string | Não | Intervalo de tempo: today, 7d, 30d, 90d |
limit | integer | Não | Máximo de resultados (padrão: 20) |
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'{
"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:
/api/external/v1/analytics/:websiteId/countriesObter decomposição geográfica
Parâmetros de Consulta:
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
timeRange | string | Não | Intervalo de tempo: today, 7d, 30d, 90d |
curl -X GET 'https://api.zenovay.com/api/external/v1/analytics/ws_abc123/countries?timeRange=30d' \
-H 'X-API-Key: YOUR_API_KEY'{
"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:
/api/external/v1/analytics/:websiteId/technologyObter decomposição tecnológica
Parâmetros de Consulta:
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
timeRange | string | Não | Intervalo de tempo: today, 7d, 30d, 90d |
curl -X GET 'https://api.zenovay.com/api/external/v1/analytics/ws_abc123/technology?timeRange=7d' \
-H 'X-API-Key: YOUR_API_KEY'{
"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:
/api/external/v1/heatmaps/:websiteId/pagesListar páginas de mapa de calor
curl -X GET 'https://api.zenovay.com/api/external/v1/heatmaps/ws_abc123/pages' \
-H 'X-API-Key: YOUR_API_KEY'{
"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:
/api/external/v1/replays/:websiteId/sessionsListar reproduções de sessão
curl -X GET 'https://api.zenovay.com/api/external/v1/replays/ws_abc123/sessions' \
-H 'X-API-Key: YOUR_API_KEY'{
"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:
/api/external/v1/errors/:websiteId/groupsListar grupos de erro
curl -X GET 'https://api.zenovay.com/api/external/v1/errors/ws_abc123/groups' \
-H 'X-API-Key: YOUR_API_KEY'{
"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
| Endpoint | Propósito |
|---|---|
GET /stats/aggregate | Métricas de número único em um período (totais, taxas, durações). |
GET /stats/timeseries | Série dividida em buckets de tempo (uma linha por dia, hora ou mês). |
GET /stats/breakdown | Mé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âmetro | Obrigatório | Descrição |
|---|---|---|
site_id | sim | UUID do site. Encontre em sua URL do dashboard ou via GET /websites. |
period | sim | day, 7d, 30d, month, 6mo, 12mo ou custom:YYYY-MM-DD,YYYY-MM-DD (máximo 366 dias). |
date | não | Âncora ISO 8601 para o período (padrão = hoje). |
metrics | sim | Separados por vírgula. Permitidos: visitors, pageviews, visit_duration, bounce_rate, events. |
filters | não | Estilo 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.
/api/external/v1/stats/aggregateMétricas agregadas em um período
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'{
"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.
/api/external/v1/stats/timeseriesSérie de métrica dividida em buckets de tempo
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'{
"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.
/api/external/v1/stats/breakdownMétricas agrupadas (páginas principais, países principais, …)
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'{
"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— igualcountry==US,CA,GB— igual a um debrowser!=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
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ódigo | HTTP | Quando |
|---|---|---|
MISSING_SITE_ID | 400 | O parâmetro de consulta site_id é obrigatório. |
MISSING_METRICS | 400 | O parâmetro de consulta metrics é obrigatório. |
MISSING_PERIOD | 400 | O parâmetro de consulta period é obrigatório. |
MISSING_PROPERTY | 400 | /stats/breakdown requer property. |
INVALID_METRIC | 400 | Uma das métricas separadas por vírgula não está na lista de permitidos. |
INVALID_PROPERTY | 400 | A propriedade de decomposição não é permitida. |
INVALID_PERIOD | 400 | O período não é day/7d/30d/month/6mo/12mo/custom:.... |
INVALID_CUSTOM_PERIOD | 400 | Sintaxe custom: malformada ou data(s) inválida(s). |
PERIOD_TOO_LONG | 400 | Período customizado > 366 dias. |
INTERVAL_PERIOD_MISMATCH | 400 | Por exemplo, interval=hour com period=7d. |
UNKNOWN_FILTER_KEY | 400 | A chave de filtro não está na lista de permitidos. |
EMPTY_FILTER_VALUE | 400 | A cláusula de filtro não tem valor. |
FORBIDDEN | 403 | Chave de camada gratuita chamando um endpoint Pro+, ou site_id fora do escopo da chave de API. |
NOT_FOUND | 404 | O site não existe ou está oculto para esta chave. |
| (limite de taxa) | 429 | Limite 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:
| Plausible | Zenovay | Notas |
|---|---|---|
site_id | site_id | Plausible usa uma string de domínio; Zenovay usa um UUID. Mapeie domain → site_id uma vez via GET /websites. |
period, date | period, date | A mesma lista de permitidos + custom:YYYY-MM-DD,YYYY-MM-DD. |
metrics | metrics | visitors, pageviews, bounce_rate, visit_duration do Plausible mapeiam 1:1 todas. events é aproximado em V1 como pageviews. |
property | property | A mesma forma: event:page, visit:country, etc. |
filters (v1 string) | filters | A 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 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:
| Plano | Solicitações/Minuto (meta) | Limite Mensal (limite máximo) |
|---|---|---|
| Gratuito | N/A (API não disponível) | N/A |
| Pro | 30 | 10.000 |
| Scale | 60 | 100.000 |
| Enterprise | 120 | 1.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 Status | Descrição |
|---|---|
| 200 | Sucesso |
| 400 | Solicitação Inválida - Parâmetros inválidos |
| 401 | Não Autorizado - Chave de API inválida ou ausente |
| 403 | Proibido - Permissões insuficientes |
| 404 | Não Encontrado - Site não encontrado |
| 429 | Muitas Solicitações - Limite de taxa excedido |
| 500 | Erro Interno do Servidor |
{
"error": {
"code": "unauthorized",
"message": "Invalid API key provided"
}
}Próximos Passos
- Widgets - Incorpore widgets prontos para usar em seu site
- Dados em Tempo Real - Acesse dados de visitantes em tempo real sem autenticação
- Limites de Taxa - Entenda a limitação de taxa da API