API reference

Every report, over plain JSON

One key reads everything your dashboard shows and manages your sites. Full history by default, real response shapes below, included on every plan. Prefer asking an AI instead of writing code? Use the MCP server.

29endpoints, every dashboard report
1key per account, shown once
60requests per minute
100%of retained history by default

Base URL https://analytics.devdome.com, HTTPS only, JSON in and out. Every sample on this page is a real captured response, trimmed for length.

01

Authentication

Create a key under Account → API and send it as a Bearer token on every request. The key can read every site on the account - treat it like a password. Only a hash is stored, so it is shown exactly once; rotate or revoke it any time and the old key dies within minutes.

curl "https://analytics.devdome.com/api/v1/stats?site=example.com" \
  -H "Authorization: Bearer ddk_your_key_here"

International domains are addressed in punycode, exactly as stored: site=xn--mnchen-3ya.de for münchen.de.

02

Time windows

Every data endpoint accepts days=N or from=YYYY-MM-DD&to=YYYY-MM-DD. No window parameter means the full history your plan retains - the API never silently defaults to 30 days. The window that actually answered rides in the x-dd-effective-window response header.

03

Account and sites

Who you are and what you track. Adding and verifying sites works exactly like the dashboard wizard.

GET/api/v1/account

Who am I: account id and plan.

{"account_id": "DD12345678", "plan": "pro"}

GET/api/v1/sites

Every site on the account.

{"sites": [
  {"domain": "example.com", "verified": true,  "pending_verification": false, "category": null},
  {"domain": "newsite.com", "verified": false, "pending_verification": true,  "category": null}
]}

verified = ownership proven. pending_verification = added but not verified yet; no data access until it is.

POST/api/v1/sites

Add a site. Creates a pending claim and returns the snippet details to install.

curl -X POST "https://analytics.devdome.com/api/v1/sites" \
  -H "Authorization: Bearer ddk_..." \
  -H "content-type: application/json" \
  -d '{"domain": "newsite.com"}'

POST/api/v1/sites/{domain}/verify

Verify ownership: passes when the live homepage carries your snippet, or a DNS TXT record devdome-verify=DD... exists.

DELETE/api/v1/sites/{domain}

Remove the site from the account. Collected data is kept; full purge is dashboard-only.

04

Traffic

The headline numbers and the per-page detail. Every count comes with its bot twin, so human numbers are never inflated.

GET/api/v1/stats

Headline KPIs for the window plus the previous window (period "current" / "previous") so you can compute changes.

?site, days | from+to

[
  {"period": "current", "visitors": 2450, "new_visitors": 1830,
   "returning_visitors": 620, "bots": 1892, "pageviews": 6120,
   "bot_pageviews": 3011, "clicks": 214, "bot_clicks": 12,
   "sessions": 3105, "bounces": 1420, "session_seconds": 512400,
   "dur_sessions": 3105, "visits": 3105},
  {"period": "previous", "...": "same fields, the window before"}
]

visits = sessions with the 30-minute gap rule. session_seconds / dur_sessions = average session duration. bounces / sessions = bounce rate.

GET/api/v1/timeseries

One row per day, zero-filled, bucketed in the site timezone.

?site, days | from+to

[
  {"day": "2026-08-19", "visitors": 312, "visits": 398, "bots": 244,
   "pageviews": 801, "clicks": 31, "ctr": 7.8, "ppv": 2.01,
   "sessions": 398, "bounces": 171, "new_visitors": 231},
  {"day": "2026-08-20", "...": "one zero-filled row per day"}
]

GET/api/v1/hourly

The last 24 hours by hour (UTC timestamps).

?site

[
  {"hour": "2026-08-21T19:00:00.000Z", "visitors": 14, "bots": 6,
   "pageviews": 31, "clicks": 2, "visits": 17},
  {"...": "24 rows"}
]

GET/api/v1/pages

Per-page traffic with page health.

?site, days | from+to, limit

[
  {"page_path": "/pricing", "traffic": 302, "visitors": 287, "bots": 44,
   "clicks": 21, "status": 200,
   "checked_at": "2026-08-22T18:20:29.149+00:00",
   "_total": 214, "_t404": 3}
]

status / checked_at come from the page health prober (404 detection). With limit=N, row 0 carries _total (all pages) and _t404 (broken count).

GET/api/v1/referrers

Traffic sources, one row per referrer.

?site, days | from+to

[
  {"referrer": "google.com", "visits": 1211, "clicks": 84},
  {"referrer": "direct",     "visits": 903,  "clicks": 61},
  {"referrer": "reddit.com", "visits": 88,   "clicks": 9}
]

GET/api/v1/redirects

Redirect slugs served, with clicks through them.

?site, days | from+to

GET/api/v1/keywords

Search keywords, where engines disclose them.

?site, days | from+to

GET/api/v1/products

Amazon product clicks (Amazon Importer sites).

