Endpoints
Activity & stats
Read your timeline of everything that happened, and the dashboard totals behind it, from code.
Two read-only surfaces: the activity timeline (what happened, event by event) and the statistics behind the dashboard (how big your farm is and how it is trending).
Scopes: activity.read for the timeline, stats.read for the numbers. They are separate on purpose. A reporting integration can be handed the totals without also being handed a blow-by-blow account of every ban, sale and failed task.
Nothing here writes. In particular, reading your timeline does not mark it seen: the unread badge in the dashboard only clears when a person opens the page, so a script polling every minute never hides new activity from you.
The timeline
Every event is durable and immutable, kept for 90 days. The list is newest first.
/api/v1/activityYour activity timeline, newest first.
| Filter | Values |
|---|---|
category |
account, wallet, task, workflow, trade, market, profile, billing |
type |
Array of event types, e.g. task.failed, market.listing_sold |
severity |
Array of info, success, warning, danger, gray |
problems_only |
true keeps only danger and warning, the dashboard's toggle |
since, before |
Timestamps. since is inclusive, before exclusive |
account_ids |
Up to 1,000 of your Steam account IDs |
accounts |
A filter object, using the same keys GET /accounts accepts |
curl "https://dashboard.steamlabs.dev/api/v1/activity?problems_only=1&per_page=20" \
-H "Authorization: Bearer $STEAMLABS_API_KEY"{
"data": [
{
"id": "019fb42e-9a61-70d2-818a-f6a56593f3a5",
"type": "task.failed",
"title": "Task failed",
"category": "task",
"severity": "danger",
"summary": null,
"happened_at": "2026-07-30T09:14:22+00:00",
"day": "2026-07-30",
"steam_account": { "id": "019fb42e-9a7e-728d-b960-8b4c2162898c", "username": "farm_014" },
"account_username": "farm_014",
"subject": { "type": "task", "id": "019fb431-2c88-71ea-b0a3-8ce2f5d19b07" },
"data": { "task_type": "login" }
}
],
"meta": { "page": 1, "per_page": 20, "total": 1, "last_page": 1 }
}day is the calendar date of happened_at in your timezone, which is the value the dashboard groups its day cards on. Group on it and you get the same timeline the page draws, without having to guess at a timezone.
account_username is the username captured when the event was written, so it survives the account being deleted. steam_account is null once that happens, and for events that were never about one account.
subject is the record the event is about, as a type and an ID, so you can link straight to it. It is null when the event has no subject or the subject has since been pruned.
Paging a long timeline
For a few pages, page is fine. To walk a long history, page with before instead: pass the oldest happened_at you have seen and read the next batch. That stays fast at any depth, while a high page number makes the database count and throw away everything above it.
curl "https://dashboard.steamlabs.dev/api/v1/activity?before=2026-07-30T09%3A14%3A22%2B00%3A00" \
-H "Authorization: Bearer $STEAMLABS_API_KEY"Narrowing to accounts
Naming IDs is capped at 1,000; over that you get 422 bulk_limit_exceeded with the ceiling in max. To follow more accounts than that, describe them instead:
curl "https://dashboard.steamlabs.dev/api/v1/activity?accounts[login_state][]=banned&problems_only=1" \
-H "Authorization: Bearer $STEAMLABS_API_KEY"The accounts object takes the same filters the accounts list does and is resolved server-side, so "everything that happened to every banned account" is one call regardless of how many accounts that is.
One event
/api/v1/activity/{id}One activity event.
Same shape as a list row. The timeline is denormalized, so a row already carries everything the event knows.
The summary strip
/api/v1/activity/summaryCounts for today and the trailing week, with problems and accounts touched.
{
"window_days": 7,
"timezone": "Europe/Amsterdam",
"today": 34,
"week": 214,
"problems": 6,
"accounts": 41
}today starts at midnight in your timezone. The other three cover the trailing seven days.
Statistics
/api/v1/statsYour dashboard totals: accounts, items, inventory value, wallet money, boosted time.
{
"accounts": 412,
"banned_accounts": 3,
"item_count": 8241,
"inventory_value_cents": 1284530,
"inventory_value_currency": "USD",
"wallet_cents": { "EUR": 41250, "USD": 9900 },
"boost_minutes": 184320
}Wallet money is never summed across currencies. Balances live in each account's own currency, and adding 15 PLN to 15 EUR gives a number that is wrong in both, so you get the whole map and convert with rates you trust. Inventory value is the Steam Market price snapshot, which is USD.
banned_accounts counts VAC, community and game bans. A trade-banned account is not counted, matching the dashboard card.
boost_minutes is wall-clock boosted time across your accounts, the same figure the Live page reports as hours all time. It is not the per-game ledger, which counts one hour of a ten-game plan ten times.
Inventory value over time
/api/v1/stats/inventory-valueDaily inventory value, from the nightly snapshots plus a live point for today.
days defaults to 30 and accepts up to 365.
{
"days": 30,
"currency": "USD",
"series": [
{ "day": "2026-07-29", "inventory_value_cents": 1279900 },
{ "day": "2026-07-30", "inventory_value_cents": 1284530 }
]
}History starts the day your account was first snapshotted; days before that are absent rather than zero, because you did not hold an inventory worth nothing, you held no inventory. Today is always present and always read live, so it agrees with GET /stats even before the night's snapshot run.
Tasks completed per day
/api/v1/stats/tasksCompleted tasks per day over a trailing window.
days defaults to 14 and accepts up to 90. The series is zero-filled, so a quiet day is a zero rather than a gap.
{
"days": 14,
"retention_days": 14,
"series": [
{ "day": "2026-07-29", "completed": 512 },
{ "day": "2026-07-30", "completed": 344 }
]
}retention_days is how long finished tasks are kept. Ask for a window longer than that and the extra days will read as zeros because the rows are gone, which is why days is refused outright above 90 rather than quietly shortened.
Polling these endpoints
All five are cheap by construction: the totals and both series sum columns that are kept up to date as you go, never the item table, and the answers are cached for a minute per account. Polling once a minute costs about as much as polling once an hour.
The one thing worth knowing is that the numbers can be up to a minute behind a change you just made, which is the same freshness the dashboard shows. If you need the exact moment something happened, read the timeline, not the totals.