uclogserver
Log in

Usage statistics

Every request that touches your account is recorded — uploads, downloads, update checks and API calls — and kept for 100 days. These endpoints give daily totals and the raw request log. IP addresses are shown as networks (/24 for IPv4, /48 for IPv6), and requests made by the service's administrators appear as service administrator.

Retrieve a usage summary

GET /stats/summary

Bearer token · scope stats:read

Daily totals for a period (default: the last 30 days) and current counts.

errors counts 5xx responses.

Query parameters

from date

YYYY-MM-DD or RFC 3339; default 30 days ago.

to date

YYYY-MM-DD or RFC 3339; default now.

GET /stats/summary
curl "https://fw.unitcircle.ca/stats/summary?from=2026-09-24" \
  -H "Authorization: Bearer eyJhbGciOiJFZERTQSIsImtpZCI6IjIwMjYtMTAtMDEtYjItaiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2Z3LnVuaXRjaXJjbGUuY2EiLCJzdWIiOiJzdmM6c2FuZGJveCByZWFkLW9ubHkgKHB1YmxpYykiLCJhdWQiOlsidWNsb2dzZXJ2ZXIiXSwiZXhwIjoxODIyNDE0NTE3LCJuYmYiOjE3OTA4Nzg1MTIsImlhdCI6MTc5MDg3ODUxNywianRpIjoiMDFhMGY4YWQtODkwZi03ODA5LWI3YTgtMDE0MTZlOWM0YTI3IiwidHlwIjoiYXBpIiwiY3VzdCI6InNhbmRib3guZXhhbXBsZSIsImNpZCI6IjAxYTBmOGExLTEzYWMtN2QzNC05NDEyLTMwYjAwOGFkYzk4NyIsInNjcCI6ImZ3OnJlYWQgbG9nZGF0YTpyZWFkIGRldmljZXM6cmVhZCB0YWdzOnJlYWQgc3RhdHM6cmVhZCJ9.IaQSEW8c2zmJWEioQ8PBaezftMriGUzGQhIof_T7HGG4Usjt9dRmhj-xiw_tMuEYcsR7EzLzXyELG0DrdJGADQ"
http -A bearer -a eyJhbGciOiJFZERTQSIsImtpZCI6IjIwMjYtMTAtMDEtYjItaiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2Z3LnVuaXRjaXJjbGUuY2EiLCJzdWIiOiJzdmM6c2FuZGJveCByZWFkLW9ubHkgKHB1YmxpYykiLCJhdWQiOlsidWNsb2dzZXJ2ZXIiXSwiZXhwIjoxODIyNDE0NTE3LCJuYmYiOjE3OTA4Nzg1MTIsImlhdCI6MTc5MDg3ODUxNywianRpIjoiMDFhMGY4YWQtODkwZi03ODA5LWI3YTgtMDE0MTZlOWM0YTI3IiwidHlwIjoiYXBpIiwiY3VzdCI6InNhbmRib3guZXhhbXBsZSIsImNpZCI6IjAxYTBmOGExLTEzYWMtN2QzNC05NDEyLTMwYjAwOGFkYzk4NyIsInNjcCI6ImZ3OnJlYWQgbG9nZGF0YTpyZWFkIGRldmljZXM6cmVhZCB0YWdzOnJlYWQgc3RhdHM6cmVhZCJ9.IaQSEW8c2zmJWEioQ8PBaezftMriGUzGQhIof_T7HGG4Usjt9dRmhj-xiw_tMuEYcsR7EzLzXyELG0DrdJGADQ GET "https://fw.unitcircle.ca/stats/summary?from=2026-09-24"
import requests

