# Snapshots and tracks

> One JSON per room, with everyone Cymo detects listed inside it.

## The room snapshot

`GET /v1/rooms/{room}` describes one room at one moment: whether it is observed and occupied, how many people and pets are in it, and a `people` list with each person's zones and signals. The vitals, presence and movement reads are filtered views of the same object.

`room.snapshot`

```
{
  "data": {
    "object": "room.snapshot",
    "room_id": "room_bedroom",
    "timestamp": "2026-10-24T23:55:30.000Z",
    "observation_status": "observed",
    "occupied": true,
    "person_count": 1,
    "pet_count": 0,
    "people": [
      {
        "track_id": "trk_001",
        "person_id": "person_001",
        "identity_confidence": 0.9,
        "timestamp": "2026-10-24T23:55:30.000Z",
        "zone_ids": [
          "zone_bed"
        ],
        "signals": {
          "heart_rate_bpm": {
            "value": 62,
            "timestamp": "2026-10-24T23:55:30.000Z",
            "confidence": 0.92
          },
          "respiration_rate_per_min": {
            "value": 14,
            "timestamp": "2026-10-24T23:55:30.000Z",
            "confidence": 0.92
          }
        }
      }
    ],
    "pets": []
  },
  "meta": {
    "request_id": "req_01",
    "project_id": "proj_demo",
    "livemode": false,
    "generated_at": "2026-10-24T23:55:30.000Z"
  }
}
```

## Why one snapshot, not one stream per person

People walk in and out. Separate streams per person would open and close all the time, and you would have to merge them again to answer simple questions such as how many people are in the room. One snapshot per room gives you the whole picture in one read, and it is the shape agents find easiest to reason about.

## Tracks and people

Each person gets a `track_id` such as `trk_001`. A track means "a person, tracked continuously". It is not an identity, and it can change when someone leaves and comes back.

`person_id` is a stable pseudonym that stays `null` until identity is established, with its own `identity_confidence`. Cymo never stores names: if your product needs to know who someone is, map the `person_id` to a person in your own app.

## Null means not measurable

Every signal is a measurement with its own `value`, `timestamp` and `confidence`. When Cymo can't measure something, such as heart rate while a person walks, the value is `null` and `reason` says why when it is known, for example `motion`. Cymo never fills a gap with a guess, so a number in the response is always a measurement.

The same goes for the room: `observation_status` is `observed`, `partial` or `unavailable`, and an unavailable room has `null` counts. An offline Cymo is not an empty room.
