Introduction

The REST API for the data historian is currently exposing the following enpoints:

The 'tag-keys' and 'tag-values' endpoints are only useful for Grafana.

Detailed descriptions of the API endpoints

Data injection

The following endpoints are used to inject data measures in the historian :

POST /api/historian/v0/import/csv

This request allows to inject data measures from CSV files. The format of the http request must be Content-Type: multipart/form-data;

Table 1. Request parameters
attribute multivalued description mandatory possible values default value

my_csv_file

Yes

the path of the csv files to import. Please note that each file is imported individually independently. In other words, listing several files or making a request per file is equivalent. The settings of the request are common to all the files listed in the request. The files must contain a header.

Yes

mapping.name

No

the name of the column that corresponds to "name". It is the main identifier of a metric.

No

must be a column name from the header of the attached csv files.

"metric"

mapping.value

No

the name of the column that corresponds to "value". It is the measure value. The values in this column must be numeric values.

No

must be a column name from the header of the attached csv files.

"value"

mapping.timestamp

No

The name of the header column which corresponds to "timestamp". It is the date of the measure. By default this column must contain an epoch timestamp in milliseconds (see format_date)

No

must be a column name from the header of the attached csv files.

"timestamp"

mapping.quality

No

The name of the header column which corresponds to "quality". It is the quality of the measure (quality is currently not stored in the historian - next release will provide quality)

No

must be a column name from the header of the attached csv files.

"quality"

mapping.tags

Yes

The names of the header columns to be considered as a tag. Tags are concepts that describe the metric in addition to its name ("name" column). All columns not entered in the mapping will be ignored during the injection.

No

must be a column name from the header of the attached csv files.

format_date

No

The expected format for the values in the "timestamp" column.

No

Must be a value in: [MILLISECONDS_EPOCH,SECONDS_EPOCH,MICROSECONDS_EPOCH,NANOSECONDS_EPOCH] NANOSECONDS_EPOCH : the value must be the number of nanoseconds since January 1, 1970 UTC. MICROSECONDS_EPOCH : the value must be the number of microseconds since January 1, 1970 UTC. MILLISECONDS_EPOCH : the value must be the number of milliseconds since January 1, 1970 UTC. SECONDS_EPOCH : the value must be the number of seconds since January 1, 1970 UTC. Or another value, in this case this value must be a valid date format, for example "yyyy-mm-dd".

"MILLISECONDS_EPOCH"

timezone_date

No

the timezone for the dates in the csv.

No

must be a valid timezone.

"UTC"

group_by

Yes

This parameter is very important! If it is misused it is possible to corrupt already existing data. List all the fields that will be used to build the chunks here. By default we group the measures in chunk only according to their name. However, it is also possible to group according to the value of some tags. Be aware that this will impact the way the data will be retrieved later. For example if we inject data by grouping by "name" and the tag "factory". Then we can request the values for each factory by filtering on the correct value of the factory tag (see the API to request the measures). Only if thereafter someone injects other data without grouping by the tag "factory" then the data will find themselves mixed.

No

Accepted values are "name" (whatever the mapping, use "name" and not the name of the column in the csv). Otherwise the other accepted values are the column names added as a tag.

"name"

  • If there is a problem with the request we receive a 400 BAD_REQUEST response.

  • If everything went well we receive a 201 CREATED response:

Table 2. Response description
json path type description

tags

array

the tags entered in the request.

grouped_by

array

the fields that are used for the group by (completed in the request).

report

json object

a report on the chunks that were injected.

Example of a minimum curl command:

curl -X POST \
http://localhost:8080/historian-server/ingestion/csv \
-F 'my_csv_file=@path/de/mon/csv/file.csv'

Example of a minial csv file :

metric,timestamp,value
metric_1, 1, 1.2
metric_1, 2, 2
metric_1, 3, 3

Example of a curl command :

curl -X POST \
http://localhost:8080/historian-server/ingestion/csv \
-F 'my_csv_file=@path/de/mon/csv/file.csv' \
-F 'my_csv_file2=@path/de/mon/csv/file2.csv' \
-F mapping.name=metric_name_2 \
-F mapping.value=value_2 \
-F mapping.timestamp=timestamp \
-F mapping.quality=quality \
-F mapping.tags=sensor \
-F mapping.tags=code_install \
-F timestamp_unit=MILLISECONDS_EPOCH \
-F group_by=name \
-F group_by=tags.sensor \
-F format_date=yyyy-D-m HH:mm:ss.SSS \
-F timezone_date=UTC \

