Skip to main content
The DATALYR Public API provides read-only access to your analytics data. Use it to build custom dashboards, export data, or integrate with other tools.

Authentication

All requests require an API key in the Authorization header:
Authorization: Bearer dk_your_api_key
Both SDK keys (dk_) and Agent keys (dk_agent_) work on all API routes.

Key Types

Key TypePrefixPurpose
SDK Keydk_Event ingestion, SDK setup, API access
Agent Keydk_agent_AI Chat, API access, MCP integrations
Generate keys in Settings -> API Keys in the DATALYR dashboard.

Error Responses

Status CodeDescription
401Missing or invalid API key
403API key valid but feature not available on your plan
429Rate limit exceeded

Rate Limiting

All API keys are limited to 100 requests per minute. Every response includes rate limit headers:
HeaderDescription
X-RateLimit-LimitMaximum requests per window (100)
X-RateLimit-RemainingRequests remaining in current window
X-RateLimit-ResetUnix timestamp when the window resets
When you exceed the limit, the API returns a 429 status code. Wait until the X-RateLimit-Reset timestamp before retrying.

Base URL

https://app.datalyr.com/api/v1

Date/Time Parameters

All datetime parameters use ISO 8601 format:
2026-03-16T14:30:00Z              (UTC)
2026-03-16T08:30:00-06:00         (with timezone offset)
2026-03-16T14:30:45.123Z          (with seconds and milliseconds)
The API normalizes all datetimes to UTC internally using your workspace timezone. Most endpoints require start_date and end_date parameters. Both are inclusive.

Endpoints

GET /api/v1/overview

Returns core dashboard stats: visitors, pageviews, sessions, and custom events over time. Parameters:
ParameterTypeRequiredDefaultDescription
start_dateISO 8601YesStart of date range
end_dateISO 8601YesEnd of date range
aggregationstringNoautohour, day, week, or month
Auto-aggregation logic:
  • Same day: hour
  • 1-60 days: day
  • 61-180 days: week
  • 180+ days: month
Response:
{
  "visitors_total": 12450,
  "pageviews_total": 34200,
  "sessions_total": 18300,
  "custom_events_total": 890,
  "custom_event_counts": {
    "signup": 120,
    "purchase": 45,
    "add_to_cart": 310
  },
  "time_series": [
    {
      "timestamp": "2026-03-16T00:00:00Z",
      "visitors": 450,
      "pageviews": 1200,
      "sessions": 680,
      "custom_events": 35,
      "signup": 5,
      "purchase": 2
    }
  ],
  "aggregation_level": "hour",
  "timezone": "America/Chicago"
}

GET /api/v1/traffic

Returns traffic sources, campaigns, or top pages. Parameters:
ParameterTypeRequiredDefaultDescription
start_dateISO 8601YesStart of date range
end_dateISO 8601YesEnd of date range
typestringNoreferrerreferrer, campaign, or page
limitnumberNo20Maximum results (1-100)
Response:
{
  "data": [
    { "name": "google.com", "count": 4500, "percentage": 36.1 },
    { "name": "twitter.com", "count": 2100, "percentage": 16.8 },
    { "name": "(direct)", "count": 1800, "percentage": 14.4 }
  ],
  "total": 12450,
  "type": "referrer"
}

GET /api/v1/devices

Returns browser, OS, or device type breakdown. Parameters:
ParameterTypeRequiredDefaultDescription
start_dateISO 8601YesStart of date range
end_dateISO 8601YesEnd of date range
typestringNobrowserbrowser, os, or deviceType
limitnumberNo15Maximum results (1-100)
Response:
{
  "data": [
    { "name": "Chrome", "count": 7800, "percentage": 62.6 },
    { "name": "Safari", "count": 2800, "percentage": 22.5 },
    { "name": "Firefox", "count": 1200, "percentage": 9.6 }
  ],
  "total": 12450,
  "type": "browser"
}

