API reference

Read your analytics from your own code: the same figures as the dashboard, as JSON. To ask an AI assistant instead, see Connect an AI assistant (MCP).

What it is for

Your own panel

Show visitors, sales or a funnel inside your admin, intranet or product.

Daily summary in Slack or by email

A script that runs every morning, reads yesterday's summary and posts it where your team reads.

Spreadsheets and BI

Copy the figures to Google Sheets, Metabase or your data warehouse to cross them with sales, CRM or costs.

Reports for clients

Agencies and freelancers: one key per client site and a monthly report built automatically.

Your own alerts

Pro already emails you about drops, spikes, 404s, goals with no conversions and new AI agents (Email alerts). For anything else, such as a day with no sales, a scheduled job that reads the figures and warns you.

A counter on your site

Show "X readers this month" from your server. Never put the key in the page.

Access

  • Part of Pro. Create a key in Settings → API and MCP, for all your sites or for one.
  • Send it in every request: Authorization: Bearer sd_…
  • Read-only: GET requests only. 60 requests per minute per key.
  • Use it from a server or a script, never from a web page: anyone could read the key in the page.

Example

curl -H "Authorization: Bearer sd_..." \
  "https://api.simpledata.dev/v1/sites/SITE_ID/summary?period=30d&compare=true"
{
  "site_id": "5b1c…",
  "range": { "start": "2026-10-01T09:00:00.000Z", "end": "2026-10-31T09:00:00.000Z", "period": "30d", "timezone": "Europe/Madrid" },
  "filters": {},
  "pageviews": 18420,
  "visitors": 6115,
  "bounce_rate": 41.2,
  "avg_visit_duration_seconds": 94,
  "views_per_visit": 2.4,
  "top_page": "/",
  "previous": {
    "range": { "start": "2026-08-31T08:59:59.999Z", "end": "2026-09-30T08:59:59.999Z" },
    "pageviews": 15002, "visitors": 5230, "bounce_rate": 43.8,
    "avg_visit_duration_seconds": 88, "views_per_visit": 2.3, "top_page": "/"
  }
}

Endpoints

All under https://api.simpledata.dev/v1. site_id is the id GET /sites returns.

GET /sitesThe sites the key can read: id, name, domain, type, currency and timezone.
GET /sites/{site_id}/summaryPageviews, visitors, bounce rate (%), visit duration (s), pages per visit and top page. compare=true adds previous: the same span before, or null if the site did not record all of it. With days imported from another tool in the range, imported says how many (days, first_day, last_day, sources, pageviews) and whether they are in the figures (included; not with a filter, excluded_reason "filters"). comparable is "pageviews" when only pageviews can be compared, because the two spans mix imported days and SimpleData's own differently (see /docs/import).
GET /sites/{site_id}/timeseriespoints: pageviews and visitors per bucket, empty ones included. interval=hour, day, week or month, on the site's clock (time is the instant each bucket starts, in UTC); by default hour up to 2 days, day up to 400 days, month beyond. Hourly covers 31 days at most.
GET /sites/{site_id}/breakdown/{dimension}rows of { value, count, visitors } for one dimension (table below). limit from 1 to 100, default 10.
GET /sites/{site_id}/realtimevisitors_last_5_minutes.
GET /sites/{site_id}/goalsEach goal with conversions, unique_conversions and conversion_rate (% of visitors).
GET /sites/{site_id}/goals/{goal_id}/propertiesA custom-event goal broken down by its properties: each key with its top values (limit, default 10 per key), events and visitors.
GET /sites/{site_id}/ecommercerevenue, orders, average_order_value, conversion_rate, add_to_cart, cart_conversion_rate, currency, top_products (limit, default 10) and revenue_by_channel.
GET /sites/{site_id}/paymentsOrders, newest first, with revenue, currency and the source, medium, channel and landing page of the buyer's first visit. total, limit (default 25, up to 100) and offset to page.
GET /sites/{site_id}/funnelsThe funnels defined on the site, with their steps.
GET /sites/{site_id}/funnels/{funnel_id}Visitors per step, conversion from the first step and from the previous one, completed and overall conversion.
GET /sites/{site_id}/pathsThe most frequent sequences of the first three pages of a session: pages, sessions, share (%). limit up to 50.
GET /sites/{site_id}/ai-trafficVisits from AI agents and crawlers: agent, purpose (user, retrieval, training or search) and visits. search is a search engine crawler, not AI traffic.
GET /sites/{site_id}/engagementScroll depth and time on page: measured (page views that sent a measurement), scroll_depth (average %), time_on_page_seconds (average), reached (measurements that saw at least 25, 50, 75 and 100 %) and pages, the top pages by measurements (limit up to 100). Each measurement is matched to a page view by visitor, page and UTC day, at most one per page view; filters apply through that match.

