Plays grouped by a dimension, by day or by hour
GET /api/v1/stats/plays
https://app.tanba-ooh.kz/api/v1/stats/plays
Scope read:stats. Own organisation; the authority and analysts see the city. The plays are the ones the bill counts: per structure, approval and hour the billable tier with the most plays gives the figure and tiers are never added up, so the total of any dimension equals the total by structure. by picks the dimension: structure, approval, district, format, class, daypart (the Almaty dayparts of the dictionary) or category (the product category of the submission behind the approval; none when it has none). grain cuts each key into Almaty days (up to 90) or hours (up to 7 days). Keys come busiest first and are paged with limit and offset; total is the number of keys and plays_total the plays of all of them. tiers splits the plays of a key by the tier that gave their basis, so the four numbers add up to total. With output=csv every key is returned, one row per key and bucket that has plays.
Authentication
API key in the Authorization header, or a console session.
Scope: read:stats
Parameters
| Name | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
by | query | string | no | Dimension to group by. structure, approval, district, format, class, daypart, category | district |
grain | query | string | no | Length of one bucket: an Almaty day or an hour. day, hour | day |
days | query | integer | no | Days back, today included. Up to 90 with grain=day; up to 7 (default 1) with grain=hour. | 30 |
limit | query | integer | no | Keys per page; ignored with output=csv. | 50 |
offset | query | integer | no | Keys to skip; ignored with output=csv. | 0 |
output | query | string | no | csv returns UTF-8 with a byte-order mark and the columns key, label, bucket, plays, plays_mtls, plays_signed, plays_attested, plays_native. json, csv | json |
sep | query | string | no | Column separator; semicolon for spreadsheets set to a comma decimal mark. comma, semicolon | comma |
Responses
200 The keys with their plays per bucket, or a CSV with `output=csv`.
application/json
| Name | Type | Required | Description | Example |
|---|---|---|---|---|
by | string | yes | The dimension asked for. | "district" |
grain | string | yes | Length of one bucket. day, hour | |
days | array of string (date) | With grain=day, the first moment of each bucket as an Almaty date; counts of an item follow this order. | ||
hours | array of string (date-time) | With grain=hour, the start of each bucket as an Almaty timestamp; counts of an item follow this order. | ||
items | array of PlayStat | yes | One entry per key on this page, busiest first. | |
items[].key | string | yes | Stable value of the dimension: a structure id, an approval number, a district, format, class or daypart code, a category id or none. | "medeu" |
items[].label | string | yes | Readable name of the key in English (the structure code for structure). | "Medeu" |
items[].total | integer (int64) | yes | Plays of the key in the whole window. | 18420 |
items[].counts | array of integer (int64) | yes | Plays per bucket, in the order of days or hours. | |
items[].tiers | object | yes | Plays of the key by the tier that gave their basis; the four numbers add up to total. | |
items[].tiers.mtls | integer (int64) | yes | Plays on the device-certificate tier. | 18420 |
items[].tiers.signed | integer (int64) | yes | Plays on the device-signature tier. | 0 |
items[].tiers.attested | integer (int64) | yes | Plays on the signed operator CMS tier. | 0 |
items[].tiers.native | integer (int64) | yes | Plays on the player-report tier. | 0 |
total | integer | yes | Number of keys, across all pages. | 12 |
plays_total | integer (int64) | yes | Plays of all keys, across all pages. | 481200 |
Example
{
"by": "district",
"grain": "day",
"days": [
"2026-10-12"
],
"hours": [
"2026-10-12T14:00:00+05:00"
],
"items": [
{
"key": "medeu",
"label": "Medeu",
"total": 18420,
"counts": [
612
],
"tiers": {
"mtls": 18420,
"signed": 0,
"attested": 0,
"native": 0
}
}
],
"total": 12,
"plays_total": 481200
}
text/csv
Example
string
Errors
Errors are problem documents (application/problem+json) with a stable code.
| Status | Meaning |
|---|---|
| 401 | No valid session or API key (unauthenticated, session_expired, invalid_api_key). |
| 403 | The role or the key's scope does not allow this (forbidden, key_scope_denied, key_route_denied). |
| 422 | Field errors (validation_failed). |
| default | An error as a problem document. |
Code samples
curl
curl 'https://app.tanba-ooh.kz/api/v1/stats/plays' \
-H 'Authorization: Bearer YOUR_API_KEY'
Python
import requests
response = requests.get(
"https://app.tanba-ooh.kz/api/v1/stats/plays",
headers={
"Authorization": "Bearer YOUR_API_KEY",
},
)
print(response.status_code, response.text)
Go
package main
import (
"fmt"
"io"
"net/http"
)
func main() {
req, err := http.NewRequest("GET", "https://app.tanba-ooh.kz/api/v1/stats/plays", nil)
if err != nil {
panic(err)
}
req.Header.Set("Authorization", "Bearer YOUR_API_KEY")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
data, _ := io.ReadAll(resp.Body)
fmt.Println(resp.Status, string(data))
}