r = requests.get(
    "https://fw.unitcircle.ca/stats/summary",
    params={
        "from": "2026-09-24"
    },
    headers={"Authorization": "Bearer eyJhbGciOiJFZERTQSIsImtpZCI6IjIwMjYtMTAtMDEtYjItaiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2Z3LnVuaXRjaXJjbGUuY2EiLCJzdWIiOiJzdmM6c2FuZGJveCByZWFkLW9ubHkgKHB1YmxpYykiLCJhdWQiOlsidWNsb2dzZXJ2ZXIiXSwiZXhwIjoxODIyNDE0NTE3LCJuYmYiOjE3OTA4Nzg1MTIsImlhdCI6MTc5MDg3ODUxNywianRpIjoiMDFhMGY4YWQtODkwZi03ODA5LWI3YTgtMDE0MTZlOWM0YTI3IiwidHlwIjoiYXBpIiwiY3VzdCI6InNhbmRib3guZXhhbXBsZSIsImNpZCI6IjAxYTBmOGExLTEzYWMtN2QzNC05NDEyLTMwYjAwOGFkYzk4NyIsInNjcCI6ImZ3OnJlYWQgbG9nZGF0YTpyZWFkIGRldmljZXM6cmVhZCB0YWdzOnJlYWQgc3RhdHM6cmVhZCJ9.IaQSEW8c2zmJWEioQ8PBaezftMriGUzGQhIof_T7HGG4Usjt9dRmhj-xiw_tMuEYcsR7EzLzXyELG0DrdJGADQ"},
)
print(r.status_code, r.json())
Response
{
  "from": "2026-09-24T00:00:00Z",
  "to": "2026-09-26T01:04:37.575616Z",
  "days": [
    {"day": "2026-09-25", "requests": 42, "errors": 0, "firmware_uploads": 0, "logdata_uploads": 2,
     "firmware_downloads": 1, "notes_downloads": 0, "logdata_downloads": 2, "update_checks": 19},
    {"day": "2026-09-26", "requests": 54, "errors": 0, "firmware_uploads": 6, "logdata_uploads": 2,
     "firmware_downloads": 0, "notes_downloads": 0, "logdata_downloads": 0, "update_checks": 5}
  ],
  "totals": {"firmware": 7, "logdata": 2, "devices": 4, "tags": 4, "active_tokens": 6, "stored_bytes": 29357}
}

List requests

GET /stats/events

Bearer token · scope stats:read

The request log, newest first (default: the last 7 days).

Query parameters

from date

Default 7 days ago.

to date

Default now.

route string

Only this route pattern, e.g. /logdata/{name}.

status integer

Only this status code.

limit integer

1–1000, default 100.

offset integer

Number of items to skip; use next_offset from the previous page.

GET /stats/events
curl "https://fw.unitcircle.ca/stats/events?limit=2" \
  -H "Authorization: Bearer eyJhbGciOiJFZERTQSIsImtpZCI6IjIwMjYtMTAtMDEtYjItaiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2Z3LnVuaXRjaXJjbGUuY2EiLCJzdWIiOiJzdmM6c2FuZGJveCByZWFkLW9ubHkgKHB1YmxpYykiLCJhdWQiOlsidWNsb2dzZXJ2ZXIiXSwiZXhwIjoxODIyNDE0NTE3LCJuYmYiOjE3OTA4Nzg1MTIsImlhdCI6MTc5MDg3ODUxNywianRpIjoiMDFhMGY4YWQtODkwZi03ODA5LWI3YTgtMDE0MTZlOWM0YTI3IiwidHlwIjoiYXBpIiwiY3VzdCI6InNhbmRib3guZXhhbXBsZSIsImNpZCI6IjAxYTBmOGExLTEzYWMtN2QzNC05NDEyLTMwYjAwOGFkYzk4NyIsInNjcCI6ImZ3OnJlYWQgbG9nZGF0YTpyZWFkIGRldmljZXM6cmVhZCB0YWdzOnJlYWQgc3RhdHM6cmVhZCJ9.IaQSEW8c2zmJWEioQ8PBaezftMriGUzGQhIof_T7HGG4Usjt9dRmhj-xiw_tMuEYcsR7EzLzXyELG0DrdJGADQ"
