1. What is HelloData?

HelloData is a smart data access platform that:

  • Registers a variety of smart metering devices (electricity, gas, water, solar, other …)

  • Manages authorization of access to data and devices

  • Routes data to a number of 3rd party applications based on user preferences

Read more about HelloData on https://www.hellodata.org.

2. How can I connect my app?

Creating an HelloData application will allow you to provide additional services to customers by collecting and analysing their meter data. To connect your app, we provide an API (the Service Provider Application API). With this API you can get authorized access to and collect data from the devices of your customers.

This guide is intended for developers who are building apps to connect to the HelloData platform.
This guide is intended for developers who are building apps to connect to the HelloData platform.

3. How does it work?

To let your app retrieve data from an ERD (Energy Reading Device), only 3 steps are needed:

Step Description

1

Get an authorization
Your app is only allowed to get data from a device, if the owner of the device authorizes this based on the type of data (e.g. electricity or gas).

2

Choose the options you want
After the authorization was agreed by the customer, you get an overview of the available data and options. Depending on the available options, you could choose for example between getting the data automatically (the data is pushed to you near-time) or getting the data on request. And you can choose what data you request.

3

Retrieve the data
If you configured the subscription with near-time data, then you just need to collect all incoming data. Otherwise, you will need to send a datarequest periodically.

4. Authorization

HelloData uses a three legged OAuth 1.0a to authorize service-provider-applications to request data from a set of channels. HelloData uses the normal OAuth authorization pattern which involves redirecting the user to HelloData to authorize the request.

  For details about OAuth messages, please check the OAuth 1.0a specification. This document only specifies the HelloData specific information you need to make the authorization work.
  The authorization process is updated in this version of the SPA-API. For backwards compatibility the old process is still supported. This process is described in an appendix.

4.1. Authorization step 1: OAuth request_token

The first step in the authorization is to request an OAuth request_token. With this request, the SPA has to specify the main categories (tags) for which authorization is requested: electricity, gas, water and heat. This can be specified either as a json body or as a query-string.

Method URI

POST

/oauth/request_token

Authorization: request authorization example, as json body
{
  "request_authorization": {
    "tags":["electricity", "gas"]
  }
}
  When using a json body, then the content type for the request MUST be application/json. Using application/x-www-form-urlencoded will result in a 401 "Invalid OAuth Request" error resonse.
Authorization: request authorization example, as query string
request_authorization[with_history]=true&request_authorization[tags][]=electricity&request_authorization[tags][]=gas
  The query-string should be url encoded: request_authorization%5bwith_history%5d=true&request_authorization%5btags%5d%5b%5d=electricity&request_authorization%5btags%5d%5b%5d=gas

4.2. Authorization step 2: Redirect user for authorization

With the OAuth request token, the user can be redirected to the HelloData authorization page. On this page, the user can authorize the requested data streams.

Method URI

GET

/oauth/authorize?oauth_token=<<token>>

Parameter
oauth_token: The token received in request_token call.

4.3. Authorization step 3: Get access token

When an SPA is granted access, the request token should be exchanged for an access token.

Method URI

POST

/oauth/access_token

4.4. Authorization step 4: Source Listing

When an SPA is granted access, it can use the access token to request a list of sources. This interface will return the available sources depending on the OAuth access token being used. This will depend on the preceding OAuth request, with the specified main categories. E.g. when only the main category "Electricity" was requested, then no "Gas" related sources will be returned.

Method URI Accept Header

GET

/spa_api/sources

application/json

Source listing example
[
  {
    "hardware_type":"p1_ele",
    "erd_name":"myerd",
    "label":"aansluitpunt elektra",
    "source_identifier":"1324513526",
    "quantities":[
      "energy_forward_tariff1",
      "energy_forward_tariff2"
    ],
    "resolutions":["10s","1m"],
    "sampletypes":["instantaneous"],
    "tags":["electricity"]
  },
  {
    "hardware_type":"imm",
    "erd_name":"myerd",
    "label":"groep 1",
    "source_identifier":"146576425",
    "quantities":[
      "energy_forward_tariff1",
      "energy_forward_tariff2"
    ],
    "resolutions":["10s","1m"],
    "sampletypes":["instantaneous"],
    "tags":["electricity"]
  }
]
Table 1. Possible response-codes
HTTP-response-code Reason

