Skip to content
nsin docs

Billable traffic per day or hour, over whole days

GET
/analytics/traffic-trend
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.

domain
required
string

The domain name (for example example.com). These endpoints take the domain as a query parameter rather than a path segment.

Example
example.com
range
string
default: 7d
Allowed values: today 7d 30d 90d custom

The 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.

from
string format: date
Example
2026-09-21

First 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.

to
string format: date
Example
2026-09-27

Last 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.

hostname
string
Example
*.example.com

Narrow 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.

granularity
string
default: auto
Allowed values: auto hour day

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
string
default: none
Allowed values: none host tier

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.

compare
string
default: 0
Allowed values: 0 1

1 adds previous: the totals of the window of equal length right before this one.

The trend.

Media type application/json
object
window
required

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
from
required
string format: date-time
to
required
string format: date-time
tz
required
string
Allowed value: Asia/Tehran
days
required

Tehran days in the window, a partial today included.

integer
granularity
required

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.

string
Allowed values: hour day
partial_last
required

The last day is today, so to is now and the last bucket is still filling.

boolean
totals
required

A window’s totals.

object
bytes
required

Billable bytes: cache_bytes + proxied_bytes + direct_bytes.

integer
requests
required

Every request, billable or not.

integer
cache_bytes
required

Egress bytes of requests served through the cache pipeline.

integer
proxied_bytes
required

Egress bytes of requests that reached the origin through the edge proxy.

integer
direct_bytes
required

Egress bytes of requests that reached the origin without it.

integer
cached_share
required

cache_bytes / bytes: the share of the traffic, by bytes, that came through the cache. A fraction 0–1; 0 with no traffic.

number
<= 1
errors
required

Requests answered with status 400 or above.

integer
error_rate
required

errors / requests, a fraction 0–1 (unlike /analytics/summary, which returns a percentage); 0 with no requests.

number
<= 1
previous
required
One of:

The totals of the window of equal length right before this one, with that window’s bounds.

object
bytes
required

Billable bytes: cache_bytes + proxied_bytes + direct_bytes.

integer
requests
required

Every request, billable or not.

integer
cache_bytes
required

Egress bytes of requests served through the cache pipeline.

integer
proxied_bytes
required

Egress bytes of requests that reached the origin through the edge proxy.

integer
direct_bytes
required

Egress bytes of requests that reached the origin without it.

integer
cached_share
required

cache_bytes / bytes: the share of the traffic, by bytes, that came through the cache. A fraction 0–1; 0 with no traffic.

number
<= 1
errors
required

Requests answered with status 400 or above.

integer
error_rate
required

errors / requests, a fraction 0–1 (unlike /analytics/summary, which returns a percentage); 0 with no requests.

number
<= 1
from
required
string format: date-time
to
required

The current window’s from.

string format: date-time
series_keys
required

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.

Array<string>
buckets
required

Every bucket of the window, oldest first, empty ones as zeros.

Array<object>
object
t
required

Bucket start, UTC — a Tehran midnight (day) or a Tehran hour, which starts at :30 UTC (hour).

string format: date-time
bytes
required

Billable bytes.

integer
requests
required
integer
partial
required

true only on the bucket that holds now.

boolean
split

Billable bytes per series key — every key of series_keys, zeros included; they add up to bytes. Absent with split=none.

object
key
additional properties
integer
data_notes
required

The known-bad days that overlap the window; empty when none do.

Array<object>

Days whose traffic data is known to be wrong. They are marked, not repaired.

object
from
required

First day (Asia/Tehran), inclusive.

string format: date
to
required

Last day, inclusive.

string format: date
kind
required
string
note
required

Text to show on the chart.

string
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.

Media type application/json

The single error shape used by every endpoint.

object
error
required

Human-readable description of what went wrong.

string
Examples
{
"error": "range must be today, 7d, 30d, 90d or custom"
}

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"
}

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.)

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 noPlan
{
"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).

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"
}

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.

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.

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 timedOut
{
"error": "summary timed out for this period; try a shorter one"
}