Example of a csv file :

metric_name_2,timestamp,value_2,quality,sensor,code_install
metric_1, 1970-1-1 00:00:00.001, 1.2 ,1.4,sensor_1,code_1
metric_1, 1970-1-1 00:00:00.002, 2 ,1.4,sensor_1,code_1
metric_1, 1970-1-1 00:00:00.003, 3 ,1.4,sensor_2,code_1
metric_2, 1970-1-1 00:00:00.004, 4 ,1.5,sensor_2,code_1

with the following request:

curl -X POST \
http://localhost:8080/historian-server/ingestion/csv \
-F 'my_csv_file=@path/de/mon/csv/file.csv' \
-F 'my_csv_file2=@path/de/mon/csv/file.csv' \
-F mapping.name=metric_name_2 \
-F mapping.value=value_2 \
-F mapping.timestamp=timestamp \
-F mapping.quality=quality \
-F mapping.tags=sensor \
-F mapping.tags=code_install \
-F timestamp_unit=MILLISECONDS_EPOCH \
-F group_by=name \
-F group_by=tags.sensor \
-F format_date=yyyy-D-m HH:mm:ss.SSS \
-F timezone_date=UTC \

and the following "file.csv":

metric_name_2,timestamp,value_2,quality,sensor,code_install
metric_1, 1970-1-1 00:00:00.001, 1.2 ,1.4,sensor_1,code_1
metric_1, 1970-1-1 00:00:00.002, 2 ,1.4,sensor_1,code_1
metric_1, 1970-1-1 00:00:00.003, 3 ,1.4,sensor_2,code_1
metric_2, 1970-1-1 00:00:00.004, 4 ,1.5,sensor_2,code_1

we get this respons back:

{
  "tags": ["sensor", "code_install"],
  "grouped_by": ["name", "sensor"],
  "report" : [
    {
      "name": "metric_1",
      "sensor": "sensor_1",
      "number_of_points_injected": 4,
      "number_of_point_failed": 0,
      "number_of_chunk_created": 2
    },
    {
      "name": "metric_1",
      "sensor": "sensor_2",
      "number_of_points_injected": 2,
      "number_of_point_failed": 0,
      "number_of_chunk_created": 2
    },
    {
      "name": "metric_2",
      "sensor": "sensor_2",
      "number_of_points_injected": 2,
      "number_of_point_failed": 0,
      "number_of_chunk_created": 2
    }
  ]
}

(we notice here that we used the same file twice)

POST /api/historian/v0/import/json

Allows you to inject measures into the historian from a request body in json format. The format of the expected request is a request with Content-Type: application / json;

Example of a request:

[
    {
        "name": "temp",
        "measures": [
            [100, 1.0],
            [200, 1.2]
        ]
    },
   {
        "name": "temp_2",
        "measures": [
           [100, 1.7],
           [200, 1.9]
        ]
   }
]

Example of a minimal request:

[
    {
        "name": "temp",
        "measures": [
            [100, 1.0]
        ]
    }
]

The body of the expected request is a list of objects. Each object must be composed of the following attributes:

Table 3. Properties of the JSON objects
json path type description mandatory /name String

The name of the metric for which we are going to inject the measures.

Yes

/measures

Array d’array

Points for creating a chunk with the metric name assigned to 'name'. The measures are to be completed in the form [[timestsamp<long>, value<double>],..,[timestsamp<long>, value<double>]].

Yes

Example of a response

[
  {
    "target":"upper_75",
    "datapoints":[
      [622,1450754160000],
      [365,1450754220000]
    ]
  },
  {
    "target":"upper_90",
    "datapoints":[
      [861,1450754160000],
      [767,1450754220000]
    ]
  }
]

Data Exprt

POST /api/historian/v0/export/csv

Allows you to search for measures and export them to csv for the desired metrics.

This endpoint uses the same request as the endpoint query but it gives the response in csv.

Example of a response :

