# Introduction

# Enectiva REST API - Librarian

Librarian is a simple public API of [Enectiva](http://www.enectiva.cz/en/about-enectiva/) for ingesting readings. It can be used only in conjunction with a valid account in Enectiva application.

---

## JSON API

This API sticks to REST principles as interpreted by [JSON API](http://jsonapi.org/). Due to gradual development, not all endpoints are fully compliant with JSON API, please, refer to documentation of each endpoint for details.

### Required Request Structure

To comply with the [JSON API](http://jsonapi.org/) specification, POST and PATCH requests require the following structure for [resource objects](https://jsonapi.org/format/#document-resource-objects):

#### **POST:**

>The POST request MUST include a single resource object as primary data. The resource object MUST contain at least a `type` member.

Example:

```
{
  "data": {
    "type": "readings",  // Must match the type required by an endpoint
    "attributes": { ... }
  }
}
```

#### **PATCH:**

>The PATCH request MUST include a single resource object as primary data. The resource object MUST contain `type` and `id` members.


Example:

```
{
  "data": {
    "type": "readings",  // Must match the type required by an endpoint
    "id": "456",  // Required and must match URL ID
    "attributes": { ... }
  }
}

// URL: /api/resource/456
```

---

## Auth

Each request (excluding a request [for access token creation](https://apidocs.enectiva.cz/create-a-new-access-token-19188091e0.md)) has to include `Authorization` header in the form `Bearer [token]`.
Each token has a limited scope and thus can access only certain resources.


For all actions, you should use a `Login token` to obtain a short lived [Access token](https://apidocs.enectiva.cz/create-a-new-access-token-19188091e0.md). Permissions for an access token are inherited from the login token used to create it. Import and login tokens are managed on the [API dashboard](https://app.enectiva.cz/en/api/dashboard).


>DEPRECATED: For backward compatibility, you can still use an import token for "import" endpoints (endpoints under `/import`). However, this is deprecated and a less secure alternative. These tokens do not expire and cannot be revoked by users. In the event of a leak, you would need to contact our development team

---

## Errors

Each endpoint lists possible error states, but most of them are shared:

- *400*: validation error, described in the `detail` attribute
- *401*: invalid token &mdash; token is missing altogether, it is not syntactically correct, it is malformed, claims are malformed or the scope is invalid, etc. The reason is described in the `detail` attribute
- *403*: the token scope is not permitted to perform the requested operation
- *404*: server cannot find the requested resource
- *406*: the request doesn't include `Accept: application/vnd.api+json` header
- *409*: duplicity &mdash; identical record is already stored
- *415*: the declared `Content-Type` is not `application/vnd.api+json`
- *429*: you have exceeded the rate limit
- *500*: any other error

## Filters

The `filter` query parameter can be used in some endpoints to traverse all the available data.

The request can limit which records should be returned by adding the `filter` query parameter. Its value has the form `[resource object type].[field][condition][value]`, some examples are:

- `readings.time>2019-10-02T00:00:00Z`
- `data_series.time>2019-10-02T00:00:00Z`
- `meter_deltas.time>2019-10-02T00:00:00`
- `entity_deltas.time>2019-10-02T00:00:00`

Currently

- `[resource object type].time>[value]`
- `[resource object type].time>=[value]`
- `[resource object type].time<[value]`

filters are supported and they can be concatenated using `?filter[]=....&filter[]=...`. An example is

```
?filter[]=readings.time>2019-10-02T00:00:00Z&filter[]=readings.time<2019-10-06T00:00:00Z
```

The API returns most times in UTC (marked explicitly by `Z`). The API accepts times without offset specification and treats them as being in UTC. Any other explicitly defined offset is honoured. This means that

- `readings.time>2019-10-02T12:00:00`
- `readings.time>2019-10-02T12:00:00Z`
- `readings.time>2019-10-02T13:00:00+01:00`

are all equivalent.

There are a [few endpoints](https://apidocs.enectiva.cz/list-monthly-deltas-of-an-entity-19188093e0.md) which return and accepts times without offset specification.

> NOTE: The filters need to be URL encoded but for readability the documentation is using an un-encoded version.

---

## Sort options
The `sort` query parameter can be used in some endpoints to reorder all the available data.
The `sort` query parameter implementation follows the [JSON API specification](https://jsonapi.org/format/#fetching-sorting).

The request can specify how the records should be ordered by adding `sort` query parameter. Its value has the form `[direction][resource].[field]`, some examples are:

- `-readings.time`
- `data_points.time`
- `-meter_deltas.time`
- `entity_deltas.time`

> TIP: Use `?sort=-[resource].time&limit=1` to retrieve only the latest record.

### Direction

Use `-` to specify sort direction to be descending, otherwise use `[resource].[field]` to specify ascending direction.

Temporal records are ordered by `time` in ascending order by default.

### Chaining

Sort options can be chained by using a comma:
- `?sort=-data_points.value,data_points.time`

Sort options are applied in the given order, thus firstly ordered by `value DESC` and then by `time ASC`.

---

## Meter identification

Meter endpoints use two forms of meter identification:

1. Enectiva's numeric meter ID
2. User entered _external ID_

External IDs must be prepended by `e_` to be distinguishable from Enectiva IDs. If meter with Enectiva ID `42` has external ID `the-ultimate-answer`, these two endpoints will provide identical data:

- `https://api.enectiva.cz/meters/42/readings`
- `https://api.enectiva.cz/meters/e_the-ultimate-answer/readings`

A request with non-unique external ID results in 409 response status. The response includes error details with links to all matching meters using their Enectiva IDs, allowing the client to choose the appropriate meter and retry the request using the Enectiva ID instead of the external ID.

---

## Limit & pagination

You can control the number of returned records of most endpoints returning a collection. The default limit is 1000 you can go lower. If you want to get fewer than 1000 records you need to pass `limit` query argument.


To paginate, set `page` query argument. Implicit value is 1.

---

## Rate limiting

API requests are tracked and can be throttled in order to ensure operational stability. The intention is to protect the API from unterminated loops or attempts to aggressively download all data at once. If you're hitting the limits with legitimate use, please [contact us](#contact).

A throttled request results in 429 response status. The response also contains `RateLimit-*` headers describing the current state and of the throttle and most importantly the time when a new request is going to be accepted.

## Contact

If you have any questions related to this API, client implementation or its use, please contact us at [api@enectiva.cz](mailto:api@enectiva.cz).

