# Data streams

A **data stream** is one measurement of a device — battery percentage, temperature, signal strength — and
this API returns its **current value**, not its history.

Each instance has an alphanumeric identifier unique within its device. When that identifier matches a data
stream template of the device's data model, the instance inherits the template's characteristics: units,
period, tags and the rest. That is why a response carries not just a value but the metadata to interpret it.

## Which store do I want?

| You want | Use |
|---|---|
| The latest reading of a measurement | **Data streams**, this page |
| Values aggregated per hour, day or any period | [Time series](../time_series/) |
| A flat table of chosen values across devices | [Data sets](../data_sets/) |
| Every raw value ever collected | [Data points](../data_points/), deprecated |

## Querying data streams

A standard [Data Lake](../data_lake/) search:

```bash
POST /north/v80/search/datastreams
```

```bash
curl --request POST \
     --header "X-ApiKey: <your-api-key>" \
     --header "Content-Type: application/json" \
     --data '{"filter": {"eq": {"datastreams.datastreamId": "batteryPercentage"}}}' \
     https://api.opengate.es/north/v80/search/datastreams
```

```json
{
  "page": { "number": 1 },
  "datastreams": [
    {
      "entityIdentifier": "device_battery_id",
      "datastreamId": "batteryPercentage",
      "name": "batteryPercentage",
      "unit": {
        "label": "%",
        "symbol": "%",
        "type": "basicSI"
      },
      "period": "INSTANT",
      "datamodelId": "teliot",
      "access": "READ",
      "channel": "battery_channel",
      "organization": "battery_organization",
      "_current": {
        "value": 100,
        "date": "2019-04-15T09:18:43.926Z",
        "at": "2019-04-15T09:18:43.926Z"
      }
    }
  ]
}
```

## Reading the response

| Field | Holds |
|---|---|
| `datastreamId`, `name` | The measurement's identifier and display name |
| `entityIdentifier` | The device the value belongs to |
| `unit` | Label, symbol and type, so the number is interpretable |
| `period` | How often the value is expected, `INSTANT` for on-change values |
| `datamodelId` | The data model the definition comes from |
| `access` | Whether the stream is readable, writable or both |
| `_current.value` | The value itself |
| `_current.date` | When the platform recorded it |
| `_current.at` | When the measurement was actually taken |

The distinction between `date` and `at` matters when a device buffers readings and reports them later: `at`
is the truth about the measurement, `date` is when OpenGate learned about it.

Filter fields are prefixed `datastreams.`, and results come back as JSON by default or as CSV through header
options.

## API specification

{{< openapi src="datastreams.yaml" >}}
