Skip to content

Analytics

Read the traffic of the site that owns the API key. The numbers come from Canverly’s own first-party pixel: cookieless, and bot-filtered — every counter on this page is humans only.

Method Path Scope
GET /v1/analytics/summary analytics:read
GET /v1/analytics/posts analytics:read
  • Base URL: https://api.canverly.com
  • Auth: Authorization: Bearer ck_… — scope analytics:read
  • Rate limit: 60 req/min per key

There is no site parameter. The site is derived from the key, so a key only ever reads its own traffic.

Both routes take the same three window parameters.

Parameter Type Default Notes
from string (YYYY-MM-DD, UTC) — Start of the window. When present it wins over days.
to string (YYYY-MM-DD, UTC) today End of the window, inclusive — to=2026-08-30 includes the whole of 30 August.
days integer 30 Preset window of the last N days (1–365). Ignored when from is given.

Precedence: a parseable from selects the explicit range (with to, or up to now); otherwise the days preset applies. An explicit range is clamped to 366 days.

Headline totals, a per-day series, and the most-viewed paths for the window.

Janela do terminal
curl "https://api.canverly.com/v1/analytics/summary?days=7" \
-H "Authorization: Bearer ck_live_xxx"

Explicit range:

Janela do terminal
curl "https://api.canverly.com/v1/analytics/summary?from=2026-08-01&to=2026-08-30" \
-H "Authorization: Bearer ck_live_xxx"
{
"from": "2026-08-01",
"to": "2026-08-30",
"days": 30,
"totals": { "views": 18420, "visitors": 11207, "sessions": 12958 },
"timeseries": [
{ "date": "2026-08-01", "views": 612, "visitors": 401 },
{ "date": "2026-08-02", "views": 588, "visitors": 377 }
],
"top_paths": [
{ "key": "/como-fazer-x", "views": 2140 },
{ "key": "/precos", "views": 1877 }
]
}
Field Type Notes
from string First day of the window (UTC, inclusive).
to string Last day of the window (UTC, inclusive).
days integer Span of the window in days.
totals.views integer Pageviews.
totals.visitors integer Distinct visitors.
totals.sessions integer Distinct sessions.
timeseries[].date string One UTC day, gap-filled (a day with no traffic is present with zeros).
timeseries[].views integer Pageviews that day.
timeseries[].visitors integer Distinct visitors that day.
top_paths[].key string URL path, e.g. /como-fazer-x.
top_paths[].views integer Pageviews for that path in the window.

The most-viewed content of the site, paginated.

The three window parameters above, plus:

Parameter Type Default Notes
limit integer 50 1–200. Out of range or non-numeric is a 400 — never silently clamped.
offset integer 0 Must be ≥ 0; anything else is a 400.
Janela do terminal
curl "https://api.canverly.com/v1/analytics/posts?days=30&limit=10" \
-H "Authorization: Bearer ck_live_xxx"

Second page:

Janela do terminal
curl "https://api.canverly.com/v1/analytics/posts?days=30&limit=10&offset=10" \
-H "Authorization: Bearer ck_live_xxx"
{
"items": [
{ "path": "/como-fazer-x", "views": 2140 },
{ "path": "/precos", "views": 1877 }
],
"total": 25,
"limit": 10,
"offset": 0
}
Field Type Notes
items[].path string URL path.
items[].views integer Pageviews in the window.
total integer Rows available in the ranking before pagination.
limit integer Page size applied.
offset integer Offset applied.

You have reached the end when offset + items.length >= total.

Envelope: { "error": { "code", "message" } }. Full table in Errors & rate limits.

Status error.code When
400 bad_request /v1/analytics/posts only — limit outside 1–200 or non-numeric, or a negative/non-numeric offset. The message names the offending parameter.
401 unauthorized Missing, invalid or revoked key.
403 forbidden Key lacks analytics:read.
429 rate_limited Over 60 req/min — honour Retry-After.
5xx upstream Transient upstream error; retry with backoff.
  • Cache the summary. Traffic aggregates change slowly; one call per dashboard render (or per few minutes) is plenty, and both routes share the same 60 req/min bucket as the rest of the API.
  • /posts costs the same as /summary. It is computed from the same upstream read, so requesting both is two upstream reads — if you already have the summary, you already have top_paths.
  • Zero rows is a valid answer. A brand-new site, or a window before the pixel was installed, returns zeroed totals and empty arrays, not a 404.