Parameters

periodtoday, yesterday, 7d (default), 30d, month (this calendar month), last_month, 6m, 12m or all. Calendar periods (today, yesterday, month, last_month) begin at midnight in the site's time zone (UTC unless changed in the site settings).
start, endA custom range instead of period, in ISO 8601: start=2026-10-01&end=2026-11-01. end is excluded.
filterkey:value, repeatable, all must match: filter=channel:Organic Search&filter=country:ES. Keys: pathname, referrer, channel, country, device, browser, os, utm_source, utm_medium, utm_campaign, utm_term, utm_content. key:value is exact; !key:value is "is not", ~key:value "contains" and !~key:value "does not contain" (contains ignores case), comparing the value the dashboard shows (Direct, None, Unknown for missing ones): filter=~pathname:/blog&filter=!country:ES. prop.<name>:value, with the same prefixes, keeps the sessions in which a custom event had that property. Up to 20 filters. channel is where the visit came from: every page of a visit (one visitor on one UTC day) keeps the channel of its first page. Summary, timeseries, breakdown, funnel results, paths and engagement accept filters; the MCP tools take the same text in filter, a list. With any filter, days imported from another tool are left out (summary says so in imported).

Breakdown dimensions

pages, referrers, channels, countries, devices, browsers, operating_systemscount is pageviews.
utm_sources, utm_mediums, utm_campaigns, utm_terms, utm_contentscount is pageviews. Visits without the tag show as Direct (source) or None.
entry_pages, exit_pagescount is entries or exits. Top 10 only.
outbound_links, downloadscount is clicks or downloads; value is the URL.
not_foundcount is occurrences of 404 pages; value is the path.
Days imported from another toolWithout filters they are in pages, entry and exit pages, referrers, channels, UTM tags, countries, devices, browsers and systems. Each imported day keeps its 100 biggest values per dimension and adds the rest up in a row whose value is "(other)" (see /docs/import).

Responses

  • JSON with snake_case keys. Each response repeats site_id, the range used (ISO 8601, UTC, with the site's timezone) and the filters applied.
  • Percentages go from 0 to 100. Money is in the site's currency.
  • A visitor is the weekly anonymous identifier (no cookies); a session is one visitor on one UTC day. There is nothing about individual people.
  • Fields may be added; existing ones are not renamed or removed within /v1.

Errors

An error answers with its HTTP status and a body like this:

{ "error": { "code": "site_not_found", "message": "No site with this id for this key. …" } }
400 invalid_requestA parameter is wrong. The message says what to send.
401 invalid_api_keyNo key, a key that does not exist, or one that was revoked.
403 pro_requiredThe account is on Free. The key works again after upgrading.
404 site_not_found, funnel_not_found, not_foundNot in this account, outside the key's site, or no such endpoint.
429 rate_limitedMore than 60 requests in a minute with one key. Retry-After says how many seconds to wait; RateLimit-Remaining and RateLimit-Reset come with every response.
500 internal_errorSomething failed on our side. Try again.

Related

← Back to the docs