200

OK

206

No active source-list authorization found

403

Unauthorized

  The access token remains valid and could be stored to be used later on again. See section about configuration for more in formation.

5. Choose the options you want

5.1. Step 1: Indicate which sources the app is going to use

The SPA can request to subscribe to sources of the measuring device. The access token needs to be included with the request. See Appendix B: Supported subscription parameters for more information about the parameters in this request.

  This step does not result in data to be retrieved. It creates subscriptions on the measuring device. This device then starts measuring data.
Method URI Content-Type Header

POST

/spa_api/subscription_request

application/json

Authorization: subscription request example
{
  "requested_sources":[
    {
      "source_identifier":"112233",
      "source_details":[
        {
          "quantities":["energy_forward_tariff1","energy_forward_tariff2"],
          "resolution":"10s",
          "sampletype":"instantaneous"
        },
        {
          "quantities":["power_forward","power_reverse"],
          "resolution":"1m",
          "sampletype":"average",
        }
      ]
    },
    {
      "source_identifier":"445566",
      "source_details":[
        {
          "quantities":["power"],
          "resolution":"10s",
          "sampletype":"average"
        }
      ]
    }
  ]
}

5.2. Step 2: Retrieve the subscription ids

The subscription id’s created in the previous step can be retrieved, to be used for requesting data in succeeding steps.

Method URI Accept Header

GET

/spa_api/subscriptions

application/json

Source response for requested_sources example
[
  {
    "source_identifier":"123456",
    "subscriptions": [
      {
        "subscription_identifier":"abc123",
        "resolution":"10s",
        "quantity":"energy_forward_tariff1",
        "sampletype":"instantaneous"
      }
    ],
  },
  {
    "source_identifier":"654321",
    "subscriptions": [
      {
        "subscription_identifier":"abc456",
        "resolution":"1m",
        "quantity":"energy_forward_tariff1",
        "sampletype":"instantaneous"
      }
    ]
  }
]
Table 2. Possible response-codes
HTTP-response-code Reason

200

OK

206

No active source-list authorization found

403

Unauthorized

  For the old, deprecated authorization API, see appendix C.

5.3. Step 3: Data request

An SPA can request data from an authorized subscription by sending a request to HelloData. If the neartime field is set to false, HelloData will collect data from the ERD(s) (for the specified period as set in the from & to fields) and create a batch to be downloaded by the SPA. A request for data will return a request_id and format which has to be used to download the data later on. It will also specify which subscriptions are inactive at the time of requesting. Inactive subscriptions will start to send data when they become active.

If the neartime field is set to true, the data request activates the near-time data flow. In this case HelloData starts delivering data to the SPA neartime url (as set by the SP in the HelloData SPA admin page). The data will be delivered periodically, the value of the interval field determines the send interval.

Note that for neartime data requests the last request, overrules all previous neartime requests with the same interval for that SPA. For example:

Data request A, (neartime:true, interval:10s subscriptions: X and Y) is sent to HelloData. A moment later data request B, (neartime:true, interval:10s subscriptions: X and Z) is sent to HelloData. From now on data will be sent for subscription X and Z, data for subscription Y will NOT be sent anymore.

Method URI Content-Type Header

POST

/spa_api/data_requests

application/json

  Data requests (and the message described in the following sections) don’t use the access token, but instead they need to be signed. See the chapter Security for more information.
JSON example 1: Batch request
{
  "data_request":{
    "subscription_identifiers":["subscription1"],
    "from":"2012-07-23T00:00:00+02:00",
    "to":"2012-07-24T00:00:00+02:00",
    "neartime":false
  }
}
JSON example 2: Neartime data
{
  "data_request":{
    "subscription_identifiers":["subscription1"],
    "neartime":true,
    "interval":"10s"
  }
}
Table 3. Remarks on the data request
Field(s) Remark

subscription_identifiers

ERD’s can be subject to a limitation on the total number of subscriptions, which will vary depending on the requested resolution.

neartime

Boolean value. If set to true, HelloData delivers the requested data periodically. The interval should be specified in the interval field. If neartime is set to false, the data request is treated as a batch request. In this case the SPA initiates the request with the from and to fields set and collects the data with the use of the request_id (as received in the response).