GET /api/v1/locations

Returns geographic breakdown by country, region, or city. Parameters:
ParameterTypeRequiredDefaultDescription
start_dateISO 8601YesStart of date range
end_dateISO 8601YesEnd of date range
typestringNocountrycountry, region, or city
limitnumberNo15Maximum results (1-100)
Response:
{
  "data": [
    { "name": "United States", "count": 8200, "percentage": 65.8, "code": "US" },
    { "name": "United Kingdom", "count": 1500, "percentage": 12.0, "code": "GB" },
    { "name": "Germany", "count": 800, "percentage": 6.4, "code": "DE" }
  ],
  "total": 12450,
  "type": "country"
}

GET /api/v1/events

Returns a paginated list of raw events with filtering. Parameters:
ParameterTypeRequiredDefaultDescription
start_dateISO 8601YesStart of date range
end_dateISO 8601YesEnd of date range
event_namestringNoallComma-separated event names
utm_sourcestringNoFilter by UTM source
utm_mediumstringNoFilter by UTM medium
utm_campaignstringNoFilter by UTM campaign
countrystringNoFilter by country code
regionstringNoFilter by region
citystringNoFilter by city
page_pathstringNoFilter by page path
limitnumberNo100Maximum results (1-1000)
offsetnumberNo0Pagination offset
Response:
{
  "events": [
    {
      "id": "evt_abc123",
      "event_name": "pageview",
      "visitor_id": "v_xxx",
      "session_id": "s_xxx",
      "user_id": "u_xxx",
      "received_at": "2026-03-16T14:32:45.123Z",
      "page_path": "/pricing",
      "page_title": "Pricing - Acme",
      "page_url": "https://acme.com/pricing",
      "referrer": "https://google.com",
      "geo_country": "US",
      "geo_country_code": "US",
      "geo_region": "Texas",
      "geo_city": "Austin",
      "utm_source": "google",
      "utm_medium": "cpc",
      "utm_campaign": "spring_sale",
      "browser": "Chrome",
      "os": "macOS",
      "device_type": "desktop",
      "screen_width": "1920",
      "screen_height": "1080",
      "source": "web",
      "event_data": {}
    }
  ],
  "total_count": 34200,
  "has_more": true,
  "limit": 100,
  "offset": 0
}
Use offset and limit to paginate through results. The has_more field indicates whether additional results exist beyond the current page.

GET /api/v1/event-names

Returns all distinct event names tracked in your workspace over the last 30 days. Parameters: None required. Response:
{
  "events": [
    { "name": "pageview", "category": "web", "source": "web" },
    { "name": "purchase", "category": "conversion", "source": "shopify" },
    { "name": "signup", "category": "conversion", "source": "web" },
    { "name": "add_to_cart", "category": "ecommerce", "source": "web" },
    { "name": "payment_intent.succeeded", "category": "payment", "source": "stripe-webhooks" }
  ],
  "integrations": ["shopify", "stripe", "meta"]
}
The integrations array lists all connected data sources that have sent events.

GET /api/v1/realtime

Returns live visitor data and real-time metrics. Parameters:
ParameterTypeRequiredDefaultDescription
time_windownumberNo30Minutes of data to include (1-60)
Response:
{
  "active_visitors": 23,
  "pageviews": 156,
  "events": 42,
  "revenue": 450.00,
  "top_pages": [
    { "path": "/pricing", "count": 12 },
    { "path": "/", "count": 8 },
    { "path": "/features", "count": 6 }
  ],
  "top_referrers": [
    { "name": "google.com", "count": 15 },
    { "name": "(direct)", "count": 8 }
  ],
  "top_locations": [
    { "name": "United States", "count": 14 },
    { "name": "United Kingdom", "count": 4 }
  ],
  "visitors": [
    {
      "visitor_id": "v_xxx",
      "country": "US",
      "city": "Austin",
      "current_page": "/pricing",
      "device": "desktop",
      "browser": "Chrome",
      "referrer": "google.com",
      "first_seen": "2026-03-16T14:20:00Z",
      "last_seen": "2026-03-16T14:32:45Z",
      "total_events": 8,
      "session_duration_seconds": 765
    }
  ],
  "timeline": [
    { "minute": "2026-03-16T14:00:00Z", "visitors": 18 },
    { "minute": "2026-03-16T14:01:00Z", "visitors": 20 }
  ],
  "time_window": 30,
  "timestamp": "2026-03-16T14:32:45Z"
}
The visitors array contains individual active visitors with their current session data. The timeline array contains per-minute visitor counts for the specified time window.

