Know what your app can observe
Start with the field's meaning, the match mode and the app's grants. A connected stream can legitimately contain no match or only part of a player's data.
| Context | What to expect |
|---|---|
| Self-play | Detailed statistics, losses and outcomes only for the actual local player; existing permissions and paid-data requirements still apply |
| Observer or replay | Authorized participant data may cover all players; a replay can also have isObserver: true |
| Self-play POIs | poiMode: 'initial': a frozen game-start snapshot, if captured; never advance stock timers |
| Observer/replay POIs | poiMode: 'live' permits observed updates and active timers |
| No match, missing grant or unreadable source | Fields or collections may be absent; show an unavailable/waiting state |
Use match.realBroadcasterPlayerId for the actual player. The broadcaster or selected replay
player is not authorization to expose another participant's private statistics.
Catalog metadata is static and does not grant access to live state.
Missing is different from zero
Optional fields are omitted when unknown. Zero means an observed zero; an empty
collection means an observed empty collection. Preserve that distinction in charts
and comparisons. Do not use ?? 0 for an unavailable player's economy or damage.
Helpers such as playerResourcesOrZero deliberately choose a presentation fallback;
use them only when your UI labels that fallback appropriately.
Snapshot, timer or cumulative counter?
| Value | Interpretation |
|---|---|
| Resources, hero inventory, current unit lists | Current observed snapshot |
TimedProgress |
A measured interval; use SDK interpolation rather than starting a second game clock |
statistics.goldMined |
Gross score: credited gold plus upkeep loss |
statistics.items |
Native cumulative item events/effects, not inventory differences |
statistics.units.totalAmount |
Retained engine instances including corpses, not an ever-trained total |
losses |
Sampled alive-to-dead transitions; currently incomplete |
match.outcomes |
Explicit native results; departure or disconnection does not imply a winner |
Hero lifetime uses the engine wall clock, so replay pause/speed can differ from match time. Rewinds invalidate accumulated comparisons. The analytics helper handles match and backward-clock changes; reset it on disconnects and known gaps.
Catalogs and custom maps
Load the revision in match.gameDataId, not whichever catalog is newest. Standard
names, artwork, item levels, starting charges, configured stock, costs and ability
levels come from that catalog. A custom map can override them. Custom object names
and overridden live stock limits are not currently exposed; do not label standard
catalog values as measured custom-map values.