from, to

Timezone is UTC. Maximum range (from - to) is limited to be a maximum of 3600 data points.

resolution

1s, 5s, 10s, 15s, 1m, 5m, 1h, 1d

interval

5s, 10s, 15s, 1m, 5m, 15m, 1h, 1d, 1w. The interval field is ignored when the neartime field is set to false.

  In order to limit the communication-load on the ERD’s, the number of data samples per batch data request has been limited to 3600 data points per ERD. These 3600 data points can be spread over multiple subscriptions.
  In case the request fails for one of the ERD’s, no data will be returned, not even for the other ERD’s. If a best-effort request is desired, because information about the capabilities of the ERD’s or their authorization state is not held, each ERD should be requested via a separate data request.
Request data_request response
{
  "format":"json",
  "request_id":"2-abc-1"
}
Table 4. Possible response-codes
HTTP-response-code Reason

201

OK, request created

400

Invalid parameters

401

Unauthorized. SPA not registered / invalid signature

Table 5. Possible error-codes
Error-code Message

200

Invalid from

201

Invalid to

202

Subscription(s) not found. Subscriptions will contain ids of found subscriptions.

203

No access to the subscription(s). Subscriptions will contain ids of unauthorized subscriptions.

204

Invalid interval.

205

Request size too large, max. 3600 points for each ERD.

6. Retrieve data

6.1. Batch requests

Each successful request for data returns an request_id. When a data-request was issued for batch-data the request-id can be used to retrieve the collected data for the batch. A service-provider can be notified using a ping-function (if implemented) when the data is ready to be downloaded.

Batch data will remain available for a maximum period of a month. After this period or when it is downloaded, whichever comes first, the batch will be removed and will no longer be available for the SPA.

Method URI Accept Header

GET

/spa_api/data_requests/<<request_id>>/data

application/json

Get data response
[
  {
    "subscription_identifier":"123",
    "datapoints": [
      {
        "sampletime_utc":"2011-02-01T00:00:00Z",
        "value":110.5
      },
      {
        "sampletime_utc":"2011-02-01T00:00:10Z",
        "value":110.6
      },
      {
        "sampletime_utc":"2011-02-01T00:00:20Z",
        "value":110.8
      }
    ]
  },
  {
    "subscription_identifier":"456",
    "datapoints": [
      {
        "sampletime_utc":"2011-02-01T00:00:00Z",
        "value":5876.1
      },
      {
        "sampletime_utc":"2011-02-01T00:00:10Z",
        "value":5877.5
      },
      {
        "sampletime_utc":"2011-02-01T00:00:20Z",
        "value":5879.3
      }
    ]
  }
]
Table 6. Possible response-codes
HTTP-response-code Reason

200

OK

202

Batch not ready for download

400

Invalid parameters

404

Batch not found.

406

Not acceptable. The wrong accept-format is used for the data. Should be equal to the format of the data_request.

6.2. Neartime data

If a service-provider-application wants to be able to receive near-time data it has to implement an api that is able to process data from HelloData.

Method URI

POST

Can be set by the SPA in the SPA admin page of HelloData

Neartime data body example
The format is equal to the GET response for batch data. For an example, see the example for batch data.

7. Configuration

7.1. Data Request (PUT)

Alter the subscription identifiers for a specific data request.

Method URI Content-Type Header

Use

PUT

/spa_api/data_requests/request_id

application/json

Either for updating using subscriptions_identifiers and data_request_id. Or for adding or removing subscriptions.

PUT

/spa_api/data_requests

application/json

For updating using subscription_identifiers and interval.

JSON example 1: Updating interval on existing subscriptions
{
  "data_request":{
    "interval":"10s",
    "subscription_identifiers":[
      "subscription_356",
      "subscription_486"
    ]
  }
}
JSON example 2: Adding and removing subscriptions
{
  "data_request":{
    "interval":"1m",
    "add_subscription_identifiers":[
      "subscription_65",
      "subscription_869"
    ],
    "remove_subscription_identifiers":[
      "subscription_674",
      "subscription_10"
    ]
  }
}
Table 7. Remarks
Field(s) Remark

interval

The send interval for the channel.

subscription_identifiers

Subscriptions with given identifiers replacing the current list. Not allowed in combination with add_subscription_identifiers and/or remove_subscription_identifiers.