metric,value,date
temp_a,622.1,1477895624866
temp_a,-3.0,1477916224866
temp_a,365.0,1477917224866
temp_b,861.0,1477895624866
temp_b,767.0,1477917224866

Interactions with Grafana

The APIs below are used to interact with Grafana using certain data sources (a concept of Grafana). Depending on which plugin version you use(SimpleJson or the more recent Historian one), you will have to use the corresponding API.

Compatible API with the "SimpleJson" plugin

GET /api/grafana/simplejson

This endpoint returns a 200 'OK' response if the historian is working properly.

POST /api/grafana/simplejson/query

Used to search for measures for the desired metrics. Various parameters are available.

Example of a request:

{
    "panelId": 1,
    "range": {
        "from": "2016-10-31T06:33:44.866Z",
        "to": "2016-10-31T12:33:44.866Z",
        "raw": {
            "from": "now-6h",
            "to": "now"
        }
    },
    "rangeRaw": {
        "from": "now-6h",
        "to": "now"
    },
    "interval": "30s",
    "intervalMs": 30000,
    "targets": [
        { "target": "upper_50", "refId": "A", "type": "timeserie" },
        { "target": "upper_75", "refId": "B", "type": "timeserie" }
    ],
    "adhocFilters": [{
        "key": "City",
        "operator": "=",
        "value": "Berlin"
    }],
    "format": "json",
    "maxDataPoints": 550
}

Example of a minimal request:

{
    "targets": [
      { "target": "upper_50" }
    ]
}
Table 4. Parameters for the request
json path type description mandatory possible values default value

/targets

array

Allows you to enter the metrics for which you want to obtain measures.

Yes

/targets/target

String

The name of a metric for which we want to obtain measures.

Yes (at least one metric must be listed)

/range/from

String

The start date to search for measures. Only measures with a date greater than or equal to this date.

No

Must represent a date in the following format (UTC) : yyyy-MM-dd’T’HH:mm:ss.SSS

January 1, 1970 (UTC)

/range/to

String

The end date to search for measures. Only measures with a date less than or equal to this date.

No

Must represent a date in the following format (UTC): yyyy-MM-dd’T’HH:mm:ss.SSS

The default is infinity

/maxDataPoints

long

The maximum number of measures desired for each metric (Indeed the goal is to draw measures on a graph). If necessary the measures will be sampled with a default sampling algorithm.

No

positive

1000

/adhocFilters

String

Used by Grafana

No

The remaining parameters are parameters that are sent by Grafana but which are not currently used.

Example of a response

[
  {
    "target":"upper_75",
    "datapoints":[
      [622,1450754160000],
      [365,1450754220000]
    ]
  },
  {
    "target":"upper_90",
    "datapoints":[
      [861,1450754160000],
      [767,1450754220000]
    ]
  }
]

Lets you search for the different metrics available.

Example of a response :

{ "target": "upper_50" }
Table 5. Parameters for the resquest
json path type description mandatory possible values default value

/target

String

Part of the name of the metric you are looking for.

No

The body of the request is optional.

Example of a response :

["upper_25","upper_50","upper_75","upper_90","upper_95"]
POST /api/grafana/simplejson/annotations

Lets you search for annotations.

Example of a request :

{
  "range": {
    "from": "2020-2-14T01:43:14.070Z",
    "to": "2020-2-14T06:50:14.070Z"
  },
  "limit" : 100,
  "tags": ["tag1", "tag2"],
  "matchAny": false,
  "type": "tags"
}

Example of the current response:

[
  {
    "annotation": "annotation",
    "time": "time",
    "title": "title",
    "tags": "tags",
    "text": "text"
  }
]
Table 6. Parameters for the request
json path type description mandatory possible values default value

/range/from

String

The start date to search for annotations. Only annotations with a date greater than or equal to this date.

No

Must represent a date in the following format (UTC): * yyyy-MM-dd’T’HH: mm: ss.SSS *

January 1, 1970 (UTC)

/range/to

String

The end date to search for annotations. Only annotations with a date less than or equal to this date.

No

Must represent a date in the following format (UTC): * yyyy-MM-dd’T’HH: mm: ss.SSS *

The default is infinity

/limit

Integer

The maximum number of annotations to return

No

positive integer

100

/tags

Liste de string

The name of the tags to filter the annotations. The behavior depends on the value of the _ / type_ field

