Getting Started with the Zenovay API
This guide walks you through generating an API key, making your first request, and understanding the response format so you can start building integrations with Zenovay analytics data.
Prerequisites
Before you begin, you need:
- A Zenovay account with at least one tracked website
- A website with the Zenovay tracking script installed and receiving data
- cURL or any HTTP client (Postman, Insomnia, or your language of choice)
Opcional: usar a coleção do Bruno
Prefere um cliente gráfico? O Zenovay oferece uma coleção do Bruno de código aberto cobrindo todos os endpoints públicos, com exemplos de requisições, formatos de resposta e autenticação pré-configurada.
curl -O https://docs.zenovay.com/downloads/bruno-zenovay-collection.zip
unzip bruno-zenovay-collection.zip
# Abra a pasta bruno-zenovay-collection/ no app Bruno desktop.
# Escolha o ambiente "production", cole sua API key no arquivo local
# .env (gitignored — nunca commitado), e já pode chamar qualquer endpoint.Step 1: Generate an API Key
API keys are managed from your Zenovay dashboard.
- Log in at app.zenovay.com
- Navigate to Settings > API Keys
- Click Create New Key
- Give your key a descriptive name (e.g., "Custom Dashboard" or "Data Pipeline")
- Select the permission level:
- Full Access -- access all websites in your team
- Site Access -- access a single specific website
- Click Generate and copy your key immediately
Your API key is shown only once. Store it securely -- you cannot retrieve it later. If you lose a key, revoke it and generate a new one.
Step 2: Make Your First API Call
The simplest endpoint to test with is GET /usage, which returns your account usage and limits.
Base URL
All External API requests use:
https://api.zenovay.com/api/external/v1
Authentication
Pass your API key in the X-API-Key header:
curl -X GET 'https://api.zenovay.com/api/external/v1/usage' \
-H 'X-API-Key: YOUR_API_KEY'You should receive a response like this:
{
"success": true,
"data": {
"api_key": {
"id": "key_abc123",
"name": "Custom Dashboard",
"permission": "full_access",
"website_id": null
},
"usage": {
"monthly_requests": 42,
"monthly_limit": 10000,
"monthly_remaining": 9958,
"monthly_reset_at": "2026-03-01T00:00:00.000Z",
"total_requests": 1250
},
"rate_limits": {
"requests_per_minute": 30
},
"subscription": {
"tier": "pro"
}
},
"timestamp": "2026-02-07T12:00:00.000Z"
}Step 3: Understand the Response Envelope
Every External API response follows the same envelope structure:
{
"success": true,
"data": { ... },
"timestamp": "2026-02-07T12:00:00.000Z"
}| Field | Type | Description |
|---|---|---|
success | boolean | true for successful requests, false for errors |
data | object | The response payload -- varies by endpoint |
timestamp | string | ISO 8601 timestamp of the response |
Error responses include an error field instead of data:
{
"success": false,
"error": {
"code": "unauthorized",
"message": "Invalid API key provided"
},
"timestamp": "2026-02-07T12:00:00.000Z"
}Step 4: List Your Websites
Now fetch the websites accessible with your API key:
curl -X GET 'https://api.zenovay.com/api/external/v1/websites' \
-H 'X-API-Key: YOUR_API_KEY'{
"success": true,
"data": {
"websites": [
{
"id": "ws_abc123",
"domain": "example.com",
"name": "Example Website",
"tracking_code": "ZV_XXXXXXXXXXX",
"is_active": true,
"created_at": "2026-01-01T00:00:00Z",
"team_id": "team_xyz"
}
],
"total": 1
},
"timestamp": "2026-02-07T12:00:00.000Z"
}Copy the id field (e.g., ws_abc123) -- you will use it in analytics endpoints.
Step 5: Fetch Analytics Data
Use the website ID to get an analytics overview:
curl -X GET 'https://api.zenovay.com/api/external/v1/analytics/ws_abc123?range=7d' \
-H 'X-API-Key: YOUR_API_KEY'The range query parameter controls the time window:
| Value | Period |
|---|---|
24h | Last 24 hours |
7d | Last 7 days (default) |
30d | Last 30 days |
90d | Last 90 days |
1y | Last year |
{
"success": true,
"data": {
"website": {
"id": "ws_abc123",
"domain": "example.com",
"name": "Example Website"
},
"time_range": "7d",
"date_range": {
"start": "2026-01-31",
"end": "2026-02-07"
},
"summary": {
"total_visitors": 12543,
"total_page_views": 45231,
"unique_visitors": 8920
},
"daily_stats": [
{
"date": "2026-01-31",
"total_visitors": 1823,
"page_views": 6542,
"unique_visitors": 1290
}
]
},
"timestamp": "2026-02-07T12:00:00.000Z"
}Authentication Methods
The primary authentication method is the X-API-Key header:
curl -H 'X-API-Key: YOUR_API_KEY' \
'https://api.zenovay.com/api/external/v1/websites'Always use the X-API-Key header. Never expose your API key in client-side JavaScript -- use a server-side proxy instead.
Rate Limits
Rate limits vary by subscription plan:
| Plan | Requests/Minute | Monthly Requests |
|---|---|---|
| Free | 10 | 1,000 |
| Pro | 30 | 10,000 |
| Scale | 60 | 100,000 |
| Enterprise | 120 | 1,000,000 |
When you exceed the rate limit, you receive a 429 Too Many Requests response. The response includes a Retry-After header indicating how many seconds to wait.
async function fetchWithRetry(url, headers, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
const response = await fetch(url, { headers });
if (response.status === 429) {
const retryAfter = parseInt(response.headers.get('Retry-After') || '60', 10);
console.log(`Rate limited. Retrying in ${retryAfter}s...`);
await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
continue;
}
return response.json();
}
throw new Error('Max retries exceeded');
}Error Handling
Common error codes and how to handle them:
| Status | Code | Meaning | Action |
|---|---|---|---|
| 400 | bad_request | Invalid parameters | Check query parameters and request body |
| 401 | unauthorized | Invalid or missing API key | Verify your API key is correct and active |
| 403 | forbidden | Key does not have access | Use a key with the correct scope/permission |
| 404 | not_found | Website not found | Check the website ID is correct |
| 429 | rate_limited | Too many requests | Wait and retry with backoff |
| 500 | internal_error | Server error | Retry after a short delay |
async function callZenovayAPI(endpoint) {
const response = await fetch(
`https://api.zenovay.com/api/external/v1${endpoint}`,
{ headers: { 'X-API-Key': process.env.ZENOVAY_API_KEY } }
);
const result = await response.json();
if (!result.success) {
const error = result.error;
switch (response.status) {
case 401:
throw new Error('Invalid API key -- check your credentials');
case 403:
throw new Error(`Access denied: ${error.message}`);
case 404:
throw new Error(`Not found: ${error.message}`);
case 429:
throw new Error('Rate limited -- slow down requests');
default:
throw new Error(`API error: ${error.message}`);
}
}
return result.data;
}Available Endpoints
Here is a summary of all External API endpoints:
Account
| Method | Endpoint | Description |
|---|---|---|
| GET | /usage | Account usage and limits |
Websites
| Method | Endpoint | Description |
|---|---|---|
| GET | /websites | List all accessible websites |
| GET | /websites/:websiteId | Get website details |
Analytics
| Method | Endpoint | Description |
|---|---|---|
| GET | /analytics/:websiteId | Analytics overview with daily stats |
| GET | /analytics/:websiteId/visitors | Visitor records with pagination |
| GET | /analytics/:websiteId/pages | Top pages by views |
| GET | /analytics/:websiteId/countries | Geographic breakdown |
| GET | /analytics/:websiteId/technology | Device, browser, OS stats |
Advanced
| Method | Endpoint | Description |
|---|---|---|
| GET | /heatmaps/:websiteId/pages | Pages with heatmap data |
| GET | /replays/:websiteId/sessions | Session replay recordings |
| GET | /errors/:websiteId/groups | JavaScript error groups |
Public (No Auth Required)
| Method | Endpoint | Description |
|---|---|---|
| GET | /e/live/:trackingCode | Live visitor count |
Next Steps
- Building a Custom Dashboard -- Use the API to build your own analytics UI
- Server-Side Analytics -- Node.js and Python wrapper classes
- Webhook and Real-Time Data -- Polling strategies and live data
- API Prompts for AI Assistants -- Copy-paste prompts to build with AI
- External API Reference -- Full endpoint documentation