API
===

The server part exposes a public API (by default). Read from the API is always
public but writing new reports can be restricted through the use of an
API token (see the doc about deployment for more infos).

A helper script is available under `scripts/api_doc.py` to export a
documentation of the available API endpoints and usage in the current version
of the code.


### Pagination

All the API endpoints support pagination. By default, no pagination is done.
You can force pagination specifying a `page[size]` GET parameter to specify a
number of items per page and a `page[number]` GET parameter to specify the
page to return. Pages are numbered starting from zero.

For instance,

```
> GET /api/v1/reports?page[size]=10&page[number]=0
```

will return the ten first reports of the first page, which are the ten first
reports from the database.


### Filtering

#### Basic filtering

Filtering is possible in the API through the use of a `filter` GET parameter.

You can filter on a given field value using the parameter value
`filter[FIELD]=VALUE`. For instance,

```
> GET /api/v1/reports?filter[id]=1
```

will return the reports with `id` 1.

_Note:_ for fields representing a date(time), the filtering value should be
encoded according to ISO 8601.


#### Combining filters

All provided filters must be filled for an item to be returned. That is, if
you want to return all the reports of type `interrupt` with no `upvotes`, you
can use

```
> GET /api/v1/reports?filter[type]=interrupt&filter[upvotes]=0
```

If you want to make an `OR` condition, satisfying either one of the filters,
you should make two different API calls.


#### Complex filtering

You can also use more complex elaborations through the syntax
`filter[FIELD][OPERATOR]=VALUE`. The available operators are `eq` (equal,
default operator), `ne` (not equal), `gt` (greater than), `ge` (greater or
equal), `lt` (lower than) and `le` (lower or equal). For instance,

```
> GET /api/v1/reports?filter[id][ne]=1
```

will return all the reports except the one with `id` 1.

With the filters combination capability, you can use this to get all the
reports in a geographical bounding box:

```
> GET /api/v1/reports?filter[lat][gt]=LAT_MIN&filter[lat][lt]=LAT_MAX&filter[lng][gt]=LNG_MIN&filter[lng][lt]=LNG_MAX
```

All operators can have a trailing `?` to make them consider fields without
value as matching the condition as well. This means you can use something like

```
> GET /api/v1/reports?filter[expiration_datetime][gt?]=2018-10-18T09:06:38.538375
```

to get the all the reports with an expiration datetime in the future or no
expiration datetime, that is all currently active reports, assuming the
current datetime is `2018-10-18T09:06:38.538375`.


### Output format

The default output format is a JSON dump of the reports, in a format specific
to Cygnal.

It is possible to get a more standard GeoJSON output using the `format` query
parameter, typically:

```
> GET /api/v1/reports?format=geojson
```