add_subscription_identifiers

Subscriptions with given identifiers will be added to current list.

remove_subscription_identifiers

Subscriptions with given identifiers will be removed from current list.

Put data_request response
{
  "request_id":"2-abc-1",
  "format":"json",
  "inactive_subscription_identifiers":[
    "subscription_146",
    "subscription_980"
  ]
}
Table 8. Possible response-codes
HTTP-response-code Reason

200

OK, request updated

304

Not modified

400

Invalid parameters

401

Unauthorized. SPA not registered / invalid signature

Table 9. Possible error-codes
Error-code Message

202

Subscription(s) not found. Subscriptions will contain ids of unfound subscriptions.

203

No access to the subscription(s). Subscriptions will contain ids of unauthorized subscriptions.

7.2. Updating authorizations

If an SPA wants to change the authorizations (e.g. it now has an authorization for Electricity only and it wants an authorization for Gas as well), then the SPA can start the authorization process again and send a new authorization request with an updated tag list. With the new access token, the SPA can retrieve an updated source list. The old access token could be removed.

7.3. New sources available

If the user has new sources available, then the SPA can retrieve the updated source list with the access token received during the authorization.

  HelloData doesn’t send a notification to the SPA about an updated source list. The SPA could add an option in the app to let the user notify the app about new sources.

7.4. Batch ping

A service-provider-application can optionally implement a ping-function. This function will be called by HelloData as soon as a request for batch-data is ready for download. By implementing this function a SPA will no longer need to poll for data on the pending data-requests.

Method URI

POST

Can be set by the SPA in the SPA admin page of HelloData

Post batch ping
{
  "data_request_id":"1-abc-2"
}

8. Service Provider API overview

The table below gives an overview of the resources defined in the previous chapters that will be available to the SPA’s.

Table 10. Server-side resources service provider API
Resource Method Description

Authorize

POST

Request authorization for a list of sources.

(Data) Request

POST

Request data from one or more channels on HelloData. If the request is correct it will return an identifier which can be used to download the data will in a single batch.

 

PUT

Alter subscription identifiers for a specific data request. The identifier and the list with subscription identifiers is returned.

Batches

GET

Download a data batch using the request identifier.

The table below gives an overview of the resources on the SPA side defined in the previous chapters.

Table 11. Client-side resources service provider API
Resource Method Description

Batch ping

POST

Can be optionally implemented by the SPA. If implemented a SPA will receive notifications when batches are ready to be downloaded.

Near-time data

POST

An SPA has to implement this function if it wants to be able to receive near-time data.

9. Email authorization

In addition to the default OAuth request token method, an asynchronous method is available relying on JSON Web Tokens (JWT). As this method suits the use case of requesting authorizations in an email campaign, this method is conveniently called email authorization. This allows a URL to be generated containing the authorization request and it’s parameters. The JWT is tied to a specific SPA using the SPA id, and can have a preset timeout. The decentral nature of the tokens allows links to be generated and distributed by the SP, allowing users to use the link to authorize the SPA up until the moment of timeout. This prevents the SPA from having to handle the associated OAuth procedure synchronously. The SPA can query for available access_tokens using the dedicated URI.

Table 12. Email authorization parameters
Field(s) Remark

remote_identifier

The identifier/label displayed in the authorization request, also used as identifier in the response to the SPA.

quantity

The quantity required for the requested channels. This parameter will be discarded if a payload is entered.

resolution

The resolution required for the requested channels. This parameter will be discarded if a payload is entered.

sampletype

The sampletype required for the requested channels. This parameter will be discarded if a payload is entered.

expiration

The duration before the token becomes expired. This can be expressed using one of the available time units (s, m, h, d) preceded by a number. For example 7d in case the token is to expire after one week.

payload

The payload is an JSON array containing the actual OAuth request, like would be POSTed to /oauth/request_token. This payload resembles the source_details array, containing quantities, resolution, sampletype and with_history. Using this payload is optional and doing so discards the separate options of quantity, resolution, and sampletype.

10. Topology of the web services

HelloData provides web services to enable a SPA to request a user to authorize a data stream and query for collected data. HelloData provides web services to two different kinds of parties. There is an API that can be used by the ERDs which provides functions to register themselves, upload configuration and measurement data and query for commands. The other set of web services will provide access for SPAs. SPAs will have to be able to request authorization, request measurement data and query for collected data.

