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

text
https://api.statscontext.com

Authentication

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 Header
Authorization: Bearer aa_live_xxxxxxxxxxxxxxxx

Error 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 Response Format
{
  "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

FieldTypeRequiredDescription
emailstringYesValid email address
namestringNoAccount name (1-255 characters)
Example Request
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)

json
{
  "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)

json
{
  "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

FieldTypeRequiredDescription
domainstringYesDomain name (e.g., "example.com")
namestringYesDisplay name for the site
Example Request
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)

json
{
  "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)

json
{
  "error": "A site with this domain already exists in your account"
}

GET /api/sites

List all sites for your account.

Authentication: Required

Example Request
curl https://api.statscontext.com/api/sites \  -H "Authorization: Bearer aa_live_xxxxxxxxxxxxxxxx"

Success Response (200)

json
{
  "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

Example Request
curl https://api.statscontext.com/api/sites/site_1234567890abcdef \  -H "Authorization: Bearer aa_live_xxxxxxxxxxxxxxxx"

Success Response (200)

json
{
  "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)

json
{
  "error": "Site not found"
}

DELETE /api/sites/:id

Delete a site and all associated analytics data.

Authentication: Required

Example Request
curl -X DELETE https://api.statscontext.com/api/sites/site_1234567890abcdef \  -H "Authorization: Bearer aa_live_xxxxxxxxxxxxxxxx"

Success Response (200)

json
{
  "success": true
}

Error Response (404)

json
{
  "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.

FieldTypeRequiredDescription
typestringYesMust be "pageview"
site_idstringYesSite identifier
urlstringYesFull URL of the page
referrerstringNoReferring URL
titlestringNoPage title
utm_sourcestringNoUTM source parameter
utm_mediumstringNoUTM medium parameter
utm_campaignstringNoUTM campaign parameter
utm_termstringNoUTM term parameter
utm_contentstringNoUTM content parameter
Pageview Event Example
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)

json
{
  "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.

FieldTypeRequiredDescription
typestringYesMust be "heartbeat"
site_idstringYesSite identifier
page_view_idstringYesID from pageview response
duration_msnumberYesTime spent on page in milliseconds
Heartbeat Event Example
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)

json
{
  "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.

FieldTypeRequiredDescription
typestringYesMust be "navigation"
site_idstringYesSite identifier
prev_page_view_idstringYesID of the previous page view
urlstringYesFull URL of the new page
referrerstringNoPrevious page URL
titlestringNoNew page title
Navigation Event Example
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)

json
{
  "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.

FieldTypeRequiredDescription
typestringYesMust be "custom"
site_idstringYesSite identifier
namestringYesEvent name (1-255 characters)
propertiesobjectNoCustom event properties (key-value pairs)
Custom Event Example
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)

json
{
  "event_id": "evt_1234567890abcdef"
}

Error Responses

json
// 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

ParameterTypeDefaultDescription
periodenum"7d"Time period: "today", "7d", "30d", "90d", or "custom"
metricenum"all"Metric to query (see Metrics table below)
fromstring-Start date (ISO 8601) for custom period
tostring-End date (ISO 8601) for custom period
pagestring-Filter by page path
referrerstring-Filter by referrer domain
countrystring-Filter by country code (ISO 3166-1 alpha-2)
devicestring-Filter by device type
browserstring-Filter by browser name
limitnumber10Number of results (1-100)

Available Metrics

MetricDescription
allReturns all metrics in a single response
pageviewsTotal number of page views
visitorsUnique visitor count
sessionsTotal number of sessions
bounce_ratePercentage of single-page sessions
avg_durationAverage session duration in seconds
top_pagesMost visited pages with view counts
referrersTraffic sources with visitor counts
countriesVisitor breakdown by country
devicesVisitor breakdown by device type
browsersVisitor breakdown by browser
custom_eventsCustom event counts by event name
timeseriesDaily time series data for the period
Example Request - All Metrics
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)

json
{
  "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 }
  ]
}
Example Request - Top Pages
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)

json
{
  "top_pages": [
    { "page": "/", "pageviews": 12543 },
    { "page": "/blog", "pageviews": 8765 },
    { "page": "/about", "pageviews": 4321 },
    { "page": "/pricing", "pageviews": 3210 },
    { "page": "/contact", "pageviews": 2109 }
  ]
}
Example Request - Custom Date Range
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)

json
{
  "pageviews": 45678
}

Error Response (404)

json
{
  "error": "Site not found"
}

Error Handling

The API uses standard HTTP status codes to indicate success or failure of requests.

HTTP Status Codes

StatusDescription
200Success - Request completed successfully
201Created - Resource created successfully
400Bad Request - Invalid request parameters or body
401Unauthorized - Missing or invalid API key
403Forbidden - Valid authentication but insufficient permissions
404Not Found - Resource does not exist
409Conflict - Resource already exists
429Too Many Requests - Rate limit exceeded
500Internal Server Error - Something went wrong on our end

Authentication Errors

json
// 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

HeaderDescription
X-RateLimit-LimitMaximum requests per window (60)
X-RateLimit-RemainingRemaining requests in current window
X-RateLimit-ResetSeconds until the rate limit window resets
Retry-AfterSeconds to wait before retrying (only on 429 responses)
Example Rate Limit Headers
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 23

Rate Limit Exceeded Response (429)

json
{
  "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.