GET /api/v1/attribution

Returns campaign attribution and conversion data. Parameters:
ParameterTypeRequiredDefaultDescription
start_dateISO 8601YesStart of date range
end_dateISO 8601YesEnd of date range
window_daysnumberNo30Attribution window in days (7, 30, or 90)
Response:
{
  "campaigns": [
    {
      "utm_source": "google",
      "utm_medium": "cpc",
      "utm_campaign": "spring_sale",
      "visitors": 1200,
      "conversions": 45,
      "revenue": 8900.00,
      "conversion_rate": 3.75,
      "avg_order_value": 197.78
    },
    {
      "utm_source": "facebook",
      "utm_medium": "paid",
      "utm_campaign": "retargeting_q1",
      "visitors": 800,
      "conversions": 32,
      "revenue": 5600.00,
      "conversion_rate": 4.0,
      "avg_order_value": 175.00
    }
  ],
  "attribution_window_days": 30,
  "total_campaigns": 12,
  "date_range": {
    "start": "2026-03-01T00:00:00Z",
    "end": "2026-03-16T23:59:59Z"
  }
}
The window_days parameter controls how far back DATALYR looks for the original attribution touchpoint when linking a conversion to a campaign.

GET /api/v1/users

Returns a paginated list of tracked users and visitors. Parameters:
ParameterTypeRequiredDefaultDescription
start_dateISO 8601YesStart of date range
end_dateISO 8601YesEnd of date range
searchstringNoSearch by visitor ID, user ID, or email
limitnumberNo100Maximum results (1-1000)
Response:
{
  "users": [
    {
      "visitor_id": "v_abc123",
      "user_id": "u_def456",
      "email": "[email protected]",
      "first_seen": "2026-03-10T08:15:30Z",
      "last_seen": "2026-03-16T14:30:00Z",
      "total_events": 45,
      "total_sessions": 8,
      "country": "US",
      "city": "Austin",
      "device": "desktop",
      "browser": "Chrome"
    }
  ],
  "total_count": 1250,
  "has_more": true
}

GET /api/v1/users/:userId

Returns a single user profile with their session history and conversions. URL Parameters:
ParameterTypeRequiredDescription
userIdstringYesVisitor ID or user ID
Response:
{
  "user": {
    "visitor_id": "v_abc123",
    "user_id": "u_def456",
    "email": "[email protected]",
    "first_seen": "2026-03-10T08:15:30Z",
    "last_seen": "2026-03-16T14:30:00Z",
    "total_events": 45,
    "total_sessions": 8,
    "country": "US",
    "city": "Austin"
  },
  "sessions": [
    {
      "session_id": "s_xxx",
      "started_at": "2026-03-16T14:00:12Z",
      "ended_at": "2026-03-16T14:05:42Z",
      "duration_seconds": 330,
      "events_count": 6,
      "pageviews_count": 4,
      "events": [
        {
          "event_name": "pageview",
          "page_path": "/",
          "received_at": "2026-03-16T14:00:12Z"
        },
        {
          "event_name": "pageview",
          "page_path": "/pricing",
          "received_at": "2026-03-16T14:01:30Z"
        },
        {
          "event_name": "signup",
          "received_at": "2026-03-16T14:03:45Z"
        }
      ]
    }
  ],
  "conversions": [
    {
      "event_name": "purchase",
      "value": 99.00,
      "received_at": "2026-03-14T10:22:15Z"
    }
  ]
}
The sessions array contains the user’s session history with individual events. The conversions array contains all conversion events associated with this user.

