Billable traffic per day or hour, over whole days
const url = 'https://api.nsin.ir/analytics/traffic-trend?domain=example.com&range=today&from=2026-09-21&to=2026-09-27&hostname=*.example.com&granularity=auto&split=none&compare=0';const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request GET \ --url 'https://api.nsin.ir/analytics/traffic-trend?domain=example.com&range=today&from=2026-09-21&to=2026-09-27&hostname=*.example.com&granularity=auto&split=none&compare=0' \ --header 'Authorization: Bearer <token>'Billable bytes and requests per bucket over a window of whole Asia/Tehran days, with the window’s totals, an optional split by host or by serving tier, the previous window’s totals, and the days whose data is known to be incomplete.
Bytes are billable bytes — cache + proxied + direct egress, what
billing charges for — so these numbers are the bill’s (show GB as
bytes / 1024³, as billing does). Buckets are Tehran days or Tehran
hours given as UTC instants (a Tehran day starts at 20:30 UTC, an hour
at :30). Every bucket of the window is listed — empty ones as zeros
— and only the one that holds now is partial.
granularity=hour (and auto on a window of two days or less) is
drawn from 30-minute rollups where they cover the window, or from the
request log for a window of one day. Where neither can, a longer
window is answered in days and window.granularity says so. Daily
buckets read from the hourly rollup may give up to 30 minutes around
Tehran midnight to the neighbouring day; totals are exact.
Requires analytics.view on the domain and a plan with the
monitoring feature. Answers are cached (2 minutes for today, 5 for
7d, 10 for longer windows) and shared between identical requests.
Authorizations
Section titled “Authorizations ”Parameters
Section titled “ Parameters ”Query Parameters
Section titled “Query Parameters ”The domain name (for example example.com). These endpoints take the
domain as a query parameter rather than a path segment.
Example
example.comThe window, in whole Asia/Tehran days (UTC+03:30), ending today:
today is today so far, 7d today and the 6 days before it, 30d
and 90d likewise. custom takes from and to. The window is
[Tehran midnight of the first day, min(Tehran midnight after the last day, now)) — a Tehran day starts at 20:30 UTC the evening
before.
Example
2026-09-21First day of a range=custom window, inclusive: the Gregorian date
of an Asia/Tehran calendar day. At most 400 days before today; the
window spans at most 400 days. Refused with any other range.
Example
2026-09-27Last day of a range=custom window, inclusive (a Tehran calendar
day, YYYY-MM-DD). Not before from, not after today. When it is
today the window ends now.
Example
*.example.comNarrow to one hostname of the domain, as the hostname values these
endpoints return (host keys, a file’s record) — for example
*.example.com for a wildcard record. Matched exactly, ignoring
case; unlike HostnameFilter it does not match subdomains.
Bucket size. auto is hour for a window of two days or less and
day beyond. hour is refused (400) on a window over 7 days.
Split each bucket’s bytes: host by the 5 hostnames with the most
bytes over the window plus other, tier by cache / proxied
/ direct. none adds no split.
1 adds previous: the totals of the window of equal length right before this one.
Responses
Section titled “ Responses ”The trend.
object
The window the answer covers, [from, to): whole Asia/Tehran days.
from is the Tehran midnight that starts the first day (20:30 UTC
the evening before); to is the Tehran midnight after the last day,
or now when the last day is today.
object
Tehran days in the window, a partial today included.
The bucket size the answer uses. On traffic-trend this is the
granularity actually drawn (see its granularity parameter); on
the other endpoints it is what auto would pick.
The last day is today, so to is now and the last bucket is still filling.
A window’s totals.
object
Billable bytes: cache_bytes + proxied_bytes + direct_bytes.
Every request, billable or not.
Egress bytes of requests served through the cache pipeline.
Egress bytes of requests that reached the origin through the edge proxy.
Egress bytes of requests that reached the origin without it.
cache_bytes / bytes: the share of the traffic, by bytes, that came through the cache. A fraction 0–1; 0 with no traffic.
Requests answered with status 400 or above.
errors / requests, a fraction 0–1 (unlike /analytics/summary, which returns a percentage); 0 with no requests.
The totals of the window of equal length right before this one, with that window’s bounds.
object
Billable bytes: cache_bytes + proxied_bytes + direct_bytes.
Every request, billable or not.
Egress bytes of requests served through the cache pipeline.
Egress bytes of requests that reached the origin through the edge proxy.
Egress bytes of requests that reached the origin without it.
cache_bytes / bytes: the share of the traffic, by bytes, that came through the cache. A fraction 0–1; 0 with no traffic.
Requests answered with status 400 or above.
errors / requests, a fraction 0–1 (unlike /analytics/summary, which returns a percentage); 0 with no requests.
The current window’s from.
The keys of every bucket’s split, in drawing order: the 5 hosts
with the most bytes over the window, then other (left out when
it is zero) for split=host; cache, proxied, direct for
split=tier; empty for split=none.
Every bucket of the window, oldest first, empty ones as zeros.
object
Bucket start, UTC — a Tehran midnight (day) or a Tehran hour, which starts at :30 UTC (hour).
Billable bytes.
true only on the bucket that holds now.
Billable bytes per series key — every key of series_keys, zeros
included; they add up to bytes. Absent with split=none.
object
The known-bad days that overlap the window; empty when none do.
Days whose traffic data is known to be wrong. They are marked, not repaired.
object
First day (Asia/Tehran), inclusive.
Last day, inclusive.
Text to show on the chart.
Example
{ "window": { "from": "2026-09-21T20:30:00Z", "to": "2026-09-28T14:20:00Z", "tz": "Asia/Tehran", "granularity": "hour" }, "buckets": [ { "split": { "*.example.com": 800000000000, "api.example.com": 17000000000, "other": 5900000000 } } ], "data_notes": [ { "kind": "incomplete" } ]}The domain query parameter is missing, or another parameter is not
valid: an unknown range, from/to without range=custom (or
missing with it), a date that is not YYYY-MM-DD, to before from
or after today, a custom window over 400 days or starting more than
400 days ago, granularity=hour on a window over 7 days, an unknown
split, compare, dim, or a limit out of range.
The single error shape used by every endpoint.
object
Human-readable description of what went wrong.
Examples
{ "error": "range must be today, 7d, 30d, 90d or custom"}{ "error": "a custom window spans at most 400 days"}{ "error": "granularity=hour needs a window of 7 days or less"}Missing, malformed, revoked or expired API key. (A valid key whose
account has been deactivated gets 403 account is inactive instead.)
The single error shape used by every endpoint.
object
Human-readable description of what went wrong.
Examples
{ "error": "invalid API key"}The domain has no active plan at all, so no plan feature is available
on it. Buy or renew a plan for the domain. (A plan that is active but
does not include the feature answers 403 instead.)
The single error shape used by every endpoint.
object
Human-readable description of what went wrong.
Examples
{ "error": "This domain does not have an active plan."}The domain’s plan does not include the feature this endpoint needs
(monitoring for most sections, logs for raw and top-N request data).
The single error shape used by every endpoint.
object
Human-readable description of what went wrong.
Example
{ "error": "read-only 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.
The single error shape used by every endpoint.
object
Human-readable description of what went wrong.
Example
{ "error": "read-only API key"}The key exceeded its request budget (300 requests per minute by default).
The single error shape used by every endpoint.
object
Human-readable description of what went wrong.
Examples
{ "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.
object
Human-readable description of what went wrong.
true when the query is still running rather than
failing. Retry after Retry-After seconds.
Examples
{ "error": "analytics unavailable"}{ "error": "still computing — try again in a few seconds", "pending": true}Headers
Section titled “Headers ”Example
5Seconds to wait before retrying. Sent only with pending.
The query ran out of time for this period. Retrying the same request
runs the same query again, so ask for a shorter period (or narrow it
with hostname/path) instead.
The single error shape used by every endpoint.
object
Human-readable description of what went wrong.
Examples
{ "error": "summary timed out for this period; try a shorter one"}