To be able to process as many requests as possible and to be highly scalable, HelloData is implemented using a pattern that uses synchronous reads and asynchronous writes. Reads on a system like HelloData are synchronous due to the fact a client is waiting for the response of the read-action. Some read actions can be optimized or preprocessed (for example querying for batch-data) to allow low response times.

Processing data send by the client can take a considerable amount of time to complete. For instance, writing measurement data to HelloData needs to be checked and appended to a batch or delivered to one or more service-provider-applications. To be able to process as many requests as possible HelloData will process the most recurring write actions asynchronously. Data writes can be processed asynchronously because a client (most of the time) has no interest in what happens to the data. Write requests will be checked to some degree and pushed to a queue for later processing. This allows HelloData to close the connection to the client and process other requests.

10.1. JSON data and headers

All functions in the web-service are compatible with JSON. The webs-service requires a Content-Type: application/json header for each POST or PUT action.

All endpoints that return JSON must be called with an Accept header indicating application/json as an acceptable media type. The simplest header for doing that is Accept: application/json.

10.2. Versioning and headers

The api will be versioned using a vendor specific accept-header. By indicating application/vnd.hd.spa-v1 as an acceptable media type a specific version of the api will be used. Omitting the versioning media type will result in returning the default (newest) version of the api. Currently only v1 is valid.

It’s possible to indicate both application/vnd.hd.spa-v1 and application/json media ranges by combining the media ranges in the standard manner according to the HTTP/1.1 spec. For example, Accept: application/vnd.hd.spa-v1, application/json is a valid header indicating Version 1 of the API when requesting a JSON resource.

10.3. Error handling

All the called functions in the API have to comply with both technical and functional demands. All requests will have to be syntactically correct (technical) and the given values will have to be logically correct (functional). All errors will return a response-code somewhere in the 400 or 500-range as illustrated in the table below.

Response-code Reason

400

Request parameters incorrect

401

Unauthorized. The given application_id and public-key are incorrect or unknown.

403

Forbidden (e.g. to read this channel)

404

Resource (channel/batch) or function is non-existent.

500

Generic (server) error while processing the request.

If multiple errors occur in a single request the lowest response-code of the combined errors will be returned. The body of the response will contain details about the errors including specific channel_ids if applicable.

JSON example 1: incorrect request parameters
[
  {
    "code":400,
    "description":"Requested parameters incorrect",
    "subscriptions":[
      "subscription_154",
      "subscription_664",
      "subscription_640"
    ]
  }
]
JSON example 2: access forbidden
[
  {
    "code":403,
    "description":"Requested parameters incorrect",
    "subscriptions":[
      "subscription_154",
      "subscription_165"
    ]
  }
]

The error-codes and matching descriptions can be used to identify and correct the problems. The error-codes are primarily meant to be used for automatic error-correction whereas the description is a human readable text for the error.

11. Security

11.1. Authentication

Authentication on the web services consists of two components. The first component of authentication is validating the identity of the clients (SPA). The second component is validating whether or not a received messages is genuine and not tampered with during transit.

11.2. Identification and validation API

Authentication of the SPA’s (Clients) using the API will be done by using private/public key pairs. Each SPA will receive a unique pair of keys. A pair of keys consists of a public and a private part of a 2048 bits encoded RSA-key. Clients will use the private keys to sign every message that is sent to HelloData. HelloData will use the corresponding public key to determine whether or not the message is genuine.

Each request sent by the client will contain a unique client-id (X-Auth-User) and signature (X-Auth-Sig) for that specific message. The client-id in the header will be used by HelloData to find the correct public key. Validation of the message is achieved by decrypting the signature using the public key and comparing it to the SHA1 of the method, path and body of the received message. Tampering with the message will result in the signature not matching the hash of the message details. By using multiple variables to generate signature of the message it allows HelloData not only to check the body of the message, but also the called function of the API. The identity of the client can be determined because decrypting the signature can only be done using the public key that matches the private key it was encrypted with.

Messages sent by HelloData to the SPA are signed in the same way using the private key of HelloData. And therefore the signature can be decrypted by the SPA using the HelloData public key.