http -A bearer -a eyJhbGciOiJFZERTQSIsImtpZCI6IjIwMjYtMTAtMDEtYjItaiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2Z3LnVuaXRjaXJjbGUuY2EiLCJzdWIiOiJzdmM6c2FuZGJveCByZWFkLW9ubHkgKHB1YmxpYykiLCJhdWQiOlsidWNsb2dzZXJ2ZXIiXSwiZXhwIjoxODIyNDE0NTE3LCJuYmYiOjE3OTA4Nzg1MTIsImlhdCI6MTc5MDg3ODUxNywianRpIjoiMDFhMGY4YWQtODkwZi03ODA5LWI3YTgtMDE0MTZlOWM0YTI3IiwidHlwIjoiYXBpIiwiY3VzdCI6InNhbmRib3guZXhhbXBsZSIsImNpZCI6IjAxYTBmOGExLTEzYWMtN2QzNC05NDEyLTMwYjAwOGFkYzk4NyIsInNjcCI6ImZ3OnJlYWQgbG9nZGF0YTpyZWFkIGRldmljZXM6cmVhZCB0YWdzOnJlYWQgc3RhdHM6cmVhZCJ9.IaQSEW8c2zmJWEioQ8PBaezftMriGUzGQhIof_T7HGG4Usjt9dRmhj-xiw_tMuEYcsR7EzLzXyELG0DrdJGADQ GET "https://fw.unitcircle.ca/stats/events?limit=2"
import requests

r = requests.get(
    "https://fw.unitcircle.ca/stats/events",
    params={
        "limit": "2"
    },
    headers={"Authorization": "Bearer eyJhbGciOiJFZERTQSIsImtpZCI6IjIwMjYtMTAtMDEtYjItaiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2Z3LnVuaXRjaXJjbGUuY2EiLCJzdWIiOiJzdmM6c2FuZGJveCByZWFkLW9ubHkgKHB1YmxpYykiLCJhdWQiOlsidWNsb2dzZXJ2ZXIiXSwiZXhwIjoxODIyNDE0NTE3LCJuYmYiOjE3OTA4Nzg1MTIsImlhdCI6MTc5MDg3ODUxNywianRpIjoiMDFhMGY4YWQtODkwZi03ODA5LWI3YTgtMDE0MTZlOWM0YTI3IiwidHlwIjoiYXBpIiwiY3VzdCI6InNhbmRib3guZXhhbXBsZSIsImNpZCI6IjAxYTBmOGExLTEzYWMtN2QzNC05NDEyLTMwYjAwOGFkYzk4NyIsInNjcCI6ImZ3OnJlYWQgbG9nZGF0YTpyZWFkIGRldmljZXM6cmVhZCB0YWdzOnJlYWQgc3RhdHM6cmVhZCJ9.IaQSEW8c2zmJWEioQ8PBaezftMriGUzGQhIof_T7HGG4Usjt9dRmhj-xiw_tMuEYcsR7EzLzXyELG0DrdJGADQ"},
)
print(r.status_code, r.json())
Response
{
  "items": [
    {
      "ts": "2026-09-26T01:02:53.777855Z",
      "actor": "token:01a0dac8-6da3-7697-a806-fac3085296d0",
      "method": "PUT",
      "route": "/logdata/{name}",
      "path": "/logdata/6d0635a7…c2",
      "status": 403,
      "ip": "203.0.113.0/24",
      "user_agent": "",
      "bytes_in": 0,
      "bytes_out": 299,
      "duration_ms": 2,
      "request_id": "52481242-ca54-47c1-939b-804d70511ba0"
    },
    {
      "ts": "2026-09-26T01:02:53.749765Z",
      "actor": "token:01a0dac8-6da2-77d7-8129-cea999b9a753",
      "method": "GET",
      "route": "/logdata",
      "path": "/logdata",
      "status": 200,
      "ip": "203.0.113.0/24",
      "user_agent": "",
      "bytes_in": 0,
      "bytes_out": 1128,
      "duration_ms": 7,
      "request_id": "b3c93b80-bc9f-4279-bb62-2ac97c41ce09"
    }
  ],
  "next_offset": 2
}