No

[] (empty array)

/matchAny

Boolean

If the type field is worth TAGS. If true the annotations must have at least one of the tags in the tags field otherwise the annotations must contain all the tags.

No

true

/type

String

The type of request. If the value is "ALL", all annotations in the time range will be returned. If the type is "TAGS", the annotations must also contain tags (either all or at least one depending on the value of matchAny).

No

one value from [ALL, TAGS]

ALL

POST /api/grafana/simplejson/tag-keys

Used to find out the keys that can be used in the tag_values endpoint.

Example of a request:

{}

Example of a response:

[
    {"type":"string","text":"City"},
    {"type":"string","text":"Country"}
]

The values in "text" are the values usable as a key in the endpoint tag-values.

Table 7. Parameters for the request
json path type description mandatory possible values default value

/range/from

String

The start date to search for annotations. Only annotations with a date greater than or equal to this date.

No

Must represent a date in the following format (UTC): * yyyy-MM-dd’T’HH: mm: ss.SSS *

January 1, 1970 (UTC)

/range/to

String

The end date to search for annotations. Only annotations with a date less than or equal to this date.

No

Must represent a date in the following format (UTC): * yyyy-MM-dd’T’HH: mm: ss.SSS *

The default is infinity

/limit

Integer

The maximum number of annotations to return

No

positive integer

100

/tags

Liste de string

The name of the tags to filter the annotations. The behavior depends on the value of the _ / type_ field

No

[] (empty array)

/matchAny

Boolean

If the type field is worth TAGS. If true the annotations must have at least one of the tags in the tags field, otherwise the annotations must contain all the tags.

No

true

/type

String

The type of request. If the value is "ALL", all annotations in the time range will be returned. If the type is "TAGS", the annotations must also contain tags (either all or at least one depending on the value of matchAny).

No

one value from [ALL, TAGS]

ALL

POST /api/grafana/simplejson/tag-values

Lets you search for the different metrics available.

Example of a request:

{"key": "City"}

Example of a response:

[
    {"text": "Eins!"},
    {"text": "Zwei"},
    {"text": "Drei!"}
]

Here are the available values for the corresponding keys.

Compatible API with the "Hurence-Historian" plugin

GET /api/grafana/v0

This endpoint returns a 200 'OK' response if the historian is working properly.

POST /api/grafana/v0/query

Used to search for measures for the desired metrics. Various parameters are available.

Example of a request:

{
  "from": "2016-10-31T06:33:44.866Z",
  "to": "2020-10-31T12:33:44.866Z",
  "names": ["metric_1"],
  "format": "json",
  "max_data_points": 30,
  "tags": {
      "sensor" : "sensor_1"
  },
  "sampling":{
     "algorithm": "MIN",
     "bucket_size" : 100
  }
}

Example of a minimal request :

[
    {
        "name": "metric_1",
        "datapoints": [
            [
                622,
                1477895624866
            ],
            [
                -3,
                1477916224866
            ],
            [
                365,
                1477917224866
            ]
        ]
    }
]

{ "tags": { "sensor" : "sensor_1" }, "sampling":{ "algorithm": "MIN", "bucket_size" : 100 } }

Table 8. Parameters for the request
json path type description mandatory possible values default value

/names

array

Allows you to enter the metrics for which you want to obtain measures.

Yes

from

String

The start date to search for measures. Only measures with a date greater than or equal to this date.

No

Must represent a date in the following format (UTC): * yyyy-MM-dd’T’HH: mm: ss.SSS *

January 1, 1970 (UTC)

to

String

The end date to search for measures. Only measures with a date less than or equal to this date.

No

Must represent a date in the following format (UTC): * yyyy-MM-dd’T’HH: mm: ss.SSS *

The default is infinity

/max_data_points

long

The maximum number of measures desired for each metric (Indeed the goal is to draw measures on a graph). If necessary the measures will be sampled with a default sampling algorithm.

No

positive

1000

/sampling

String

An object which will contain the information of the parameters to be used for the sampling of the measures if the number of measures to return is greater than the maximum number of measures requested.

No

/sampling/algorithm

String

L’algorithme à utiliser pour l’échantillonnage

No

les valeurs possibles sont ["NONE", "AVERAGE", "FIRST", "MIN", "MAX"]

