# Data sets

{{% notice style="note" title="Limited access" icon="lock" %}}
{{% include file="include/restricted_access.md" hidefirstheading="true"  %}}
{{% /notice %}}

## What a data set is

A **data set** is a flat table over your devices: one row per device, one column per value you chose. You
pick the data streams that become columns, and the platform keeps the table current.

It is the answer to *"give me a spreadsheet of my fleet"* — the identifier, the model, the ICC, the last
reading — without writing a query that walks each device's data streams and flattens the result.

| | Data sets | [Time series](../time_series/) | [Data points](../data_points/) |
|---|---|---|---|
| Shape | One row per device | One row per device per period | One row per measurement |
| Time | Current values | Aggregated history | Full raw history |
| Best for | Exports, inventories, tabular views | Trends at scale | Auditing exact readings |

Column values are limited to **strings, numbers and booleans**. If a data stream holds an object or an
array, the column definition has to include a path down to one of those primitive values. Devices with
communication modules need one column per module.

## The two halves of the API

**[Defining a data set](defining/)** is administration: choose the columns, their paths, and which of them
are filterable, and declare the sorts a query may ask for. Done once.

**[Querying a data set](querying/)** is the daily work: `POST` a filter, read rows back as JSON or CSV.

{{% children sort="weight" %}}

## API specification

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