Skip to content

Statistics

Dinio’s DNS servers report what they answered in 10-minute windows, and Dinio keeps the data for 90 days. How far back you can read depends on your package. These routes return it shaped for charts: series (a value per time step) and top lists. Zone statistics belong to DNS hosting; client statistics to DNS filtering.

Terminal window
curl -H "Authorization: Bearer $DINIO_API_KEY" \
"https://api-dinio.bitelex.com/api/v1/stats/zones/example.com/queries?group_by=qtype&step=1h"

Every route takes:

Query
from, to ISO 8601 with an offset, e.g. 2026-10-27T08:00:00Z. Default: the last 24 hours. Aligned to 10 minutes; at most 92 days.
step auto (default: at most 300 points), or 10m, 30m, 1h, 3h, 6h, 12h, 1d, 7d. At most 2 000 points. Series only.
compare previous: also the totals of the preceding range of equal length. Series only.

Series also take:

Query
mode What the point values are: count per step (default), rate per second, or share of all series at that step (0–1).
fill true (default): a step without data is 0. false: it is left out.
limit Series kept, 1–100, default 20; the rest is merged into one series with key __other (“Other”).
group_by How to split the series; per route below.

Top lists take from, to and limit (1–100, default 20).

A zone’s statistics reach back as many days as its Owner’s package allows (auth.logs.retention_days; with 0, the zone has no statistics). Client statistics reach back filter.logs.retention_hours of the identities’ owner. A from before that — or a compare=previous range that starts before it — is refused with 403 PLAN_LIMIT, and details.requested says how far back you asked. The default, the last 24 hours, fits a package that keeps 24 hours.

{
"success": true,
"data": {
"from": 1761552000000,
"to": 1761638400000,
"step": 3600,
"mode": "count",
"total": 48210,
"rate_per_s": 0.558,
"series": [
{
"key": "1",
"label": "A",
"total": 30112,
"share": 0.625,
"rate_per_s": 0.349,
"peak": { "t": 1761580800000, "v": 2210 },
"points": [[1761552000000, 1180], [1761555600000, 1204]]
}
]
}
}
Field
from, to The range, aligned; to is exclusive.
step Step length in seconds.
total, rate_per_s Sum of every series over the range, and its average per second.
series[].key, label Raw key (rcode 3) and a readable name (NXDOMAIN).
series[].total, share The series’ sum, and its part of total.
series[].peak The busiest step: t, and its count v.
series[].points [t, value] per step.
previous_total, change With compare=previous, overall and on each series. change is relative (0.25 = +25 %), null when the previous total is 0.
{
"success": true,
"data": {
"from": 1761552000000,
"to": 1761638400000,
"items": [{ "key": "ads.tracker.example", "count": 912, "count_min": 897, "relays": 3 }]
}
}

The counts are estimates from each server’s top list, summed: count is an upper bound, count_min a lower bound, and relays the number of servers that reported the name.

These need access to the zone: a zone key reaches its own zone, a personal key the zones its user is Owner or Administrator of. :ref is the zone’s uuid or name.

GET /api/v1/stats/zones/queries

The same series as Queries to a zone, summed over every zone you can see — the zones GET /zones lists — in one request. group_by: rcode (default), qtype, geo or none; there is no name query.

Terminal window
curl -H "Authorization: Bearer $DINIO_API_KEY" \
"https://api-dinio.bitelex.com/api/v1/stats/zones/queries?group_by=none&compare=previous"
GET /api/v1/stats/zones/top

A top list of the zones you can see. Each item has zone (the name), zone_id (null for a zone no longer hosted on Dinio), queries, nxdomain, and nxdomain_share (0–1).

{
"success": true,
"data": {
"from": 1761552000000,
"to": 1761638400000,
"items": [
{
"zone": "example.com",
"zone_id": "6f1c2a9e-3d4b-4c8a-9a51-0e2f7b1d4c33",
"queries": 48210,
"nxdomain": 4120,
"nxdomain_share": 0.085
}
]
}
}
GET /api/v1/stats/zones/:ref/queries

A series of the queries to the zone. group_by: rcode (default), qtype, geo (country), name, or none. Queries for names that don’t exist are included as rcode 3, or as an NXDOMAIN series for the other groupings. Query name limits it to one full name, then without NXDOMAIN.

GET /api/v1/stats/zones/:ref/nx

NXDOMAIN answers under the zone. Returns count, a series as above, and unique_max: [t, value] points estimating how many distinct non-existent names were asked in each step. It is a lower bound — distinct counts can’t be added up across servers or windows.

GET /api/v1/stats/zones/:ref/names

A top list of the zone’s names. Each item has name, queries, rcodes and qtypes (counts by readable name, e.g. { "NOERROR": 120, "NXDOMAIN": 3 }), and error_share: the part of the answers that weren’t NOERROR.

GET /api/v1/stats/zones/:ref/nx-names

A top list of names under the zone that don’t exist — typos, scanners, or records you forgot.

These need a personal key; a zone key gets 403. Without a query they cover all of your client identities; client_id (an identity’s uuid) narrows them to one.

GET /api/v1/stats/clients/events

A series of your clients’ lookups by outcome. group_by: event_type (default), client (labelled with each identity’s identify), or none. Event types include normal, sinkhole (blocked by a list), negative and request_fail; the share of sinkhole is the share that was blocked.

Terminal window
curl -H "Authorization: Bearer $DINIO_API_KEY" \
"https://api-dinio.bitelex.com/api/v1/stats/clients/events?client_id=$IDENTITY_ID&mode=share"
GET /api/v1/stats/clients/rcodes

A series of the answers to your clients. group_by: rcode (default), client or none.

GET /api/v1/stats/clients/blocked

A top list of the names your lists blocked most often.

422 for a bad range — from not before to, more than 92 days, or a step that gives more than 2 000 points. 403 PLAN_LIMIT for a range further back than the package allows. 503 TELEMETRY_DISABLED when statistics are not available.