Skip to content
nsin docs

Requests over time, for period-over-period comparison

GET
/analytics/requests-compare
curl --request GET \
--url 'https://api.nsin.ir/analytics/requests-compare?granularity=hour' \
--header 'Authorization: Bearer <token>'

Request counts in whole-day windows, for charts that overlay one period on another. Unlike /analytics/requests — which ends now and takes a period — this window always starts at a local midnight, so every bucket covers a complete day and days can be compared like for like.

  • granularity: hour returns hourly buckets, meant to be drawn as one line per day (hour-by-hour overlay). days defaults to 3, max 14.
  • granularity: day returns one bucket per day for day-over-day change. days defaults to 14, max 35 — the ClickHouse row retention, beyond which no data exists.

Scope is one domain (domain_id), or — by default — every active domain you can see. The response has the time-series shape of /analytics/requests, except that each timestamp is the bucket’s start as Asia/Tehran wall-clock time, YYYY-MM-DD HH:MM:SS with no zone (not RFC 3339): 2026-09-28 00:00:00 is 2026-09-27T20:30:00Z. Buckets with no traffic are omitted rather than zero-filled.

granularity
string
default: hour
Allowed values: hour day

Bucket size. Anything other than day is treated as hour.

days
integer
>= 1 <= 35

Number of whole days to return, counting back from today. Clamped to the granularity’s maximum. 0 or omitted uses the default.

domain_id
integer

Numeric domain id — note this endpoint scopes by id, not by the domain name the rest of the API uses. Omit to cover every active domain you can see.

Time series.

Media type application/json
object
data
Array<object>

One bucket of /analytics/requests-compare.

object
timestamp

Bucket start as Asia/Tehran wall-clock time (UTC+03:30), with no zone designator — not RFC 3339.

string
/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/
count
integer
Example
{
"data": [
{
"timestamp": "2026-09-28 00:00:00"
}
]
}

Missing, malformed, revoked or expired API key. (A valid key whose account has been deactivated gets 403 account is inactive instead.)

Media type application/json

The single error shape used by every endpoint.

object
error
required

Human-readable description of what went wrong.

string
Examples
Example invalidKey
{
"error": "invalid API key"
}

No such domain, or it is not visible to this account. Domains you cannot access are reported as not found rather than forbidden.

Media type application/json

The single error shape used by every endpoint.

object
error
required

Human-readable description of what went wrong.

string
Example
{
"error": "read-only API key"
}

The key exceeded its request budget (300 requests per minute by default).

Media type application/json

The single error shape used by every endpoint.

object
error
required

Human-readable description of what went wrong.

string
Examples
Example limited
{
"error": "rate limit exceeded"
}

Either the analytics backend is temporarily unreachable (retry; no data is lost), or the answer is still being computed. The per-domain sections and the cached account-wide views (domains-overview, global-summary, global-summary/peak, requests-compare, bandwidth-overview, nodes-overview) wait at most about 25 seconds for their query; past that they answer 503 with pending: true and a Retry-After header, while the query keeps running and caches its result, so the retry is served from that cache instead of starting the same scan again. Identical concurrent requests share one computation.

Media type application/json
object
error
required

Human-readable description of what went wrong.

string
pending

true when the query is still running rather than failing. Retry after Retry-After seconds.

boolean
Examples
{
"error": "analytics unavailable"
}
Retry-After
integer
Example
5

Seconds to wait before retrying. Sent only with pending.