GET /api/v1/ads

Returns ad platform performance data from connected Meta, Google, and TikTok accounts. Parameters:
ParameterTypeRequiredDefaultDescription
start_dateISO 8601YesStart of date range
end_dateISO 8601YesEnd of date range
platformstringNoallmeta, google, or tiktok
levelstringNocampaigncampaign, adset, or ad
limitnumberNo50Maximum results (1-200)
Response:
{
  "data": [
    {
      "platform": "meta",
      "level": "campaign",
      "campaign_id": "123456",
      "campaign_name": "Spring Sale 2026",
      "status": "ACTIVE",
      "spend": 1200.50,
      "impressions": 45000,
      "clicks": 1800,
      "conversions": 45,
      "revenue": 8900.00,
      "roas": 7.41,
      "ctr": 4.0,
      "cpc": 0.67,
      "cpm": 26.68
    }
  ],
  "platforms_connected": ["meta", "google"],
  "total_spend": 3500.00,
  "total_revenue": 15200.00,
  "overall_roas": 4.34
}
Metrics in the response:
  • spend — Total ad spend in the platform’s currency
  • impressions — Number of ad impressions
  • clicks — Number of ad clicks
  • conversions — Number of conversion events
  • revenue — Total revenue attributed to conversions
  • roas — Return on ad spend (revenue / spend)
  • ctr — Click-through rate (clicks / impressions * 100)
  • cpc — Cost per click (spend / clicks)
  • cpm — Cost per thousand impressions (spend / impressions * 1000)

GET /api/v1/tags

Returns tag analytics data. Parameters:
ParameterTypeRequiredDefaultDescription
start_dateISO 8601YesStart of date range
end_dateISO 8601YesEnd of date range
limitnumberNo20Maximum results (1-100)
Response:
{
  "data": [
    { "tag": "pricing_page", "count": 450, "percentage": 12.3, "source": "web" },
    { "tag": "checkout_flow", "count": 320, "percentage": 8.8, "source": "web" }
  ],
  "total": 3650
}

GET /api/v1/workspace

Returns workspace metadata, connected integrations, and plan information. Parameters: None required. Response:
{
  "id": "abc123",
  "name": "My Site",
  "domain": "example.com",
  "timezone": "America/Chicago",
  "connected_platforms": [
    { "provider": "meta", "status": "active" },
    { "provider": "google-ads", "status": "active" },
    { "provider": "shopify", "status": "active" },
    { "provider": "stripe", "status": "active" }
  ],
  "plan": "growth_plan",
  "created_at": "2025-11-20T15:30:00Z"
}

GET /api/v1/usage

Returns current billing period usage statistics. Parameters: None required. Response:
{
  "events_used": 45000,
  "events_limit": 100000,
  "postbacks_used": 1200,
  "postbacks_limit": 5000,
  "period_start": "2026-03-01T00:00:00Z",
  "period_end": "2026-03-31T23:59:59Z",
  "plan": "growth_plan"
}
The events_used and postbacks_used values reflect consumption in the current billing period. These reset on period_start each month.

Code Examples

curl

Get overview stats for the last 7 days:
curl -X GET "https://app.datalyr.com/api/v1/overview?start_date=2026-03-10T00:00:00Z&end_date=2026-03-16T23:59:59Z" \
  -H "Authorization: Bearer dk_your_api_key"
Get traffic sources:
curl -X GET "https://app.datalyr.com/api/v1/traffic?start_date=2026-03-01T00:00:00Z&end_date=2026-03-16T23:59:59Z&type=referrer&limit=10" \
  -H "Authorization: Bearer dk_your_api_key"
