Stats endpoints reference
Four endpoints cover almost every reporting need. All return JSON, share the same period and filter parameters, and respond in tens of milliseconds.
- Key takeaways
- Four endpoints, /v1/stats, /pages, /sources, /goals, share period and filter params.
- Filters combine with ';' e.g. page==/pricing;country==NL.
- Numbers match the dashboard exactly, same store, same time zone.
Common parameters
site(required): the site ID.period:day,7d,30d,month,customwithfrom/toISO dates.filter: e.g.page==/pricing,source==Search,country==NL, combinable with;.
GET /v1/stats
Headline aggregates for the period:
{
"visitors": 48210,
"pageviews": 112094,
"avg_time_seconds": 161,
"bounce_rate": 0.38
}
GET /v1/pages · /v1/sources · /v1/goals
Ranked breakdowns with the same shape: an array of { key, visitors, pageviews } (goals add conversions and conversion_rate). Pagination via limit (max 1000) and offset.
A worked example
# Top pages for visits from Search, last 30 days
curl "https://api.bobray.com/v1/pages?site=br_7fk2mq&period=30d&filter=source==Search&limit=10" \
-H "Authorization: Bearer $TOKEN"Timestamps and day boundaries use the site's reporting time zone, the same numbers you see in the dashboard, no off-by-one surprises.
Common pitfalls
The mistakes we see most often on this topic, so you can skip them entirely.
- Paginating past limit=1000 by looping offsets forever, narrow the filter instead.
- Building day boundaries in UTC while the site reports in CET.
- Polling /stats every second when a webhook would push the event.
Quick reference
| Base | https://api.bobray.com/v1 |
| Periods | day · 7d · 30d · month · custom |
| Filter join | ; (AND) |
| Max limit | 1000/page |
Did this solve it? If not, write to support with your site ID, a real person replies within one business day.