Externe API
Die External API ermöglicht es dir, Zenovay-Analysedaten auf deinen kundengerichteten Websites einzubetten. Verwende deinen API-Schlüssel, um Live-Besucherzahlen, Analysezusammenfassungen, Seitenstatistiken und vieles mehr abzurufen.
Basis-URL
Alle External API-Anfragen sollten an folgende Adresse gesendet werden:
https://api.zenovay.com/api/external/v1
Authentifizierung
External API-Endpunkte erfordern einen API-Schlüssel, der im Request-Header übergeben wird:
curl -X GET 'https://api.zenovay.com/api/external/v1/websites' \
-H 'X-API-Key: YOUR_API_KEY' \
-H 'Content-Type: application/json'Generiere deinen API-Schlüssel unter Settings → Security → API keys. Jeder Schlüssel kann spezifische Berechtigungen haben (lesen, schreiben, Admin).
Die External API erfordert einen bezahlten Plan. Konten im kostenlosen Tier erhalten eine 403 API_PAID_PLAN_REQUIRED-Antwort bei jedem Endpunkt. Upgrade auf Pro, Scale oder Enterprise, um API-Schlüssel programmgesteuert zu nutzen.
Konto-Endpunkte
Kontonutzung abrufen
Rufe deine Kontoverbrauchsstatistiken und Limits ab:
/api/external/v1/usageGet account usage and limits
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"
}
}Website-Endpunkte
Websites auflisten
Rufe alle Websites ab, die mit deinem Konto verknüpft sind:
/api/external/v1/websitesList all tracked websites
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
}Website-Details abrufen
Rufe Details für eine bestimmte Website ab:
/api/external/v1/websites/:websiteIdGet website details
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
}
}Analyse-Endpunkte
Analyse-Zusammenfassung abrufen
Rufe umfassende Analysedaten für eine Website ab:
/api/external/v1/analytics/:websiteIdGet analytics overview
Query Parameters:
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
timeRange | string | No | Zeitraum: today, 7d, 30d, 90d (Standard: 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
}Besucherdaten abrufen
Rufe Besucherinformationen mit optionalem Filtering ab:
/api/external/v1/analytics/:websiteId/visitorsGet visitor data
Query Parameters:
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
timeRange | string | No | Zeitraum: today, 7d, 30d, 90d |
limit | integer | No | Max. Ergebnisse (Standard: 50, Maximum: 100) |
offset | integer | No | Paginierungs-Offset |
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
}Seitenanalysen abrufen
Rufe Statistiken auf Seitenebene ab:
/api/external/v1/analytics/:websiteId/pagesGet top pages
Query Parameters:
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
timeRange | string | No | Zeitraum: today, 7d, 30d, 90d |
limit | integer | No | Max. Ergebnisse (Standard: 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
}
]
}Geografische Daten abrufen
Rufe Besucherdaten nach Land ab:
/api/external/v1/analytics/:websiteId/countriesGet geographic breakdown
Query Parameters:
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
timeRange | string | No | Zeitraum: 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
}
]
}Technologie-Aufschlüsselung abrufen
Rufe Geräte-, Browser- und OS-Statistiken ab:
/api/external/v1/analytics/:websiteId/technologyGet technology breakdown
Query Parameters:
| Parameter | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
timeRange | string | No | Zeitraum: 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 }
]
}Erweiterte Endpunkte
Heatmap-Seiten abrufen
Führe Seiten mit Heatmap-Daten auf:
/api/external/v1/heatmaps/:websiteId/pagesList heatmap pages
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"
}
]
}Session-Replays abrufen
Führe aufgezeichnete Sitzungen auf:
/api/external/v1/replays/:websiteId/sessionsList session replays
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
}Fehlergruppen abrufen
Führe JavaScript-Fehlergruppen auf:
/api/external/v1/errors/:websiteId/groupsList error groups
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
}Stats API (Plausible-Parität, Pro+)
Die Stats API stellt drei Plausible-kompatible Endpunkte für programmgesteuerte Abfragen von Analysen bereit. Verwende sie, um benutzerdefinierte Dashboards zu erstellen, Live-Metriken in BI-Tools einzubetten oder mit minimalem Code-Aufwand von Plausible zu migrieren.
Erforderlicher Plan: Pro, Scale oder Enterprise. Wie bei der übrigen External API erhalten Konten im kostenlosen Tier eine 403 API_PAID_PLAN_REQUIRED-Antwort bei jedem Endpunkt.
Endpunkte
| Endpunkt | Zweck |
|---|---|
GET /stats/aggregate | Einnummerige Metriken über einen Zeitraum (Summen, Raten, Dauern). |
GET /stats/timeseries | Zeitgebundene Serien (eine Zeile pro Tag, Stunde oder Monat). |
GET /stats/breakdown | Gruppierte Metriken (Top-Seiten, Top-Länder, Top-Browser, ...). |
OpenAPI spec: /api/external/v1/openapi.json (live, öffentlich, keine Authentifizierung für die Spezifikation erforderlich).
Gemeinsame Parameter
| Parameter | Erforderlich | Beschreibung |
|---|---|---|
site_id | yes | Website UUID. Finde sie in deiner Dashboard-URL oder über GET /websites. |
period | yes | day, 7d, 30d, month, 6mo, 12mo oder custom:YYYY-MM-DD,YYYY-MM-DD (max 366 Tage). |
date | no | ISO 8601 Anker für den Zeitraum (Standard = heute). |
metrics | yes | Kommagetrennt. Erlaubt: visitors, pageviews, visit_duration, bounce_rate, events. |
filters | no | Plausible-Stil: country==US;browser==Chrome;page!=/admin. Siehe Filter unten. |
GET /stats/aggregate
Gibt einnummerige Werte für jede angeforderte Metrik über einen Zeitraum zurück.
/api/external/v1/stats/aggregateAggregate metrics over a period
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
Gibt eine Zeile pro Bucket über den Zeitraum zurück. Standard interval=day; interval=hour erfordert period=day; interval=month erfordert period von 6mo, 12mo, month oder custom.
/api/external/v1/stats/timeseriesTime-bucketed metric series
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"
}Die Antwort ist dicht — Tage mit null Traffic erscheinen immer noch mit visitors: 0. Dies hält Chart-Bibliotheken glücklich ohne Client-seitige Lückenfüllung.
GET /stats/breakdown
Gibt Metriken gruppiert nach einer Dimension zurück, sortiert nach Besuchern absteigend.
/api/external/v1/stats/breakdownGroup-by metrics (top pages, top countries, …)
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"
}Erlaubte property Werte: event:page, visit:country, visit:browser, visit:device, visit:os, visit:source.
Paginierung: limit ist 1–1000 (Standard 100); page ist 1-indiziert (Standard 1).
Filter
Plausible-Stil-Filter-Klauseln, verbunden mit ;:
country==US— gleichcountry==US,CA,GB— gleich eins vonbrowser!=Safari— nicht gleich
Erlaubte Schlüssel: country, browser, device, os, source, utm_source, utm_medium, utm_campaign, page.
V1 Einschränkung: Wenn filters bereitgestellt wird, wird nur die visitors-Metrik berechnet; andere Metriken geben null mit einem meta.note-Flag zurück. Vollständige Filter-Unterstützung über alle Metriken kommt in V2.
JavaScript-Beispiel
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}`);Fehlercodes
Die Stats API gibt Codes zurück, auf die du reagieren kannst für eine gefällige UX:
| Code | HTTP | Wann |
|---|---|---|
MISSING_SITE_ID | 400 | site_id Query-Parameter erforderlich. |
MISSING_METRICS | 400 | metrics Query-Parameter erforderlich. |
MISSING_PERIOD | 400 | period Query-Parameter erforderlich. |
MISSING_PROPERTY | 400 | /stats/breakdown erfordert property. |
INVALID_METRIC | 400 | Eine der kommagetrennten Metriken ist nicht in der Allowlist. |
INVALID_PROPERTY | 400 | Die Breakdown-Eigenschaft ist nicht erlaubt. |
INVALID_PERIOD | 400 | Der Zeitraum ist nicht day/7d/30d/month/6mo/12mo/custom:.... |
INVALID_CUSTOM_PERIOD | 400 | Fehlerhaft formatierte custom:-Syntax oder ungültige Datum(e). |
PERIOD_TOO_LONG | 400 | Benutzerdefinierter Zeitraum > 366 Tage. |
INTERVAL_PERIOD_MISMATCH | 400 | z.B. interval=hour mit period=7d. |
UNKNOWN_FILTER_KEY | 400 | Filter-Schlüssel ist nicht in der Allowlist. |
EMPTY_FILTER_VALUE | 400 | Filter-Klausel hat keinen Wert. |
FORBIDDEN | 403 | Konto im kostenlosen Tier (External API erfordert einen bezahlten Plan), oder site_id außerhalb des API-Schlüssel-Bereichs. |
NOT_FOUND | 404 | Website existiert nicht oder ist für diesen Schlüssel verborgen. |
| (rate limit) | 429 | Ratelimit pro Tier überschritten. Retry-After Header gibt Wartezeit an. |
Migration von Plausible
Die Parameterform ist bewusst Plausible-kompatibel:
| Plausible | Zenovay | Hinweise |
|---|---|---|
site_id | site_id | Plausible verwendet eine Domain-String; Zenovay verwendet eine UUID. Mappe domain → site_id einmalig über GET /websites. |
period, date | period, date | Gleiche Allowlist + custom:YYYY-MM-DD,YYYY-MM-DD. |
metrics | metrics | Plausibles visitors, pageviews, bounce_rate, visit_duration alle Karten 1:1. events ist V1-angenähert als pageviews. |
property | property | Gleiche Form: event:page, visit:country, etc. |
filters (v1 string) | filters | Gleiche key==value;key!=value Form. JSON v2 Array-Filter landen in Zenovay V2. |
JavaScript-Beispiel
Bette Analysedaten auf deiner Website mit JavaScript ein:
// Fetch analytics data from your backend
async function fetchAnalytics() {
const response = await fetch('/api/analytics', {
headers: {
'X-API-Key': 'YOUR_API_KEY' // Use server-side proxy to protect your key
}
});
const data = await response.json();
// Update your 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) + '%';
}
// Refresh every 30 seconds
fetchAnalytics();
setInterval(fetchAnalytics, 30000);Sicherheitshinweis: Geben niemals deine API Key in Client-seitigem Code preis. Erstelle einen Server-seitigen Proxy-Endpunkt, der die Zenovay API mit deinem Schlüssel aufruft, und lass dein Frontend deinen Proxy aufrufen.
Rate Limits
External API Rate Limits nach Plan:
| Plan | Anfragen/Minute (Ziel) | Monatliches Limit (Hard Cap) |
|---|---|---|
| Free | N/A (API nicht verfügbar) | N/A |
| Pro | 30 | 10.000 |
| Scale | 60 | 100.000 |
| Enterprise | 120 | 1.000.000 |
Wie Rate-Limiting durchgesetzt wird. Die Zahl pro Minute ist ein Ziel, keine harte Obergrenze. Wir verwenden Cloudflares Edge Rate-Limit, das pro Rechenzentrum mit einer kleinen Burst-Zulassung ist — ein beständiger Client kann vorübergehend das 1,5–3-fache der angegebenen Zahl sehen, bevor es gedrosselt wird, besonders wenn Anfragen über Regionen gesendet werden. Die harte Obergrenze ist das monatliche Kontingent, das atomar gegen dein Konto durchgesetzt wird, unabhängig davon, welcher Edge POP die Anfrage verarbeitet. Plane capacity-sensitive Workloads gegen das monatliche Kontingent; behandle das pro-Minute-Ziel als Glättungssignal.
Fehlerantworten
| Statuscode | Beschreibung |
|---|---|
| 200 | Erfolg |
| 400 | Ungültige Anfrage - Ungültige Parameter |
| 401 | Nicht autorisiert - Ungültiger oder fehlender API-Schlüssel |
| 403 | Verboten - Unzureichende Berechtigungen |
| 404 | Nicht gefunden - Website nicht gefunden |
| 429 | Zu viele Anfragen - Rate Limit überschritten |
| 500 | Interner Serverfehler |
{
"error": {
"code": "unauthorized",
"message": "Invalid API key provided"
}
}Nächste Schritte
- Widgets - Einbettbare Widgets auf deiner Website verwenden
- Echtzeit-Daten - Live-Besucherdaten ohne Authentifizierung abrufen
- Rate Limits - API-Rate-Limiting verstehen