An example how to construct the signature (X-Auth-Sig):
{"subscription_ids":["ch1"]}

The string that needs to be signed is:

"POST" + "/spa_api/requests" + "{\"subscription_ids\":[\"ch1\"]}"

11.3. OAuth

The OAuth messages do not have to be signed with the above signing scheme. The OAuth messages are signed with the OAuth key and OAuth secret.(these are supplied to the SPA by MPARE)

11.4. Transport security

All API’s are available using a SSL connection. Although the transport can be considered secure, the authentication of messages on the API by signing the requests provides an extra layer of security.

12. Appendix A: JSON schemas

12.1. Authorization

Request
{
  "type": "object",
  "properties": {
    "request_authorization": {
      "type": "object",
      "description": "Request authorization, based on a list of tags.",
      "items": {
        "type": "object",
        "properties": {
          "tags": {
            "type": "array",
            "required": true,
            "items": {
             "type": "string"
            }
          }
        }
      }
    }
  }
}
Source list
{
  "type":"array",
  "description":"A list of sources",
  "items":{
    "type":"object",
    "description":"Details of a source",
    "properties":{
      "hardware_type":{
        "type":"string",
        "description":"The type of source"
      },
      "erd_name":{
        "type":"string",
        "description":"The type of source"
      },
      "label":{
        "type":"string",
        "description":"The label for this source given by the user"
      },
      "source_identifier":{
        "type":"string",
        "description":"The identifier for this source generated by the ERD"
      },
      "resolution":{
        "type": "array",
        "description":"The available resolutions",
        "items": {
          "type":"string"
        }
      },
      "quantity":{
        "type":"array",
        "description":"The available quantities",
        "items": {
          "type":"string"
        }
      },
      "sampletype":{
        "type":"array",
        "description":"The available sampletypes",
        "items": {
          "type":"string"
        }
      }
    }
  }
}
Sources request
{
  "type": "object",
  "properties": {
    "requested_sources": {
      "type": "array",
      "items": {
        "description": "Request for a channel",
        "type": "object",
        "properties": {
          "source_identifier": {
            "description": "The identifier/label displayed in the source list ",
            "type": "string",
            "required": true
          },
          "source_details": {
            "description": "Details about what types of data to subscribe",
            "type": "array",
            "required": false,
            "items": {
              "type": "object",
              "properties": {
                "quantities": {
                  "description": "The quantities required for this channel ",
                  "type": "array",
                  "required": true,
                  "items": {
                    "type": "string",
                    "description": "The quantity required"
                  }
                },
                "resolution": {
                  "description": "The resolution required for this channel",
                  "type": "string",
                  "required": true
                },
                "sampletype": {
                  "description": "The sampletype required for this channel",
                  "type": "string",
                  "required": true
                },
                "with_history": {
                  "description": "Whether or not previous measurements for this
                  source will be included in the authorization. If not given,
                  this defaults to false ",
                  "type": "boolean",
                  "required": false
                }
              }
            }
          }
        }
      }
    }
  }
}

12.2. DataRequest create

Request data_request
{
  "description":"The details for this data-request",
  "type":"object",
  "properties":{
    "data_request":{
      "type":"object",
      "properties":{
        "subscription_identifiers":{
          "type":"array",
          "items":{
            "description":"Id of the subscription for which the data is requested.",
            "type":"string",
            "required":true
          }
        },
        "neartime":{
          "description":"Request for neartime data",
          "type":"boolean",
          "required":true
        },
        "from":{
          "description":"The start of the period for which to send
          data. Required for non-neartime requests",
          "type":"string",
          "format":"date-time",
          "required":false
        },
        "to":{
          "description":"The end of the period for which to send
          data. Required for non-neartime requests",
          "type":"string",
          "format":"date-time",
          "required":false
        },
        "interval":{
          "description":"The send interval for the channel. Required
          if neartime",
          "type":"string",
          "required":false
        }
      }
    }
  }
}
Data request resposne
{
  "type":"object",
  "properties":{
    "request_id":{
      "description":"The request identifier.",
      "type":"string",
      "required":true
    },
    "format":{
      "description":"The format (json) in which the data will be
      formatted",
      "type":"string",
      "required":true
    },
    "inactive_subscription_identifiers":{
      "type":"array",
      "items":{
        "type":"string",
        "description":"The subscription-identifier of an inactive
        subscription"
      }
    }
  }
}