AVERAGE (la moyenne des measures pour chaque bucket, le timestamp utilisé est celui du premier measure du bucket)

/sampling/bucket_size

Int

The size of the buckets desired to sample the data. Please note this size can be changed by the server if this is incompatible with the maximum number of measures returned desired.

No

Automatically computed by the server in order to obtain at most the maximum number of measures.

/tags

String

Allows you to obtain only the measures of the chunks which contain the filled tags. The tags must be indicated in the form of a key / value map.

No

no tags.

Example of a response

[
  {
    "name":"upper_75",
    "datapoints":[
      [622,1450754160000],
      [365,1450754220000]
    ]
  },
  {
    "name":"upper_90",
    "datapoints":[
      [861,1450754160000],
      [767,1450754220000]
    ]
  }
]

Lets you search for the different metrics available.

Example of a request:

{
  "name": "upper_50",
  "limit": 5
}
Table 9. Parameter of the request
json path type description mandatory possible values default value

/name

String

Part of the name of the metric you are looking for.

No

/limit

Int

The maximum number of metric names to return.

No

The body of the request is optional.

Example of a response:

["upper_25","upper_50","upper_75","upper_90","upper_95"]
POST /api/grafana/v0/search/values

Allows you to search for the different values for the indicated key.

Example of a request:

{
  "field": "name",
  "query": "up",
  "limit": 5
}
Table 10. Parameters of the request
json path type description mandatory possible values default value

/field

String

the searched key.

Yes

/query

String

Part of the name of the key you are looking for.

Yes

/limit

Int

The maximum number of metric names to return.

No

The query and limit parameters of the query are optional.

Example of a response:

["upper_25","upper_50","upper_75","upper_90","upper_95"]
POST /api/grafana/v0/annotations

Lets you search for annotations.

Example of a request:

{
  "from": "2020-2-14T01:43:14.070Z",
  "to": "2020-2-14T06:50:14.070Z",
  "limit" : 100,
  "tags": ["tag1", "tag2"],
  "matchAny": false,
  "type": "tags"
}

Example of a response in current release:

{
  "annotations" : [
    {
      "time": 1581669794070,
      "text": "annotation 7",
      "tags": ["tag2","tag3"]
    },
    {
      "time": 1581666194070,
      "text": "annotation 6",
      "tags": ["tag3","tag5"]
    }
  ],
  "total_hit" : 2
}
Table 11. Parameters for the request
json path type description mandatory possible values default value

/from

String

The start date to search for annotations. Only annotations with a date greater than or equal to this date.

No

Must represent a date in the following format (UTC): * yyyy-MM-dd’T’HH: mm: ss.SSS *

January 1, 1970 (UTC)

/to

String

The end date to search for annotations. Only annotations with a date less than or equal to this date.

No

Must represent a date in the following format (UTC): * yyyy-MM-dd’T’HH: mm: ss.SSS *

The default is infinity

/limit

Integer

The maximum number of annotations to return

No

positive integer

100

/tags

Liste de string

The name of the tags to filter the annotations. The behavior depends on the value of the _ / type_ field

No

[] (empty array)

/matchAny

Boolean

If the type field is equal to TAGS. If true the annotations must have at least one of the tags in the tags field otherwise the annotations must contain all the tags.

No

true

/type

String

The type of request. If the value is "ALL", all annotations in the time range will be returned. If the type is "TAGS", the annotations must also contain tags (either all or at least one depending on the value of matchAny.

No

one value from [ALL, TAGS]

ALL

POST /api/grafana/v0/tag-keys

Used to find out the keys that can be used in the tag_values endpoint.

Example of a request:

{}

Example of a response:

[
    {
        "type": "string",
        "text": "Algo"
    },
    {
        "type": "int",
        "text": "Bucket size"
    }
]

The values in "text" are the values that can be used as a key in the endpoint tag-values.

POST /api/grafana/simplejson/tag-values

Lets you search for the different metrics available.

Example of a request:

{"key": "Algo"}

Example of a response:

[
    {
        "text": "NONE"
    },
    {
        "text": "AVERAGE"
    },
    {
        "text": "FIRST"
    },
    {
        "text": "MIN"
    },
    {
        "text": "MAX"
    }
]

Here are the values available for the corresponding keys.