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.
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.
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.
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.
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.
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
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
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
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}
] 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
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.