# Accessing Data

There are three ways of accessing your data in the BACE system:

1. **The Fastest**: the `data-downsampled` endpoint \
   Use this endpoint when you want to poll data with fast response times, e.g. for graphing purposes.
2. **The Easiest**: webhooks\
   Use a webhook when you want retrieve all raw data continuously.&#x20;
3. **The Most Precise**: the `data` endpoint\
   Use this endpoint for a one-time export of raw data over a certain time period.

The `data-downsampled` and `data` endpoints are explained in this section. Note that a separate section is dedicated to webhooks.

{% content-ref url="../integrations/bace-webhooks" %}
[bace-webhooks](https://docs.bace-iot.com/integrations/bace-webhooks)
{% endcontent-ref %}

## Accessing data, the fast way

Down-sampled data is a great way of improving performance of retrieving data. Raw data in the BACE system is aggregated per minute, hour and day for this reason. In general we recommend the `data-downsampled`endpoint for accessing data. This endpoint is the most high performing endpoint for data polling. It is excellent for graphing and visualisation purposes.

A list of all downsampled endpoints accessible by user can be retrieved as follows:

## List downsampled data

<mark style="color:blue;">`GET`</mark> `https://dashboard.bace-iot.com/api/v2/data-downsampled/index`

The response will be a paginated list of all downsampled endpoints accessible by the users.

{% tabs %}
{% tab title="200: OK A paginated list of all downsampled datapoints" %}

```javascript
"items": [
        {
            "id_container_data_latest": "112e51e6-...",
            "id_group": "b7624b4d-...",
            "datatype": 2073,
            "source_device": "007ed6e0-...",
            "timestamp_seconds": 1647907200,
            "min_val": 0,
            "max_val": 0,
            "avg_val": 0,
            "count_val": 263
        },
        {
            "id_container_data_latest": "1aec07ea-...",
            "id_group": "b7624b4d-...",
            "datatype": 2070,
            "source_device": "007ed6e0-...",
            "timestamp_seconds": 1647907200,
            "min_val": 0,
            "max_val": 59.5999984741,
            "avg_val": 7.93155873229467,
            "count_val": 263
        },
        {
            "id_container_data_latest": "2f333ae8-...",
            "id_group": "b7624b4d-...",
            "datatype": 2101,
            "source_device": "007ed6e0-...",
            "timestamp_seconds": 1647993600,
            "min_val": 43806,
            "max_val": 57005,
            "avg_val": 52856.7428571429,
            "count_val": 35
        },
        {
            "id_container_data_latest": "490beb6b-...",
            "id_group": "b7624b4d-...",
            "datatype": 5003,
            "source_device": "007ed6e0-...",
            "timestamp_seconds": 1647993600,
            "min_val": 0,
            "max_val": 27,
            "avg_val": 6.84732824427481,
            "count_val": 262
        },
        {
            "id_container_data_latest": "858424d7-...",
            "id_group": "b7624b4d-...",
            "datatype": 2071,
            "source_device": "007ed6e0-...",
            "timestamp_seconds": 1647907200,
            "min_val": 59.5999984741,
            "max_val": 59.5999984741,
            "avg_val": 59.5999984741001,
            "count_val": 263
        },
        {
            "id_container_data_latest": "8faac4b0-...",
            "id_group": "b7624b4d-...",
            "datatype": 5000,
            "source_device": "007ed6e0-...",
            "timestamp_seconds": 1647993600,
            "min_val": 27.7362060547,
            "max_val": 30.3244018555,
            "avg_val": 29.0922662866034,
            "count_val": 262
        },
        {
            "id_container_data_latest": "acb5d7fe-...",
            "id_group": "b7624b4d-...",
            "datatype": 2072,
            "source_device": "007ed6e0-...",
            "timestamp_seconds": 1647907200,
            "min_val": 390,
            "max_val": 390.6000061035,
            "avg_val": 390.079848720998,
            "count_val": 263
        },
        {
            "id_container_data_latest": "b8c1c262-...",
            "id_group": "b7624b4d-...",
            "datatype": 2100,
            "source_device": "007ed6e0-...",
            "timestamp_seconds": 1647993600,
            "min_val": 0,
            "max_val": 57005,
            "avg_val": 52372.1140065147,
            "count_val": 307
        },
        {
            "id_container_data_latest": "c8bb58e9-...",
            "id_group": "b7624b4d-...",
            "datatype": 2102,
            "source_device": "007ed6e0-...",
            "timestamp_seconds": 1647993600,
            "min_val": 43806,
            "max_val": 47836,
            "avg_val": 45072.5714285714,
            "count_val": 35
        },
        {
            "id_container_data_latest": "f54d5550-...",
            "id_group": "b7624b4d-...",
            "datatype": 5001,
            "source_device": "007ed6e0-...",
            "timestamp_seconds": 1647993600,
            "min_val": 24.7131347656,
            "max_val": 33.5266113281,
            "avg_val": 27.4022924991168,
            "count_val": 262
        }
    ],
    "_links": {
        "self": {
            "href": "https://evalan-dev-bace-webapp.azurewebsites.net/api/v2/data-downsampled?filter%5Bid_group%5D=b7624b4d-...&page=1"
        },
        "first": {
            "href": "https://evalan-dev-bace-webapp.azurewebsites.net/api/v2/data-downsampled?filter%5Bid_group%5D=b7624b4d-...&page=1"
        },
        "last": {
            "href": "https://evalan-dev-bace-webapp.azurewebsites.net/api/v2/data-downsampled?filter%5Bid_group%5D=b7624b4d-...&page=1"
        }
    },
    "_meta": {
        "totalCount": 10,
        "pageCount": 1,
        "currentPage": 1,
        "perPage": 500
    }
```

{% endtab %}
{% endtabs %}

By default you will receive aggregated data per day from the device. In order to get more precise data we should request a smaller chunks of time, like so:

## Access downsampled data

<mark style="color:blue;">`GET`</mark> `https://dashboard.bace-iot.com/api/v2/data-downsampled`

Filters are recommend to access downsampled data. In this example, a time interval and group filter is set.

#### Query Parameters

| Name                             | Type                | Description       |
| -------------------------------- | ------------------- | ----------------- |
| filter\[id\_group]               | 4c1c81ca-...        |                   |
| filter\[timestamp\_seconds]\[gt] | 1652691600          | From timestamp    |
| filter\[timestamp\_seconds]\[lt] | 1652778001          | To timestamp      |
| sort                             | -timestamp\_seconds | Sort on timestamp |

{% tabs %}
{% tab title="200: OK Aggregated data within specified timestamps, sorted by timestamp descending." %}

```javascript
{
    "items": [
        {
            "id_container_data_latest": "c1dafb46-...",
            "id_group": "4c1c81ca-...",
            "datatype": 5205,
            "source_device": "6b88b4df-...",
            "timestamp_seconds": 1652706000,
            "min_val": 4.106001,
            "max_val": 4.21,
            "avg_val": 4.12140803703704,
            "count_val": 27
        },
        {
            "id_container_data_latest": "f2d754ba-...",
            "id_group": "4c1c81ca-...",
            "datatype": 6000,
            "source_device": "8329650b-...",
            "timestamp_seconds": 1652706000,
            "min_val": 1,
            "max_val": 1,
            "avg_val": 1,
            "count_val": 27
        },
        {
            "id_container_data_latest": "8e00087e-...",
            "id_group": "4c1c81ca-...",
            "datatype": 6000,
            "source_device": "d6a18bf2-...",
            "timestamp_seconds": 1652702400,
            "min_val": 100,
            "max_val": 103,
            "avg_val": 101.5,
            "count_val": 2
        },
        {
            "id_container_data_latest": "c1dafb46-...",
            "id_group": "4c1c81ca-...",
            "datatype": 5205,
            "source_device": "6b88b4df-...",
            "timestamp_seconds": 1652702400,
            "min_val": 4.090001,
            "max_val": 4.126667,
            "avg_val": 4.10807645454545,
            "count_val": 55
        },
        {
            "id_container_data_latest": "f2d754ba-...",
            "id_group": "4c1c81ca-...",
            "datatype": 6000,
            "source_device": "8329650b-...",
            "timestamp_seconds": 1652702400,
            "min_val": 1,
            "max_val": 1,
            "avg_val": 1,
            "count_val": 5
        }
    ],
    "_links": {
        "self": {
            "href": "https://dashboard.bace-iot.com/api/v2/data-downsampled?filter%5Bid_group%5D=4c1c81ca-1ef9-47ac-9c03-97060db9d021&filter%5Btimestamp_seconds%5D%5Bgt%5D=1652691600&filter%5Btimestamp_seconds%5D%5Blt%5D=1652778001&sort=-timestamp_seconds&page=1"
        },
        "first": {
            "href": "https://dashboard.bace-iot.com/api/v2/data-downsampled?filter%5Bid_group%5D=4c1c81ca-1ef9-47ac-9c03-97060db9d021&filter%5Btimestamp_seconds%5D%5Bgt%5D=1652691600&filter%5Btimestamp_seconds%5D%5Blt%5D=1652778001&sort=-timestamp_seconds&page=1"
        },
        "last": {
            "href": "https://dashboard.bace-iot.com/api/v2/data-downsampled?filter%5Bid_group%5D=4c1c81ca-1ef9-47ac-9c03-97060db9d021&filter%5Btimestamp_seconds%5D%5Bgt%5D=1652691600&filter%5Btimestamp_seconds%5D%5Blt%5D=1652778001&sort=-timestamp_seconds&page=1"
        }
    },
    "_meta": {
        "totalCount": 5,
        "pageCount": 1,
        "currentPage": 1,
        "perPage": 500
    }
}
```

{% endtab %}
{% endtabs %}

Because the time interval the data was requested over was more than a day in this case, the endpoint responded with hour aggregates. The precision of the data depends, i.e. the aggregation period is determined by the time interval data is requested over. The smaller the time interval, the more precise the data will be. The logic for this is shown in the schematic below.

![Logic for retrieving more precise data from down-sampled endpoint](https://2186022299-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FQAP1rE2NAOVH04TQmlau%2Fuploads%2FrKi9rBUZLtWeTtnItIij%2Fimage.png?alt=media\&token=abcab445-4937-4982-b0d5-680991eab51e)

{% hint style="info" %}
In order to reduce the resource load on our data storage, a maximum of 100 different datasets can be fetched in one request. A dataset is a unique combination of 1 group, 1 device and 1 datatype. For example, if you have 2 groups with 2 devices each reporting 2 datatypes, that’s 8 distinct datasets. This limitation can be avoided by applying further filtering, explained in the next paragraph.
{% endhint %}

### Filtering

This limitation is avoided by querying smaller chunks of time, or fewer datasets.&#x20;

&#x20;With filters you determine what data you want to retrieve.  As explained in the [previous section](https://docs.bace-iot.com/api/navigating-data) the most common onces are *id\_group* or *source\_device.* The table below provides  comprehensive overview of parameters that can be applied:

| Field                       | Description                                                             |
| --------------------------- | ----------------------------------------------------------------------- |
| id\_container\_data\_latest | UUID which describes combination of Group, Physical Device and Datatype |
| id\_group                   | UUID of Group                                                           |
| datatype                    | Datatype of stored data                                                 |
| source\_device              | UUID of Physical Device, BACE Cloud have received data from             |
| timestamp\_seconds          | Timestamp in seconds                                                    |
| min\_val                    | Minimal value                                                           |
| max\_val                    | Maximal value                                                           |
| avg\_val                    | Average value                                                           |
| count\_val                  | Count of downsampled samples                                            |

You can also request data between two timestamps to get more data, with a higher resolution.

For example you would be interested in getting temperature data.

To get more detailed information about datatype meaning, you should make GET request, to the Group endpoint with the same ID group, you have used to get data, and expand response on `dataTypes`

```
GET https://dashboard.bace-iot.com/api/v2/group/b7624b4d-...?expand=dataTypes
```

<details>

<summary>Response:</summary>

```json
{
  "id": "b7624b4d-...",
  "id_group": "b7624b4d-...",
  "label": "BacePlus-...",
  "type": "5003",
  "type_label": "Loose Device",
  "subtype": "...",
  "id_country": null,
  "created_at": 1647963043,
  "dataTypes": [
      {
          "datatype": 2070,
          "label": "Datatype 2070",
          "unit": "",
          "precision": 1
      },
      {
          "datatype": 2071,
          "label": "Datatype 2071",
          "unit": "",
          "precision": 1
      },
      {
          "datatype": 2072,
          "label": "Datatype 2072",
          "unit": "",
          "precision": 1
      },
      {
          "datatype": 2073,
          "label": "Datatype 2073",
          "unit": "",
          "precision": 1
      },
      {
          "datatype": 2100,
          "label": "Modbus Parameter 2100",
          "unit": "",
          "precision": 1
      },
      {
          "datatype": 2101,
          "label": "Modbus Parameter 2101",
          "unit": "",
          "precision": 1
      },
      {
          "datatype": 2102,
          "label": "Modbus Parameter 2102",
          "unit": "",
          "precision": 1
      },
      {
          "datatype": 5000,
          "label": "Temperature",
          "unit": "°C",
          "precision": 1
      },
      {
          "datatype": 5001,
          "label": "Relative Humidity",
          "unit": "%",
          "precision": 1
      },
      {
          "datatype": 5003,
          "label": "Presence",
          "unit": "",
          "precision": 0
      }
  ],
  "_links": {
      "self": {
          "href": "/api/v2/group/b7624b4d-..."
      },
      "index": {
          "href": "/api/v2/group/index"
      },
      "data": {
          "href": "/api/v2/data?filter[id_group]=b7624b4d-..."
      },
      "downsampled_data": {
          "href": "/api/v2/data-downsampled?filter[id_group]=b7624b4d-..."
      },
      "raw_data": {
          "href": "/api/v2/data/index?filter[id_group]=b7624b4d-..."
      }
  }
}
```

</details>

In the response you will get basic information about this group, and also information about all datatypes related to this group.

For example we want to get Temperature in °C from Group response, we can see that it is **datatype 5000**.

```json
{
    "datatype": 5000,
    "label": "Temperature",
    "unit": "°C",
    "precision": 1
}
```

Now when we know, that Temperature has datatype 5000, we can go back to Downsampled data endpoint and find id\_container\_data\_latest, matching our Temperature datatype

```json
{
    "id_container_data_latest": "8faac4b0-...,
    "id_group": "b7624b4d-...",
    "datatype": 5000,
    "source_device": "007ed6e0-...",
    "timestamp_seconds": 1647993600,
    "min_val": 27.7362060547,
    "max_val": 30.3244018555,
    "avg_val": 29.0922662866034,
    "count_val": 262
}
```

Now we can request just Temperature in °C data. We will make our request more specific. In our response from data\_downsampled endpoint we can see "timestamp\_seconds": 1647993600 - Wed Mar 23 2022 01:00:00 GMT+0100 (Central European Standard Time). Then we will try to request data for 24 hours from this timestamp.

Wed Mar 23 2022 01:00:00 GMT+0100 (Central European Standard Time) - Thu Mar 24 2022 01:00:00 GMT+0100 (Central European Standard Time)

We will make GET request to the same endpoint, but we will add two more filters and will sort received data on a timestamp\_seconds - descending.

```http
GET https://dashboard.bace-iot.com/api/v2/data-downsampled?filter[id_container_data_latest]=8faac4b0-…&filter[timestamp_seconds][gt]=1647993600&filter[timestamp_seconds][lt]=1648080000&sort=-timestamp_seconds
```

Response:

```json
{
    "items": [
        {
            "id_container_data_latest": "8faac4b0-...",
            "id_group": "b7624b4d-...",
            "datatype": 5000,
            "source_device": "007ed6e0-...",
            "timestamp_seconds": 1648051140,
            "min_val": 29.9517822266,
            "max_val": 30.022277832,
            "avg_val": 29.9870300293,
            "count_val": 2
        },
        {
            "id_container_data_latest": "8faac4b0-...",
            "id_group": "b7624b4d-...",
            "datatype": 5000,
            "source_device": "007ed6e0-...",
            "timestamp_seconds": 1648051080,
            "min_val": 29.9819946289,
            "max_val": 30.022277832,
            "avg_val": 30.00213623045,
            "count_val": 2
        },
        {
            "id_container_data_latest": "8faac4b0-...",
            "id_group": "b7624b4d-...",
            "datatype": 5000,
            "source_device": "007ed6e0-...",
            "timestamp_seconds": 1648051020,
            "min_val": 29.9517822266,
            "max_val": 30.022277832,
            "avg_val": 29.9870300293,
            "count_val": 2
        },
        ...
    ],
    "_links": {
        "self": {
            "href": "https://dashboard.bace-iot.com/api/v2/data-downsampled?filter%5Bid_container_data_latest%5D=8faac4b0-...&filter%5Btimestamp_seconds%5D%5Bgt%5D=1647993600&filter%5Btimestamp_seconds%5D%5Blt%5D=1648080000&sort=-timestamp_seconds&page=1"
        },
        "first": {
            "href": "https://dashboard.bace-iot.com/api/v2/data-downsampled?filter%5Bid_container_data_latest%5D=8faac4b0-...&filter%5Btimestamp_seconds%5D%5Bgt%5D=1647993600&filter%5Btimestamp_seconds%5D%5Blt%5D=1648080000&sort=-timestamp_seconds&page=1"
        },
        "last": {
            "href": "https://dashboard.bace-iot.com/api/v2/data-downsampled?filter%5Bid_container_data_latest%5D=8faac4b0-...&filter%5Btimestamp_seconds%5D%5Bgt%5D=1647993600&filter%5Btimestamp_seconds%5D%5Blt%5D=1648080000&sort=-timestamp_seconds&page=1"
        }
    },
    "_meta": {
        "totalCount": 201,
        "pageCount": 1,
js        "currentPage": 1,
        "perPage": 500
    }
}
```

Now we can find more data in the response, with 1 value per minute. But we can still see that there is some data in between, because  **"count\_val": 2**.

So to get raw data we can make last request.

```
GET https://dashboard.bace-iot.com/api/v2/data-downsampled?filter[id_container_data_latest]=8faac4b0-a971-47c6-bd16-c80b2ef99299&filter[timestamp_seconds][gt]=1648051080&filter[timestamp_seconds][lt]=1648051140&sort=-timestamp_seconds
```

In this case we are requesting data between **1648051080** - Wed Mar 23 2022 16:58:00 GMT+0100 (Central European Standard Time) and **1648051140** - Wed Mar 23 2022 16:59:00 GMT+0100 (Central European Standard Time)

Response:

```json
{
  "items": [
      {
          "id_container_data_latest": "8faac4b0-...",
          "id_group": "b7624b4d-...",
          "datatype": 5000,
          "source_device": "007ed6e0-...",
          "timestamp_seconds": 1648051122,
          "min_val": "30.022277832",
          "max_val": "30.022277832",
          "avg_val": "30.022277832",
          "count_val": 1
      },
      {
          "id_container_data_latest": "8faac4b0-...",
          "id_group": "b7624b4d-...",
          "datatype": 5000,
          "source_device": "007ed6e0-...",
          "timestamp_seconds": 1648051090,
          "min_val": "29.9819946289",
          "max_val": "29.9819946289",
          "avg_val": "29.9819946289",
          "count_val": 1
      }
  ],
  "_links": {
      "self": {
          "href": "https://dashboard.bace-iot.com/api/v2/data-downsampled?filter%5Bid_container_data_latest%5D=8faac4b0-...&filter%5Btimestamp_seconds%5D%5Bgt%5D=1648051080&filter%5Btimestamp_seconds%5D%5Blt%5D=1648051140&sort=-timestamp_seconds&page=1"
      },
      "first": {
          "href": "https://dashboard.bace-iot.com/api/v2/data-downsampled?filter%5Bid_container_data_latest%5D=8faac4b0-...&filter%5Btimestamp_seconds%5D%5Bgt%5D=1648051080&filter%5Btimestamp_seconds%5D%5Blt%5D=1648051140&sort=-timestamp_seconds&page=1"
      },
      "last": {
          "href": "https://dashboard.bace-iot.com/api/v2/data-downsampled?filter%5Bid_container_data_latest%5D=8faac4b0-...&filter%5Btimestamp_seconds%5D%5Bgt%5D=1648051080&filter%5Btimestamp_seconds%5D%5Blt%5D=1648051140&sort=-timestamp_seconds&page=1"
      }
  },
  "_meta": {
      "totalCount": 2,
      "pageCount": 1,
      "currentPage": 1,
      "perPage": 500
  }
}
```

In the response we will find raw data points.&#x20;

How to know, that it is raw data:

* We can find, that "count\_val": 1 It means there is no more data in between two timestamps
* We can also convert timestamp, for example: 1648051122, to datetime: Wed Mar 23 2022 16:58:42 GMT+0100 (Central European Standard Time). And we will see, that time is not rounded 16:58:42
* Minimal, maximal & average values are equal

## Conclusion

So to get data from aggregated data endpoint we should follow reverse logic.&#x20;

We start from getting 1 value per day. This is what downsampled\_data endpoint returns without timestamp\_seconds filters or if time interval is greater than 3 weeks.&#x20;

If you want to get more accurate data, we are able to request hourly aggregated data, by having our request interval less then 3 weeks and greater than 1 day. It should return 1 value per hour.&#x20;

Then we can make request and keep interval less than 1 day and greater than 1 hour to get data aggregated to 1 value per minute.&#x20;

To get raw data, we should make request, where requested interval would be less than 1 hour - it should return raw data

### Accessing raw data

The below example shows how the `data` endpoint can be called with a filter on *id\_group* to access that groups data:

## Access group data

<mark style="color:blue;">`GET`</mark> `https://dashboard.bace-iot.com/api/v2/data?filter[id_group]=0fcf513b-...`

Response will be a paginated list of datapoints that are available in the group.

{% tabs %}
{% tab title="200: OK " %}

```javascript
{
    "items": [
        {
            "id_container_data_latest": "17833fcc-...",
            "id_group": "0fcf513b-...",
            "datatype": 2105,
            "source_device": "40f0462c-...",
            "timestamp_seconds": 1628774057,
            "microseconds": 965000,
            "value": 50
        },
        {
            "id_container_data_latest": "17833fcc-...",
            "id_group": "0fcf513b-...",
            "datatype": 2106,
            "source_device": "40f0462c-...",
            "timestamp_seconds": 1628774064,
            "microseconds": 275000,
            "value": 100
        },
        {
            "id_container_data_latest": "17833fcc-...",
            "id_group": "0fcf513b-...",
            "datatype": 2107,
            "source_device": "40f0462c-...",
            "timestamp_seconds": 1628774070,
            "microseconds": 575000,
            "value": 0
        }
    ],
    "_links": {
        "self": {
            "href": "https://evalan-dev-bace-webapp.azurewebsites.net/api/v2/data/index?filter%5Bid_group%5D=0fcf513b-..."
        },
        "first": {
            "href": "https://evalan-dev-bace-webapp.azurewebsites.net/api/v2/data/index?filter%5Bid_group%5D=0fcf513b-..."
        },
        "last": {
            "href": "https://evalan-dev-bace-webapp.azurewebsites.net/api/v2/data/index?filter%5Bid_group%5D=0fcf513b-..."
        },
        "next": {
            "href": "https://evalan-dev-bace-webapp.azurewebsites.net/api/v2/data/index?filter%5Bid_group%5D=30fcf513b-...&page=2"
        }
    },
    "_meta": {
        "totalCount": 3,
        "pageCount": 3,
        "currentPage": 1,
        "perPage": 500
    }
}
```

{% endtab %}

{% tab title="401: Unauthorized Request was made with invalid credentials" %}

```javascript
{
    "name": "Unauthorized",
    "message": "Your request was made with invalid credentials.",
    "code": 0,
    "status": 401,
    "type": "yii\\web\\UnauthorizedHttpException"
}
```

{% endtab %}
{% endtabs %}

From the response we see that this group has three data points from three different datatypes available. If more than 500 datapoints are available in the group the response will be paginated with latest data on top. Please refer to the Advanced Features section to learn about browsing through pages.

Note that both the `data` endpoint requires you to set a filter. Forgetting the filter will result in an error.