Search for a user by email:
curl -X GET "https://app.datalyr.com/api/v1/users?start_date=2026-03-01T00:00:00Z&end_date=2026-03-16T23:59:59Z&[email protected]" \
  -H "Authorization: Bearer dk_your_api_key"
Get Meta Ads campaign performance:
curl -X GET "https://app.datalyr.com/api/v1/ads?start_date=2026-03-01T00:00:00Z&end_date=2026-03-16T23:59:59Z&platform=meta&level=campaign" \
  -H "Authorization: Bearer dk_your_api_key"
Get real-time visitors:
curl -X GET "https://app.datalyr.com/api/v1/realtime?time_window=30" \
  -H "Authorization: Bearer dk_your_api_key"

JavaScript (fetch)

Get overview stats:
const API_KEY = 'dk_your_api_key';
const BASE_URL = 'https://app.datalyr.com/api/v1';

async function getOverview(startDate, endDate) {
  const params = new URLSearchParams({
    start_date: startDate,
    end_date: endDate
  });

  const response = await fetch(`${BASE_URL}/overview?${params}`, {
    headers: {
      'Authorization': `Bearer ${API_KEY}`
    }
  });

  if (!response.ok) {
    throw new Error(`API error: ${response.status}`);
  }

  return response.json();
}

// Usage
const data = await getOverview(
  '2026-03-10T00:00:00Z',
  '2026-03-16T23:59:59Z'
);
console.log(`Visitors: ${data.visitors_total}`);
console.log(`Pageviews: ${data.pageviews_total}`);
Get attribution data:
async function getAttribution(startDate, endDate, windowDays = 30) {
  const params = new URLSearchParams({
    start_date: startDate,
    end_date: endDate,
    window_days: windowDays.toString()
  });

  const response = await fetch(`${BASE_URL}/attribution?${params}`, {
    headers: {
      'Authorization': `Bearer ${API_KEY}`
    }
  });

  if (!response.ok) {
    throw new Error(`API error: ${response.status}`);
  }

  return response.json();
}

const attribution = await getAttribution(
  '2026-03-01T00:00:00Z',
  '2026-03-16T23:59:59Z'
);

for (const campaign of attribution.campaigns) {
  console.log(
    `${campaign.utm_source}/${campaign.utm_campaign}: ` +
    `${campaign.conversions} conversions, $${campaign.revenue} revenue`
  );
}
Paginate through events:
async function getAllEvents(startDate, endDate, eventName) {
  const allEvents = [];
  let offset = 0;
  const limit = 1000;
  let hasMore = true;

  while (hasMore) {
    const params = new URLSearchParams({
      start_date: startDate,
      end_date: endDate,
      event_name: eventName,
      limit: limit.toString(),
      offset: offset.toString()
    });

    const response = await fetch(`${BASE_URL}/events?${params}`, {
      headers: {
        'Authorization': `Bearer ${API_KEY}`
      }
    });

    const data = await response.json();
    allEvents.push(...data.events);
    hasMore = data.has_more;
    offset += limit;
  }

  return allEvents;
}

const purchases = await getAllEvents(
  '2026-03-01T00:00:00Z',
  '2026-03-16T23:59:59Z',
  'purchase'
);
console.log(`Total purchases: ${purchases.length}`);

Handle Rate Limiting

async function fetchWithRateLimit(url, options, maxRetries = 3) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    const response = await fetch(url, options);

    if (response.status === 429) {
      const resetTimestamp = response.headers.get('X-RateLimit-Reset');
      const waitMs = (parseInt(resetTimestamp) * 1000) - Date.now();
      await new Promise(resolve => setTimeout(resolve, Math.max(waitMs, 1000)));
      continue;
    }

    return response;
  }

  throw new Error('Rate limit exceeded after retries');
}

Next Steps

AI Chat

Query your data with natural language

Web SDK

Install tracking on your website

Attribution Models

Understand how attribution works

Conversion Rules

Configure conversion postbacks