# Advanced Features

The API provides a standard set of features that are available on most endpoints.

## Pagination

The API provides pagination functionality via the parameters page, per-page. Endpoints that support pagination will have the `?page` and `?per-page` GET parameters in the documented options.

#### Example:

* To get 20 records per page, User would make request with query parameter: `?per-page=20`. In the response User should get records 1 - 20.
* To get second page, User would make request with query parameter: `?page=2`. In the response User should get second page with records. Default per-page value will be applied to the request. Different endpoints have different default per-page values.&#x20;
* You can also combine this query parameters, for example to get per page 20, and second page. User would make request with following query parameters: `?per-page=20&page=2`. In the response User should get records from 21 - 40.

### Example `_meta` object

```json
"_meta": {
    "totalCount": 246,
    "pageCount": 13,
    "currentPage": 1,
    "perPage": 20
}
```

| **Field**   | **Description**                                                                                                                                                                     |
| ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| totalCount  | Total count of records in collection - User have access to                                                                                                                          |
| pageCount   | Total page count of records in collection - User have access to, with respect to perPage value. If not set as query parameter. Default one will be applied and returned in response |
| currentPage | Currently requested page                                                                                                                                                            |
| perPage     | Count of records returned on one page                                                                                                                                               |

The same information is available in the response headers.

### Example pagination headers

```
x-pagination-current-page: 1 
x-pagination-page-count: 13 
x-pagination-per-page: 20 
x-pagination-total-count: 246
```

| Field                     | Description                                                                                                                                                                         |
| ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| x-pagination-total-count  | Total count of records in collection - User have access to                                                                                                                          |
| x-pagination-page-count   | Total page count of records in collection - User have access to, with respect to perPage value. If not set as query parameter. Default one will be applied and returned in response |
| x-pagination-current-page | Currently requested page                                                                                                                                                            |
| x-pagination-per-page     | Count of records returned on one page                                                                                                                                               |

### HEAD request

Sometimes User is not interested in getting records itself, but wants to get the number of records. It is possible by making a HEAD request to the same collection API endpoint.

For example we would like to get all groups in the system User have access to.

`HEAD https://dashboard.bace-iot.com/api/v2/group`

It will not return anything in the body of response. But in the Headers you will be able to find pagination Headers

## Expand

It is often useful to expand the response with extra optional attributes or nested relations. If you want to know what are optional expand options for your request, you can find expand option array, if you make GET request to collection endpoint.

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

```json
{
    "items": [
        ...
    ],
    "expand": [
        "latestEvent",
        "group",
        "parent",
        "deviceType",
        "location",
        "iotDevice",
        "deviceInfo",
        "modbusTemplateHistory",
        "currentModbusTemplate",
        "simCard"
    ]
}
```

{% hint style="info" %}
Expand options array is available only in collection endpoint, but can be used in the same way on collection and singleton endpoints
{% endhint %}

By passing one or more (comma seperated) to the "expand" parameter, you can drill down into further relations, as in example of parentGroup.physicalDevices.

For example from Physical Device endpoints , you may request a comma-separated list by using `?expand=group,parent,parent.group`, which will return a response that contains Physical Device information, it’s Group information, also parent Physical Device and it’s Group information.

<mark style="color:blue;">`GET`</mark>` ``https://dashboard.bace-iot.com/api/v2/physical-device/0235e44c-…?expand=group,parent,parent.group`

Example response:

```json
{
    "id_physical_device": "0235e44c-...",
    "serial_hardware": "d88...",
    "label": "Device Label",
    "id_parent": "39ee0b23-...",
    "id_group": "4bb7b680-...",
    "id_device_type": "refrigerator",
    "id_iot_device": null,
    "is_connected": 0,
    "expected_offline_interval": null,
    "expected_live_status": null,
    "device_status": null,
    "connection": null,
    "created_at": 1617022239,
    "last_data_at": 1617962070,
    "signal": 0,
    "commissioned_at": null,
    "calibrated_at": 0,
    "reconnected_at": null,
    "bace_software_version": null,
    "app_software_version": null,
    "archived_serial": null,
    "archived_at": null,
    "archived_by": null,
    "group": {
        "id": "4bb7b680-...",
        "id_group": "4bb7b680-...",
        "label": "Refrigerator Leiden 1",
        "type": "5003",
        "type_label": "Loose Device",
        "subtype": "Refrigerator",
        "id_country": "b8415b65-...",
        "created_at": 1617351877,
        "_links": {
            "self": {
                "href": "/api/v2/group/4bb7b680-..."
            },
            "index": {
                "href": "/api/v2/group/index"
            },
            "data": {
                "href": "/api/v2/data?filter[id_group]=4bb7b680-..."
            },
            "downsampled_data": {
                "href": "/api/v2/data-downsampled?filter[id_group]=4bb7b680-..."
            },
            "raw_data": {
                "href": "/api/v2/data/index?filter[id_group]=4bb7b680-..."
            }
        }
    },
    "parent": {
        "id_physical_device": "39ee0b23-...",
        "serial_hardware": "b8f009804ef4",
        "label": "BACE-18",
        "id_parent": null,
        "id_group": "0e5144e0-...",
        "id_device_type": "refrigerator",
        "id_iot_device": "9d80b382-dce5-4fd5-a9ed-ec9fb24d37e2",
        "is_connected": 0,
        "expected_offline_interval": null,
        "expected_live_status": null,
        "device_status": null,
        "connection": "cellular",
        "created_at": 1617021509,
        "last_data_at": 1619128818,
        "signal": 0,
        "commissioned_at": null,
        "calibrated_at": null,
        "reconnected_at": null,
        "bace_software_version": null,
        "app_software_version": null,
        "archived_serial": null,
        "archived_at": null,
        "archived_by": null,
        "group": {
            "id": "0e5144e0-...",
            "id_group": "0e5144e0-...",
            "label": "Test-Building-1",
            "type": "50000",
            "type_label": "Building",
            "subtype": "bace-ep",
            "id_country": "b8415b65-...",
            "created_at": 1617021758,
            "_links": {
                "self": {
                    "href": "/api/v2/group/0e5144e0-..."
                },
                "index": {
                    "href": "/api/v2/group/index"
                },
                "data": {
                    "href": "/api/v2/data?filter[id_group]=0e5144e0-..."
                },
                "downsampled_data": {
                    "href": "/api/v2/data-downsampled?filter[id_group]=0e5144e0-..."
                },
                "raw_data": {
                    "href": "/api/v2/data/index?filter[id_group]=0e5144e0-..."
                }
            }
        },
        "_links": {
            "self": {
                "href": "https://dashboard.bace-iot.com/api/v2/physical-device/view?id=39ee0b23-..."
            },
            "index": {
                "href": "https://dashboard.bace-iot.com/api/v2/physical-device/index"
            }
        }
    },
    "_links": {
        "self": {
            "href": "https://dashboard.bace-iot.com/api/v2/physical-device/view?id=0235e44c-..."
        },
        "index": {
            "href": "https://dashboard.bace-iot.com/api/v2/physical-device/index"
        }
    }
}
```

In the device object, User will find `group` object, it is Group record related to Physical Device. Also User will find `parent` object, it is parent Physical Device, and inside User will found another `group` object - it is Group of parent Physical Device.

## Fields

We recommend that you always filter only on the fields that you need for your request. This speeds up the response time and reduces the amount of data being transferred between servers. A comma-separated list of fields can be provided to achieve this. For example we will extend previous request and will request only labels, `?expand=group,parent,parent.group&fields=label,group.label,parent.label,parent.group.label` will return a response that contains only the label for every record.

`GET https://dashboard.bace-iot.com/api/v2/physical-device/0235e44c-…?expand=group,parent,parent.group&fields=label,group.label,parent.label,parent.group.label`

Response:

```json
{
  "label": "Device Label",
  "group": {
      "label": "Refrigerator Leiden 1",
      "_links": []
  },
  "parent": {
      "label": "BACE-18",
      "group": {
          "label": "Test-Building-1",
          "_links": []
      },
      "_links": {
          "self": {
              "href": "dashboard.bace-iot.com/api/v2/physical-device/view?id=39ee0b23-..."
          },
          "index": {
              "href": "dashboard.bace-iot.com/api/v2/physical-device/index"
          }
      }
  },
  "_links": {
      "self": {
          "href": "https://dashboard.bace-iot.com/api/v2/physical-device/view?id=0235e44c-..."
      },
      "index": {
          "href": "https://dashboard.bace-iot.com/api/v2/physical-device/index"
      }
  }
}
```

You can find that 120 lines in response reduced to 30 lines. It allows queries to run faster, especially if you increasing default per-page for requests on collection endpoints. But we in general recommend to limit fields for every request and get just required fields.

## Sort

Some attributes can be sorted using the ?sort query parameter. For example, making a GET request on an index with ?sort=label will do an ascending sort on the label attribute. Sorting on strings will do a natural sort, whereas sorting on a numeric value will do a numeric sort instead. Its also possible to invert a sort by prefixing the attribute name with a minus sign. ?sort=-timestamp results in sorting timestamps from newest to oldest.

## Filter

