Appearance
Stats and Realtime
Query aggregated analytics data, real-time visitor counts, and custom event statistics.
Base URL: https://app.krafter.dev/api/v1/analytics
Get Stats
Retrieve aggregated statistics for a site over a given period, with optional breakdowns by dimension.
GET /analytics/sites/:key/statsRequired scope: analytics:read
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
period | string | 7d | Time period. One of: today, 7d, 30d, 12mo, custom. Each named period is inclusive of today and spans exactly the days it names, so 7d is today and the six days before it. An unrecognised value falls back to 7d. |
from | string | -- | Start date (ISO 8601, e.g., 2025-01-01). Required when period=custom. |
to | string | -- | End date (ISO 8601, e.g., 2025-01-31). Required when period=custom. |
dimensions | string | -- | Comma-separated list of dimensions to break down by. |
Dimensions
| Dimension | Description |
|---|---|
path | Page URL path |
referrer | Traffic source / referring URL |
country | Visitor country (ISO 3166-1 alpha-2) |
device | Device type (Desktop, Mobile, Tablet) |
browser | Browser name (Chrome, Firefox, Safari, etc.) |
os | Operating system (Windows, macOS, Linux, iOS, Android) |
utm_source | UTM source parameter |
utm_medium | UTM medium parameter |
utm_campaign | UTM campaign parameter |
Example Request
bash
curl "https://app.krafter.dev/api/v1/analytics/sites/sk_abc123def456/stats?period=7d&dimensions=path,country" \
-H "Authorization: Bearer YOUR_API_TOKEN"Example Response
json
{
"data": {
"period": {
"from": "2025-02-11",
"to": "2025-02-18"
},
"totals": {
"pageviews": 1000,
"visitors": 500,
"visits": 600
},
"timeseries": [
{
"date": "2025-02-11",
"pageviews": 100,
"visitors": 50,
"visits": 60
},
{
"date": "2025-02-12",
"pageviews": 120,
"visitors": 65,
"visits": 72
},
{
"date": "2025-02-13",
"pageviews": 95,
"visitors": 48,
"visits": 55
},
{
"date": "2025-02-14",
"pageviews": 180,
"visitors": 90,
"visits": 105
},
{
"date": "2025-02-15",
"pageviews": 150,
"visitors": 75,
"visits": 88
},
{
"date": "2025-02-16",
"pageviews": 140,
"visitors": 72,
"visits": 85
},
{
"date": "2025-02-17",
"pageviews": 110,
"visitors": 55,
"visits": 68
},
{
"date": "2025-02-18",
"pageviews": 105,
"visitors": 45,
"visits": 67
}
],
"breakdown": {
"path": [
{ "value": "/", "count": 500, "visitors": 410, "percent": 50.0 },
{ "value": "/pricing", "count": 200, "visitors": 180, "percent": 20.0 },
{ "value": "/blog", "count": 150, "visitors": 130, "percent": 15.0 },
{ "value": "/docs", "count": 100, "visitors": 85, "percent": 10.0 },
{ "value": "/about", "count": 50, "visitors": 48, "percent": 5.0 }
],
"country": [
{ "value": "US", "count": 300, "visitors": 240, "percent": 30.0 },
{ "value": "DE", "count": 150, "visitors": 120, "percent": 15.0 },
{ "value": "GB", "count": 120, "visitors": 95, "percent": 12.0 },
{ "value": "FR", "count": 80, "visitors": 70, "percent": 8.0 },
{ "value": "RS", "count": 50, "visitors": 44, "percent": 5.0 }
]
}
}
}Custom Date Range
Use period=custom with from and to parameters:
bash
curl "https://app.krafter.dev/api/v1/analytics/sites/sk_abc123def456/stats?period=custom&from=2025-01-01&to=2025-01-31&dimensions=referrer" \
-H "Authorization: Bearer YOUR_API_TOKEN"Response Fields
| Field | Description |
|---|---|
period.from | Start date of the queried period. |
period.to | End date of the queried period. |
totals.pageviews | Total page views in the period. |
totals.visitors | Total unique visitors in the period. |
totals.visits | Total sessions/visits in the period. |
timeseries | Array of daily data points with date, pageviews, visitors, and visits. |
breakdown | Object with keys for each requested dimension. Each contains an array of {value, count, visitors, percent}, ordered by count descending and cut at 20 rows. count is page views, visitors unique visitors. |
breakdown.*.percent | The row's count as a share of totals.pageviews, with one decimal. It is null when the period total is unknown. |
TIP
If you do not pass any dimensions, the response will include totals and timeseries but no breakdown object.
INFO
percent is a share of the whole period, not of the rows returned. The rows of a dimension therefore add up to at most 100 and usually less: the list is cut at 20, and the utm_* dimensions leave out page views that carried no UTM parameter at all. The same share is what the dashboard and the MCP tools analytics_get_stats, analytics_top_pages and analytics_top_referrers report.
Get Realtime
Get the number of visitors currently on your site.
GET /analytics/sites/:key/realtimeRequired scope: analytics:read
Example Request
bash
curl https://app.krafter.dev/api/v1/analytics/sites/sk_abc123def456/realtime \
-H "Authorization: Bearer YOUR_API_TOKEN"Example Response
json
{
"data": {
"current_visitors": 5
}
}INFO
The realtime endpoint returns visitors active in the last 5 minutes. This is updated continuously and reflects live traffic to your site.
List Custom Events
Retrieve a list of custom events tracked for a site, with total and unique counts.
GET /analytics/sites/:key/eventsRequired scope: analytics:read
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
period | string | 7d | Time period. One of: today, 7d, 30d, 12mo, custom. Each named period is inclusive of today and spans exactly the days it names, so 7d is today and the six days before it. An unrecognised value falls back to 7d. |
from | string | -- | Start date. Required when period=custom. |
to | string | -- | End date. Required when period=custom. |
Example Request
bash
curl "https://app.krafter.dev/api/v1/analytics/sites/sk_abc123def456/events?period=30d" \
-H "Authorization: Bearer YOUR_API_TOKEN"Example Response
json
{
"data": [
{
"event_name": "signup",
"total": 245,
"unique_count": 230,
"revenue": null
},
{
"event_name": "purchase",
"total": 89,
"unique_count": 82,
"revenue": 4355.00
},
{
"event_name": "download",
"total": 156,
"unique_count": 140,
"revenue": null
}
]
}| Field | Description |
|---|---|
event_name | Name of the custom event. |
total | Total number of times the event was triggered. |
unique_count | Number of unique visitors who triggered the event. |
revenue | Total revenue associated with the event, or null if no revenue tracked. |
When the store cannot answer
Every endpoint on this page reads from ClickHouse. A query that did not run is reported, never smoothed into zeros: a site with traffic must not be described as a site without any.
| Status | Body | Meaning |
|---|---|---|
200 | {"data": {...}} with zeros and empty lists | The query ran and the period genuinely has nothing in it. |
503 | {"error": "Analytics storage temporarily unavailable"} | ClickHouse did not answer. Safe to retry after a brief backoff. Nothing partial is returned — if one requested dimensions breakdown fails, the whole response is a 503 rather than an empty list beside the ones that did read. |
Scopes
| Scope | Endpoints |
|---|---|
analytics:read | All endpoints on this page |