12.3. Data Request (PUT)

Put data_request
{
  "description":"The details for this data-request",
  "type":"object",
  "properties":{
    "data_request":{
      "type":"object",
      "properties":{
        "interval":{
          "description":"The send interval for the channel. Optional for
          near-time in case the subscription_identifier is given.",
          "type":"string",
          "required":false
        },
        "subscription_identifiers":{
          "type":"array",
          "items":{
            "description":"Id's of subscription(s) to replace to current
            subscriptions. Optional for near-time in case the interval is given.",
            "type":"string",
            "required":false
          }
        },
        "add_subscription_identifiers":{
          "type":"array",
          "items":{
            "description":"Id's of subscription(s) to add to current subscriptions.",
            "type":"string",
            "required":false
          }
        },
        "remove_subscription_identifiers":{
          "type":"array",
          "items":{
            "description":"Id's of subscription(s) to remove from current subscriptions.",
            "type":"string",
            "required":false
          }
        }
      }
    }
  }
}
Put data_request response
{
  "type":"object",
  "properties":{
    "request_id":{
      "description":"The request identifier.",
      "type":"string",
      "required":true
    },
    "format":{
      "description":"The format (json) in which the data will
      be formatted",
      "type":"string",
      "required":true
    },
    "inactive_subscription_identifiers":{
      "type":"array",
      "items":{
        "type":"string",
        "description":"The subscription-identifier of an
        inactive subscription"
      }
    }
  }
}

12.4. Batch ping

Post batch ping
{
  "type":"object",
  "properties":{
    "data_request_id":{
      "description":"The request_id that is ready for download.",
      "type":"string", "required":true
    }
  }
}

12.5. (Neartime) Data

JSON
{
  "description":"The data for the request",
  "type":"array",
  "items":{
    "type":"object",
    "properties":{
      "subscription_identifier":{
        "description":"Id of the subscription.",
        "type":"string",
        "required":true
      },
      "datapoints":{
        "description":"The data of the channel for this period",
        "type":"array",
        "required":true,
        "items":{
          "description":"A single datapoint for a given sampletime",
          "type":"object",
          "properties":{
            "sampletime_utc":{
              "description":"The sampletime of the point (end of
              the resolution-period)",
              "type":"string",
              "format":"date-time",
              "required":true
            },
            "value":{
              "description":"The value of this sampletime",
              "type":"number",
              "required":true
            }
          }
        }
      }
    }
  }
}

12.6. Error handling

Schema error-response
{
  "type":"array",
  "description":"Error response",
  "items":{
    "type":"object",
    "properties":{
      "code":{
        "description":"Code to identify the error.",
        "type":"number",
        "required":true
      },
      "description":{
        "description":"Human readable description of the error.",
        "type":"string",
        "required":true
      },
      "subscriptions":{
        "type":"array",
        "description":"Identifiers of the subscriptions for which the error occurred",
        "items":{
          "type":"string"
        }
      }
    }
  }
}

13. Appendix B: Supported subscription parameters

13.1. Resolutions

The resolution refers to the sample period of the requested data. Some endcustomers might offer limited data retention either because their ERD’s support data storage, or because an external storage provider is connected. The default data retention is defined for all resolutions, which can be used by issuing a batch request.

Table 13. Available resolutions
Resolution Default retention

1s

3d

5s

3d

10s

7d

15s

7d

1m

7d

5m

1095d

15m

3600d

1h

3600d

1d

3600d

13.2. Quantities

The quantity refers to the type of measurement data that can be requested.

Table 14. Available quantities
Quantity Parameter Unit

Energy

energy

Wh

Energy forward tariff 1

energy_forward_tariff1

Wh

Energy forward tariff 2

energy_forward_tariff2

Wh

Energy reverse tariff 1

energy_reverse_tariff1

Wh

Energy reverse tariff 2

energy_reverse_tariff2

Wh

Power

power

W

Power forward

power_forward

W

Power reverse

power_reverse

W

Reactive power

reactive_power

VAr

RMS Current

rms_current

A

RMS Voltage

rms_voltage

V

Power factor (cos phi)

cos_phi

Fraction

Frequency

frequency