Filtering on most attributes is available via the filter query parameter. For example, to filter on the label attribute, you can use `?filter[label]=MyLabel` to filter on an exact match, or `?filter[label][like]=Label` to do a like-match. Available operators (depending on datatype) are

| Operator                    | Example                                                                        | Explanation                                                           |
| --------------------------- | ------------------------------------------------------------------------------ | --------------------------------------------------------------------- |
| =                           | filter\[label]=MyLabel                                                         | for an explicit exact match                                           |
| for an explicit exact match | filter\[label]\[eq]=A1                                                         | for an explicit exact match                                           |
| neq                         | filter\[label]\[neq]=A1                                                        | for not equal to                                                      |
| like                        | filter\[label]\[like]=Label                                                    | for a partial match that ignores capitalization                       |
| lt                          | filter\[timestamp\_seconds]\[lt]=1648038180                                    | to filter only on attributes lower than the provided value            |
| lte                         | filter\[timestamp\_seconds]\[lte]=1648038180                                   | to filter only on attributes lower-or-equal than the provided value   |
| gt                          | filter\[timestamp\_seconds]\[gt]=1648038180                                    | to filter only on attributes greater than the provided value          |
| gte                         | filter\[timestamp\_seconds]\[gte]=1648038180                                   | to filter only on attributes greater-or-equal than the provided value |
| in                          | filter\[label]\[in]\[0]=A1\&filter\[label]\[in]\[1]=A2                         | to filter on array of values. \[field] + \[in] + \[index number]      |
| or                          | filter\[or]\[0]\[label]\[like]=b2\&filter\[or]\[1]\[label]\[like]=b1           | or operator (\|\|). \[or] + \[index number] + \[field] + \[like]      |
| and                         | filter\[and]\[0]\[label]\[like]=bace\&filter\[and]\[1]\[label]\[like]=acc/gyro | and operator (&&). \[and] + \[index number] + \[field] + \[like]      |

In some cases it is possible to filter on relationships from the Expand option. Support for this is being expanded currently where it is useful.

### Filter with JSON body

It is also possible to build your more complicated queries and send it not as a query parameters, but with a json body.&#x20;

To make use of this you are required to make your request with the header: `Content-Type: application/json`

**Request body**

```json
{
    "filter": {
        "or": [
            {
                "label": {
                    "like": "site"
                }
            },
            {
                "type": 5003
            }
        ]
    }
}
```

This request would be equal to `?filter[or][0][label][like]=site&filter[or][1][type]=5003`, if you prefer to use your filters as a query parameters. All the operators for JSON body filters are the same as operators for filter in query parameters.

!Important: The API will only accept a URL-parameter GET or a Body, it will not merge them if both are provided; the URL parameters will take precedence.

## Links

Many pages and objects will have a "\_links" attribute which represents a list of useful resources related to this response or object.

For example, our pagination will add pre-built links for the current, next, previous and last page of the result, allowing you to quickly use these in building buttons in your frontend that follow our URL scheme.\
Many objects will also contain a \_links attribute that will point you to endpoints for relevant relational objects, datasets to query or the location of the index endpoint for that particular type of object.

## Labels

In some of API calls, you will find labels, which can be used to better understand meaning of fields in the response object. For example endpoint to remove z-wave node:

<mark style="color:blue;">`DELETE`</mark>` ``https://dashboard.bace-iot.com/api/v2/physical-device/04771e4c-…/zwave-node`

**Example response**

```json
{
  "message": "We are processing your request. You can use API event endpoint to get information about your request status.",
  "routeToPollEvents": "https://dashboard.bace-iot.com/api/v2/event?filter[source_device]=04771e4c-...&filter[event_type]=612&sort=-created_at",
  "tips": [
    {
      "id": 0,
      "label": "Success"
    },
    {
      "id": 7,
      "label": "Exclusion failed"
    },
    {
      "id": 255,
      "label": "Failed"
    }
  ],
  "fromCloud": {
    "status": 200,
    "payload": {
      "result": "success"
    }
  }
}
```

<table><thead><tr><th width="203.6423406098108">Fields</th><th>Description</th></tr></thead><tbody><tr><td>fromCloud</td><td>Is response User got from IoT Hub</td></tr><tr><td>message</td><td>Message generated by BACE Cloud</td></tr><tr><td>routeToPollEvents</td><td>This is endpoint, User can use to listen to get result of asynchronous action</td></tr><tr><td>tips</td><td>Array of possible event values, you can receive from routeToPollEvents. So if you get event with value 0 - it would mean a success in z-wave node exclusion.</td></tr></tbody></table>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.bace-iot.com/api/advanced-features.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