?site, days | from+to

05

Audience

Where visitors are and what they browse with. Rows in these tables use short keys, decoded below.

GET/api/v1/countries

Traffic by country (ISO 3166-1 alpha-2).

?site, days | from+to

[
  {"country": "US", "visitors": 5, "bots": 2, "clicks": 0,
   "pageviews": 5, "visits": 5},
  {"country": "IE", "visitors": 2, "bots": 0, "clicks": 0,
   "pageviews": 2, "visits": 2}
]

GET/api/v1/regions

Regions inside one country.

?site, country, days | from+to

GET/api/v1/cities

Cities inside one region.

?site, country, region, days | from+to

GET/api/v1/devices

Device split with sub-breakdowns.

?site, days | from+to

{"rows": [
  {"k": "desktop", "t": 9, "b": 2, "c": 0, "cb": 0, "uv": 9, "pv": 9}
 ],
 "subs": [
  {"k": "desktop", "dim": "browser", "skey": "chrome", "t": 9, "c": 0},
  {"k": "desktop", "dim": "country", "skey": "US", "t": 5, "c": 0}
]}

Short keys: k = dimension value, t = visits, b = bot visits, c = clicks, cb = bot clicks, uv = unique visitors, pv = pageviews. subs = the same value split by a second dimension.

GET/api/v1/browsers

Browser split. Same shape as devices.

?site, days | from+to

GET/api/v1/os

Operating system split. Same shape as devices.

?site, days | from+to

GET/api/v1/dates

Per-date table. Same shape as devices, keyed by date.

?site, days | from+to

06

Visitors and realtime

Individual anonymous visits with their full paths, and who is on the site right now.

GET/api/v1/visitors

Recent visits, each with its step-by-step path.

?site, days | from+to, limit

[
  {"visitor_id": "09d307d8...", "country": "US", "browser": "chrome",
   "os": "windows", "device": "desktop", "is_bot": false,
   "entry": "direct", "last_seen": "2026-08-22T08:59:27.640Z",
   "steps": [
     {"t": "2026-08-22T08:59:27.640Z", "type": "pageview",
      "page": "/pricing", "secs": 5}
   ]}
]

visitor_id is a daily-rotating anonymous hash, never a person. steps carry pageviews and outbound clicks with per-page dwell seconds.

GET/api/v1/paths

Aggregated visitor paths through the site.

?site, days | from+to

GET/api/v1/realtime

Visitors active in the last 5 minutes with their current page.

?site

07

Bots

The report nobody else gives you over an API: every detected bot with the receipt for WHY it was flagged.

GET/api/v1/bots

Every detected bot: user agent, reason, hits, IPs, networks, pages.

?site, days | from+to

[
  {"user_agent": "Mozilla/5.0 (X11; Linux x86_64) ... Chrome/124.0",
   "reason": "datacenter ASN (Amazon Data Services), automation (BotD:headless_chrome)",
   "hits": 2, "ips": 2, "countries": ["US"],
   "asns": ["Amazon Data Services Northern Virginia"],
   "pages": ["/report/example"],
   "last_seen": "2026-08-22T08:59:06.607Z"}
]

GET/api/v1/bot-threats

Detection-category totals for the window.

?site, days | from+to

[
  {"bots": 2, "ua_bots": 0, "datacenter": 2, "scanner": 0,
   "automation": 2, "no_profile": 0, "session_bot": 0, "fleet": 0}
]
08

Site health

The uptime and health monitoring that rides on the same key.

GET/api/v1/health

Full health report: uptime, response times, TLS, DNS, page checks.

?site

{"domain": "example.com",
 "meta": {"monitor_state": "up", "cadence_s": 3600, "plan": "pro",
          "effective_days": 30, "data_state": "ready",
          "coverage_24h": 0.98, "latency_metric": "ttfb_ms"},
 "sections": {"last_check": true, "incidents": true, "audit": true}}

GET/api/v1/incidents

Downtime incidents.

?site

{"incidents": [], "limit": 25, "has_more": false}

GET/api/v1/alerts

Alert history for the site.

?site

09

Export

Everything, raw.

GET/api/v1/export

Full CSV export of the raw analytics for the window. Returns text/csv, not JSON.

?site, days | from+to

Rate limits and errors

Every error is {"error": "human readable message"} with a matching status:

  • 400 - missing or malformed parameter; the message names it.
  • 401 - missing or invalid API key.
  • 403 - the site does not belong to this account.
  • 404 - unknown endpoint.
  • 423 - the account is over its plan limit and dashboards are locked.
  • 429 - rate limited (60 requests/minute per key); comes with a retry-after: 60 header.

On the roadmap

Write endpoints for site settings, share links and the bot protection policy are planned as phase 2. Tell us what you need first via the contact page.

Get your key and make the first call

The API is included on every plan, the free one too. Create the key, paste the curl above, done.