REST API Reference
Complete reference for the Agent Analytics REST API. Learn how to authenticate, manage sites, track events, and query analytics data programmatically.
Overview
The Agent Analytics API is organized around REST. All requests should be made to the base URL, and all responses are returned in JSON format.
Base URL
https://api.statscontext.comAuthentication
Authenticate API requests by including your API key in the Authorization header as a Bearer token. API keys always start with the prefix aa_live_.
Authorization: Bearer aa_live_xxxxxxxxxxxxxxxxError Format
All API errors return a JSON object with an error field containing a human-readable message. Some errors also include a details field with additional validation information.
{
"error": "Invalid input",
"details": {
"fieldErrors": {
"email": ["Invalid email"]
}
}
}Rate Limiting
The API enforces rate limits of 60 requests per minute per IP address. Rate limit information is included in response headers.
Authentication
POST /api/auth/signup
Create a new account and generate an API key. This endpoint is used for programmatic account creation (e.g., by AI agents or MCP clients).
Authentication: None required
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
email | string | Yes | Valid email address |
name | string | No | Account name (1-255 characters) |
curl -X POST https://api.statscontext.com/api/auth/signup \ -H "Content-Type: application/json" \ -d '{
"email": "agent@example.com",
"name": "My Agent Account"
}'Success Response (201)
{
"account": {
"id": "acc_1234567890abcdef",
"email": "agent@example.com",
"name": "My Agent Account"
},
"api_key": "aa_live_xxxxxxxxxxxxxxxx",
"message": "Store this API key securely. It will not be shown again."
}Error Response (409)
{
"error": "Account with this email already exists"
}Sites
Sites represent the web properties you want to track. Each site has a unique ID and tracking snippet.
POST /api/sites
Create a new site.
Authentication: Required
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
domain | string | Yes | Domain name (e.g., "example.com") |
name | string | Yes | Display name for the site |
curl -X POST https://api.statscontext.com/api/sites \ -H "Authorization: Bearer aa_live_xxxxxxxxxxxxxxxx" \ -H "Content-Type: application/json" \ -d '{
"domain": "example.com",
"name": "My Website"
}'Success Response (201)
{
"site": {
"id": "site_1234567890abcdef",
"account_id": "acc_1234567890abcdef",
"domain": "example.com",
"name": "My Website",
"created_at": "2025-01-15T10:30:00.000Z"
},
"snippet": "<script defer data-site-id=\"site_1234567890abcdef\" src=\"https://example.com/tracker.js\"></script>"
}Error Response (409)
{
"error": "A site with this domain already exists in your account"
}GET /api/sites
List all sites for your account.
Authentication: Required
curl https://api.statscontext.com/api/sites \ -H "Authorization: Bearer aa_live_xxxxxxxxxxxxxxxx"Success Response (200)
{
"sites": [
{
"id": "site_1234567890abcdef",
"account_id": "acc_1234567890abcdef",
"domain": "example.com",
"name": "My Website",
"created_at": "2025-01-15T10:30:00.000Z"
},
{
"id": "site_abcdef1234567890",
"account_id": "acc_1234567890abcdef",
"domain": "blog.example.com",
"name": "My Blog",
"created_at": "2025-01-14T08:15:00.000Z"
}
]
}GET /api/sites/:id
Get a single site by ID.
Authentication: Required
curl https://api.statscontext.com/api/sites/site_1234567890abcdef \ -H "Authorization: Bearer aa_live_xxxxxxxxxxxxxxxx"Success Response (200)
{
"site": {
"id": "site_1234567890abcdef",
"account_id": "acc_1234567890abcdef",
"domain": "example.com",
"name": "My Website",
"created_at": "2025-01-15T10:30:00.000Z"
}
}Error Response (404)
{
"error": "Site not found"
}DELETE /api/sites/:id
Delete a site and all associated analytics data.
Authentication: Required
curl -X DELETE https://api.statscontext.com/api/sites/site_1234567890abcdef \ -H "Authorization: Bearer aa_live_xxxxxxxxxxxxxxxx"Success Response (200)
{
"success": true
}Error Response (404)
{
"error": "Site not found"
}Events
Events are tracked interactions on your site. The tracker.js script automatically sends events, but you can also send them programmatically via the API.
POST /api/event
Track a new event. Supports four event types: pageview, heartbeat, navigation, and custom.
Authentication: None required (validated by site_id and origin)
Event Types
Pageview Event
Tracks a page view with optional UTM parameters for campaign tracking.
| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | Must be "pageview" |
site_id | string | Yes | Site identifier |
url | string | Yes | Full URL of the page |
referrer | string | No | Referring URL |
title | string | No | Page title |
utm_source | string | No | UTM source parameter |
utm_medium | string | No | UTM medium parameter |
utm_campaign | string | No | UTM campaign parameter |
utm_term | string | No | UTM term parameter |
utm_content | string | No | UTM content parameter |
curl -X POST https://api.statscontext.com/api/event \ -H "Content-Type: application/json" \ -H "Origin: https://example.com" \ -d '{
"type": "pageview",
"site_id": "site_1234567890abcdef",
"url": "https://example.com/blog/hello-world",
"referrer": "https://google.com/",
"title": "Hello World - My Blog",
"utm_source": "twitter",
"utm_medium": "social",
"utm_campaign": "launch"
}'Success Response (201)
{
"page_view_id": "pv_1234567890abcdef",
"session_id": "sess_1234567890abcdef"
}Heartbeat Event
Updates the duration of an active page view. Automatically sent by the tracker every 15 seconds.
| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | Must be "heartbeat" |
site_id | string | Yes | Site identifier |
page_view_id | string | Yes | ID from pageview response |
duration_ms | number | Yes | Time spent on page in milliseconds |
curl -X POST https://api.statscontext.com/api/event \ -H "Content-Type: application/json" \ -d '{
"type": "heartbeat",
"site_id": "site_1234567890abcdef",
"page_view_id": "pv_1234567890abcdef",
"duration_ms": 15000
}'Success Response (200)
{
"success": true
}Navigation Event
Tracks navigation between pages in a single-page application (SPA). Links the new page view to the previous one in the same session.
| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | Must be "navigation" |
site_id | string | Yes | Site identifier |
prev_page_view_id | string | Yes | ID of the previous page view |
url | string | Yes | Full URL of the new page |
referrer | string | No | Previous page URL |
title | string | No | New page title |
curl -X POST https://api.statscontext.com/api/event \ -H "Content-Type: application/json" \ -H "Origin: https://example.com" \ -d '{
"type": "navigation",
"site_id": "site_1234567890abcdef",
"prev_page_view_id": "pv_1234567890abcdef",
"url": "https://example.com/about",
"referrer": "https://example.com/",
"title": "About Us"
}'Success Response (201)
{
"page_view_id": "pv_abcdef1234567890",
"session_id": "sess_1234567890abcdef"
}Custom Event
Track custom user interactions with optional properties. Use this for button clicks, form submissions, video plays, etc.
| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | Must be "custom" |
site_id | string | Yes | Site identifier |
name | string | Yes | Event name (1-255 characters) |
properties | object | No | Custom event properties (key-value pairs) |
curl -X POST https://api.statscontext.com/api/event \ -H "Content-Type: application/json" \ -H "Origin: https://example.com" \ -d '{
"type": "custom",
"site_id": "site_1234567890abcdef",
"name": "signup_completed",
"properties": {
"plan": "pro",
"trial": false,
"source": "landing_page"
}
}'Success Response (201)
{
"event_id": "evt_1234567890abcdef"
}Error Responses
// Invalid site_id (404)
{
"error": "Invalid site_id"
}
// Origin mismatch (403)
{
"error": "Origin mismatch"
}
// Invalid payload (400)
{
"error": "Invalid event payload",
"details": { ... }
}Stats
Query analytics data for your sites. The stats endpoint supports time-based filtering, metric selection, and breakdowns by various dimensions.
GET /api/sites/:id/stats
Query analytics data for a specific site.
Authentication: Required
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
period | enum | "7d" | Time period: "today", "7d", "30d", "90d", or "custom" |
metric | enum | "all" | Metric to query (see Metrics table below) |
from | string | - | Start date (ISO 8601) for custom period |
to | string | - | End date (ISO 8601) for custom period |
page | string | - | Filter by page path |
referrer | string | - | Filter by referrer domain |
country | string | - | Filter by country code (ISO 3166-1 alpha-2) |
device | string | - | Filter by device type |
browser | string | - | Filter by browser name |
limit | number | 10 | Number of results (1-100) |
Available Metrics
| Metric | Description |
|---|---|
all | Returns all metrics in a single response |
pageviews | Total number of page views |
visitors | Unique visitor count |
sessions | Total number of sessions |
bounce_rate | Percentage of single-page sessions |
avg_duration | Average session duration in seconds |
top_pages | Most visited pages with view counts |
referrers | Traffic sources with visitor counts |
countries | Visitor breakdown by country |
devices | Visitor breakdown by device type |
browsers | Visitor breakdown by browser |
custom_events | Custom event counts by event name |
timeseries | Daily time series data for the period |
curl "https://api.statscontext.com/api/sites/site_1234567890abcdef/stats?period=7d&metric=all" \ -H "Authorization: Bearer aa_live_xxxxxxxxxxxxxxxx"Success Response - metric=all (200)
{
"pageviews": 15234,
"visitors": 3421,
"sessions": 4892,
"bounce_rate": 42.3,
"avg_duration": 187,
"top_pages": [
{ "page": "/", "pageviews": 5432 },
{ "page": "/blog", "pageviews": 3210 },
{ "page": "/about", "pageviews": 1543 }
],
"referrers": [
{ "referrer": "google.com", "visitors": 1234 },
{ "referrer": "twitter.com", "visitors": 567 },
{ "referrer": "(direct)", "visitors": 890 }
],
"countries": [
{ "country": "US", "visitors": 1543 },
{ "country": "GB", "visitors": 432 },
{ "country": "CA", "visitors": 321 }
],
"devices": [
{ "device": "desktop", "visitors": 2103 },
{ "device": "mobile", "visitors": 1234 },
{ "device": "tablet", "visitors": 84 }
],
"browsers": [
{ "browser": "Chrome", "visitors": 2543 },
{ "browser": "Safari", "visitors": 654 },
{ "browser": "Firefox", "visitors": 224 }
],
"custom_events": [
{ "name": "signup_completed", "count": 45 },
{ "name": "button_clicked", "count": 892 }
],
"timeseries": [
{ "date": "2025-01-08", "pageviews": 2134, "visitors": 543 },
{ "date": "2025-01-09", "pageviews": 2234, "visitors": 587 },
{ "date": "2025-01-10", "pageviews": 2056, "visitors": 521 }
]
}curl "https://api.statscontext.com/api/sites/site_1234567890abcdef/stats?period=30d&metric=top_pages&limit=5" \ -H "Authorization: Bearer aa_live_xxxxxxxxxxxxxxxx"Success Response - metric=top_pages (200)
{
"top_pages": [
{ "page": "/", "pageviews": 12543 },
{ "page": "/blog", "pageviews": 8765 },
{ "page": "/about", "pageviews": 4321 },
{ "page": "/pricing", "pageviews": 3210 },
{ "page": "/contact", "pageviews": 2109 }
]
}curl "https://api.statscontext.com/api/sites/site_1234567890abcdef/stats?period=custom&from=2025-01-01T00:00:00Z&to=2025-01-31T23:59:59Z&metric=pageviews" \ -H "Authorization: Bearer aa_live_xxxxxxxxxxxxxxxx"Success Response - metric=pageviews (200)
{
"pageviews": 45678
}Error Response (404)
{
"error": "Site not found"
}Error Handling
The API uses standard HTTP status codes to indicate success or failure of requests.
HTTP Status Codes
| Status | Description |
|---|---|
200 | Success - Request completed successfully |
201 | Created - Resource created successfully |
400 | Bad Request - Invalid request parameters or body |
401 | Unauthorized - Missing or invalid API key |
403 | Forbidden - Valid authentication but insufficient permissions |
404 | Not Found - Resource does not exist |
409 | Conflict - Resource already exists |
429 | Too Many Requests - Rate limit exceeded |
500 | Internal Server Error - Something went wrong on our end |
Authentication Errors
// Missing Authorization header
{
"error": "Missing or invalid Authorization header"
}
// Invalid API key format
{
"error": "Invalid API key format. Must start with 'aa_live_'"
}
// API key not found
{
"error": "Invalid API key"
}Rate Limiting
API requests are rate-limited to 60 requests per minute per IP address. Rate limit information is included in the response headers of every request.
Rate Limit Headers
| Header | Description |
|---|---|
X-RateLimit-Limit | Maximum requests per window (60) |
X-RateLimit-Remaining | Remaining requests in current window |
X-RateLimit-Reset | Seconds until the rate limit window resets |
Retry-After | Seconds to wait before retrying (only on 429 responses) |
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 23Rate Limit Exceeded Response (429)
{
"error": "Rate limit exceeded. Try again later."
}Note: The event tracking endpoint (
/api/event) does not require authentication, but it is still subject to rate limiting by IP address to prevent abuse.