Hz

Gas consumption

consumption_gas

m3

Water consumption

consumption_water

m3

Heat

heat

J

Cold

cold

J

Tariff

tariff

Integer

Quantities for M-bus devices

HelloData supports several M-Bus devices. The current implementation regarding the request for M-bus data requires the explicit definition of the field number corresponding to the field values in the M-bus telegram. Documentation for the M-bus devices is available on request.

HelloData supports the following M-Bus devices:

  • Kamstrup Multical 21

  • Kamstrup Multical 402

  • Socomec Countis E15 and E16

  • Socomec Countis E25 and E26

  • Socomec Countis E45 and E46

  • FastForward EnergyCam version 1

  • GWF Unicode watermeter

  • BTR t/m converter

13.3. Sample types

The sample type adds to the resolution and quantity by specifying how the measurement samples within the resolution (sample period) should be aggregated. In case the resolution equals the period of the underlying measurement, no aggregation occurs and therefore the sample type will make no difference.

Table 15. Available sample types
Sample type Description

minimum

Returns the minimal value within the sample period.

maximum

Returns the maximum value within the sample period.

average

Returns the mean value from all values measured in the sample period.

cumulative

Returns the sum of the values measured in the sample period, intend for energy-based measurements.

instantaneous

Returns the last measured value at the moment the data is being sent

  Please take care of selecting good combinations of quantities and sample types. For example: Energy should only be combined with instantaneous. Other combinations don’t make sense. Power could be combined with minimum, maximum and average.

13.4. Send intervals

The send interval is similar to the resolution, but different in the sense that it concerns the periodicity by which data is sent rather than measured. The send interval is considered to be larger or equal to the resolution such that each data transmission will feature one or more samples.

Send intervals of 5s, 15s, 1m, 15m, 1h, 1d, and 1w are available.

  Requesting a send interval that is shorter than the resolution of the measured data will result in receiving message with null data (see example below). For example: if the resolution is 1 minute and the send interval is 10 seconds, then you will receive 5 messages with null data after each message with valid data. To avoid this, make sure that the send interval is at least as long as the resolution.
Example Get data response message with null data when send interval is shorter than the resolution
[
  {
    "subscription_identifier":"123",
    "datapoints": [
      null
    ]
  }
]

14. Appendix C: Deprecated authorization requests

In the deprecated API it’s possible to request authorization for sources in a single step - the user is then required to authorize the app and select the relevant sources at the same time. This turned out to be too complex for end users. Please use the new API documented above.

Method URI Content-Type Header

POST

/oauth/request_token

application/json

Deprecated authorization request
{
  "type":"object",
  "properties":{
    "requested_sources":{
      "type":"array",
      "items":{
        "description":"Request for a channel", "type":"object",
        "properties":{
          "remote_identifier":{
            "description":"The identifier/label displayed in the
            authorization request, also used as identifier in the response
            to the SPA",
            "type":"string", "required":true },
          "source_details":{
            "description":"Details about what types of data to authorize",
            "type":"array", "required":true,
            "items":{
              "type":"object",
              "properties":{
                "quantities":{
                  "description":"The quantities required for this
                  channel",
                  "type":"array", "required":true,
                  "items":{
                    "type":"string",
                    "description":"The quantity required"
                  }
                },
                "resolution":{
                  "description":"The resolution required for this channel",
                  "type":"string", "required":true
                },
                "sampletype":{
                  "description":"The sampletype required for this channel",
                  "type":"string", "required":true
                },
                "with_history":{
                  "description":"Whether or not previous measurements for this
                  source will be included in the authorization. If not given,
                  this defaults to false",
                  "type":"boolean", "required":false
                },
                "prefered_source": {
                  "description": "Source identifier for the prefilled source for this authorization",
                  "type":"string", "required":false
                }
              }
            }
          },
          "tags":{
            "description":"The predefined tags required for this channel",
            "type":"array", "required":false,
            "items":{
              "type":"string",
              "description":"The requested tag"
            }
          }
        }
      }
    }
  }
}

15. Appendix D: Deprecated response formatting and urls

All API requests for json data SHOULD include an Accept: application/json header. For backwards compatilbity reasons, it’s also possible to append a ".json" extension to the URL for these requests, making the Accept header optional. This extension is deprecated.