.wpb_animate_when_almost_visible { opacity: 1; }
Data Share
A single API to create services that connect all your users' objects data. Expand your potential with the Data Share ecosystem.

This document will help you get started using Data Share and create great new applications and services for your users. Data Share is based on a consent user journey, and this document will help you get all the parts of this journey.

You can find the full documentation for Data Share here: https://datashare.orange.com/dev/

Table of content

Before starting

Data Share is an end user service helping users manage their connected life. By aggregating and storing data from different objects, the user can have simpler view and control over its connected objects data. The user can therefore choose what to share and with whom, without have to reconnect each object to every service provider. Before using data, you therefore need to ask permission from the user to access its data. As you will be using end users' data, you are responsible for the right usage of this data. see terms & conditions

Throughout this guide, we will take the example of a Gym Club that wants to offer a new kind of coaching to its client.

Every API call and redirect is made with the base URL https://api.orange.com/datavenue/datashare/v2 The end user portal is accessible through https://datashare.orange.com

If you are coming from the V1 version, please refer to this guide for changes: https://datashare.orange.com/dev/apiv2.html

Understand the end user point of view

The Data Share service is based on user accounts. Each user manages its account and the data he will share with your service.

To test your app, it is best to have access to end users account. To create an end user account, you will need to “sign up” on the Data Share portal https://datashare.orange.com/signup . In your app, in the consent process, user will need to login before accepting to share data. They will also be able to create an account at this point if they do not have one.

Data oriented IoT

Data Share is based on the user's data, and therefore can abstract the objects and devices from the real data. That means that you will mainly work with normalized data streams. Unlinke other IoT platforms, devices are not the entry point for your data exploration, but data streams are. All of this will be explained in the next parts.

Most of your calls will be protected, and user based. To get consent to be able to use user’s data, you will need to follow the OAuth2 consent flow.

OAuth2 three legs is a common way to ask the user consent in a secure way (link more on OAuth2). Through a system of redirections, your app will be able to ask the user consent without having to ask for a login/password. This is also called the authorization code grant for OAuth2.

You can find the full documentation for the OAuth flow here: https://datashare.orange.com/dev/oauth2.html

Understanding scopes

To be able to retrieve data from the end user, you will need to add the necessary scopes, needed for your service. Scopes are individual permissions to access individual data. You can find the list of data available within Data Share in the documentation here: https://datashare.orange.com/dev/streams.html

And for each data stream you have the related scopes to use. For example for our Gym Club, we’ll need probably:

Data streamScopeAction
/connectionread_connectionto get user connections
/me/activity/stepsread_data_me_activity_stepsto get user's steps data
/me/body/heart/rateread_data_me_body_heart_rateto get user's heart rate data
/me/body/weightread_data_me_body_weightto get user's weight data
/me/activity/energyread_data_me_activity_energyto get user's energy calories data

Step one: Create the redirection URL

To get the user consent you will need to redirect him to the Data Share consent pages, with the appropriate GET parameters. Everything should be URL encoded.

Example:

GET /authorize?client_id=yourClientId&redirect_uri=http%3A%2F%2Fwww.yourcallbackurl.com&response_type=code&scope=YOUR_SCOPES&state=Unique_ID_For_You

NB: state is a free value used to maintain state between the request and callback. The authorization server includes this value when redirecting the user-agent back to the client. The parameter MUST be used for preventing cross-site request forgery.

For our example, for our Gym Club:

GET /authorize?client_id=lp9rTn6mm…LmgAAg&redirect_uri=http%3A%2F%2Fwww.MyGreatGymClub.com%2Fconnection%2FUser3&response_type=code&scope=read_connection%20read_data_path%20read_data_me_activity_steps%20read_data_me_body_heart_rate%20read_data_me_body_weight%20read_data_me_activity_energy&state=UniqueStateParam

Once the user has validated the consent form, he will be redirected to your callback URL. In this callback, you will receive thecode to exchange. The code is provided as a parameter in the returned URL. You will also have state returned as parameter. The value of this parameter should be the exact value that was present in the client authorization request.

REDIRECT  (302) http%3A%2F%2Fwww.MyGreatGymClub.com%2Fconnection%2FUser3?code=6Ho0bT&state=UniqueStateParam

In case of error (e.g. user consent is denied) , the details about the error are sent back to your server using your callback URL:

REDIRECT  (302) http%3A%2F%2Fwww.MyGreatGymClub.com%2Fconnection%2FUser3?error=access_denied&error_description=User denied access&state=UniqueStateParam

Step three: Exchange the code for an access token

The last step is to exchange the code for an access token and a refresh token. This access token will be required to get user data.

The Authorization header is constructed as follows:

  1. The client key id client secret are combined into a string "clientID:clientSecret"
  2. The resulting string is then Base64 encoded
  3. The authorization method and a space i.e. "Basic " is then put before the encoded string.
POST /token
Headers:
  Authorization: Basic bHA5clRuNm1tbm1UQWd…3TXUwNw==
  Content-Type: application/x-www-form-urlencoded
Body:
  grant_type=authorization_code
  code=6Ho0bT
  redirect_uri=http%3A%2F%2Fwww.MyGreatGymClub.com%2Fconnection%2FUser3

Response example (JSON)

{
  access_token:"9b02b1be-a5fe-4299-8b35-d9199bfdb471",
  token_type:"bearer",
  refresh_token:"57b7259f-8b93-42c4-8571-e4375441c3bb",
  expires_in:"43074",
  scope:"read_connection read_data_path read_data_me_activity_steps read_data_me_body_heart_rate read_data_me_body_weight read_data_me_activity_energy"
} 

expires_in is the expiration delay of the access token in seconds

Refresh your tokens

Each token has an expiration delay (expires_in in the response of POST oauth/token). When the access token expires instead of sending the user back through the authorization code grant type the client can use the refresh token to retrieve a new access token with the same permissions as the previous one.

The client requests a fresh access token from a valid issued Refresh Token, by making a POST /token request.

POST /token
Headers:
  Authorization: Basic bHA5clRuNm1tbm1UQWd…3TXUwNw==
  Content-Type: application/x-www-form-urlencoded
Body:
  grant_type=refresh_token
  refresh_token=57b7259f-8b93-42c4-8571-e4375441c3bb

Response example (JSON)

{
  "access_token":"eb4f621e-4d17-4bff-b97f-a43f282f47ae",
  "token_type":"bearer",
  "refresh_token":"57b7259f-8b93-42c4-8571-e4375441c3bb",
  "expires_in":"43074",
  "scope":"read_connection, read_data_path, read_data_me_activity_steps, read_data_me_body_heart_rate, read_data_me_body_weight, read_data_me_activity_energy"
} 

Bear in mind that both "access_token" and "refresh_token" can change. The access token is valid for 12 hours and the refresh token for 6 months. You can still refresh the access token if your token is invalid, but you will not be able to refresh it if the refresh token is invalid and you will need to ask your user again for its consent.

Using your access token

To make a request to the API, you will need to pass a correct token for the correct user. You do not need to pass the user_id, the /-/ or /me/ is an alias for the user id (/me/ should be prefered)

 GET /users/me/connections
Headers:
  Authorization: Bearer 9b02b1be-a5fe-4299-8b35-d9199bfdb471 

Letting the user connect new devices to its Data Share account

The user devices and objects are gathered by connections. A connection is, most of the time, a brand of connected devices (eg. Fitbit, Withings, Netatmo...) where the user has a cloud account. In some cases a brand can have multiple connections (grouped by type of devices for example)

You will be able to help the user connect its devices, if it is still not the case yet. You can do it through your service without making the user leave it. Remember that the user connects the devices to its Data Share account and not directly to your service, you will still need the required scope to access the data of those devices. Any Data Share user may connect its devices from any supported vendor by going through the authorization process.

This process shall be initialized with a basic web browser navigating on the url https://datashare.orange.com/connectors/<name>/authorization/request on the Data Share server (<name> is case sensitive: all characters are in lower case).

Generally, the user will go through the following screens:

  • A Data Share authentication screen (if not authenticated in this browser session),
  • An authentication screen on the 3rd party backend (if not authenticated in this browser session),
  • An authorization screen on the 3rd party backend ("Do you authorize Data Share to access your data?").

The successful end of this process may be intercepted in two manners:

  1. (client way) by watching for HTTP response headers sent to the browser:

    X-Datavenue-authorization: success or error.
    X-Datavenue-connectionId: the newly created connection identifier.
    
  2. (server way) by implementing a callback mechanism:

    the callbackUrl parameter shall be passed as a query parameter (url encoded) in the first authorization request,
    then at the end of the (successful) process, the user's browser will be redirected to the specified url, with two additional query parameters:
        datashare-authorization: success
        datashare-connectionId: the newly created connection identifier.
    

You can find the list of all the connectors here: https://datashare.orange.com/dev/connections.html

Getting user connections

This API requires the read_connection scope.

Each connection is normalized to help you discover devices of the user easily.

A normal call to get the connections of a user is:

GET /users/me/connections
Headers:    
  Authorization: Bearer 9b02b1be-a5fe-4299-8b35-d9199bfdb471
  Accept: application/json

successful response sample (200 OK):

[
  {
    "id": 1005,
    "created": 1464960372000,
    "status": "WORKING",
    "error": "NONE",
    "lastStateChanged": 1464960372000,
    "connectorName": "fitbit",
    "key": "26BJQ7",
    "devices": [
      {
        "id": 4108,
        "created": 1464960372000,
        "status": "CONNECTED",
        "error": "NONE",
        "lastStateChanged": 1464960372000,
        "udi": "fitbit:charge@15849559",
        "model": "fitbit:charge",
        "instance": "15849559",
        "lastSync": 1463142195000,
        "niceName": null,
        "battery": 0.8,
        "capabilities": {
          "data": [
            "/devices/battery/level",
            "/me/activity/steps",
            "/me/activity/distance",
            "/me/activity/energy",
            "/me/activity/elevation",
            "/me/sleep"
          ],
          "commands": []
        },
        "links": {
          "self": "/users/me/connections/1005/devices/4108",
          "connection": "/users/me/connections/1005"
        }
      },
      {
        "id": 4110,
        "created": 1464960372000,
        "status": "CONNECTED",
        "error": "NONE",
        "lastStateChanged": 1464960372000,
        "udi": "fitbit:aria@YFM4G79EIC40IMA5",
        "model": "fitbit:aria",
        "instance": "YFM4G79EIC40IMA5",
        "lastSync": 1460949362000,
        "niceName": null,
        "battery": 0.8,
        "capabilities": {
          "data": [
            "/devices/battery/level",
            "/me/body/weight",
            "/me/body/fat"
          ],
          "commands": []
        },
        "links": {
          "self": "/users/me/connections/1005/devices/4110",
          "connection": "/users/me/connections/1005"
        }
      }
    ],
    "links": {
      "self": "/users/me/connections/1005"
    }
  }
]

This example tells us that the user has 1 connection, a Fitbit one, and 2 devices. For the connection, you will find the status, connectorName and different informations about the creation date and last state change You can read more about the different statuses here: https://datashare.orange.com/dev/connections.html#Connection_Status

For each device, you will find the model, udi, battery level, niceName, status and different date/time related information such as the lastSync date. The udi is a unique device identifier that will help you filter different APIs based on this particular device. You will also find the capabilities of the device. Those capabilities will help you understand what the data the device can gather and what commands you will be able to do on it. In this example, we can find that the device with the udi fitbit:charge@15849559 is capable of sending different data, but has no commands available.

"data": [
        "/devices/battery/level",
        "/me/activity/steps",
        "/me/activity/distance",
        "/me/activity/energy",
        "/me/activity/elevation",
        "/me/sleep"
      ],
      "commands": []
    },

Be careful, that does not mean that you have access to all the data of this device. For example, for our Gym Club we did not ask for the read_me_activity_elevation scope in the user consent, and therefore we won't be able to access the /me/activity/elevation data.

You can find more information on the different possibilities of this API, for example to search a particlular device, or filter by capabilities here : https://datashare.orange.com/dev/connections.html#Connections

Getting the user data

Normalization philosophy

Data Share helps you get the data you need, without having to know exactly how each device will speak to you. We normalized each type of data to help you exactly for that matter.

You can find all the details for each type of data here: https://datashare.orange.com/dev/streams.html

Data paths

To get what data path the user has in his account you can use the GetDataPath API.

GET /users/me/data
Headers:
  Authorization: Bearer 9b02b1be-a5fe-4299-8b35-d9199bfdb471
  Accept: application/json

Response sample:

[
  "/connection",
  "/devices/battery/level",
  "/me/activity/distance",
  "/me/activity/elevation",
  "/me/activity/energy",
  "/me/activity/steps",
  "/me/body/blood/o2",
  "/me/body/fat",
  "/me/body/heart/rate",
  "/me/body/weight",
  "/me/sleep"
]

Be careful, that does not mean that you have access to all of the data of the user. For example, for our Gym Club we did not ask for the read_me_activity_elevation scope in the user consent, and therefore we won't be able to access the /me/activity/elevation data.

Getting and searching for data

For each data path, you can then get the corresponding data, if you have consent from the user to get it. If you try to get data from a path you do not have consent too, you will get a 403 response:

[
  {
    "code":40301
    "message":"OAuthInsufficientScope",
    "description": "OAuth scope 'read_data_me_activity_elevation' is required for this resource"
  }
]

To get the data from a path or can use the following API:

GET /users/me/data/timeseries/{path}
Headers:
  Authorization: Bearer 9b02b1be-a5fe-4299-8b35-d9199bfdb471
  Accept: application/json

For example, if we would like to get the steps count from our user, we will make the following request:

GET /users/me/data/timeseries/me/activity/steps
Headers:
  Authorization: Bearer 9b02b1be-a5fe-4299-8b35-d9199bfdb471
  Accept: application/json

Successful response sample (200 OK):

[
    {
      "timestamp": "2016-06-09T06:38:06.000Z",
      "created": "2016-08-04T12:31:12.000Z",
      "model": "/me/activity/steps",
      "location": null,
      "metadata": {
        "source": "withings:ActivityTracker@2186606#0"
      }
      "tags": [
        "owner:fa049f57"
      ]
      "value": {
        "duration": 60,
        "value": 37
      }
    },
    {
      "timestamp": "2016-06-09T06:31:06.000Z",
      "created": "2016-08-04T12:31:12.000Z",
      "model": "/me/activity/steps",
      "location": null,
      "metadata": {
        "source": "withings:ActivityTracker@2186606#0"
      }
      "tags": [
        "owner:fa049f57"
      ]
      "value": {
        "duration": 60,
        "value": 7
      }
    },
    {
      "timestamp": "2016-06-09T06:29:06.000Z",
      "created": "2016-08-04T12:31:12.000Z",
      "model": "/me/activity/steps",
      "location": null,
      "metadata": {
        "source": "withings:ActivityTracker@2186606#0"
      }
      "tags": [
        "owner:fa049f57"
      ]
      "value": {
        "duration": 60,
        "value": 63
      }
    },
    {...}
]

Each data type has its own modelization, but most will at least have the value, timestamp and source parameters. You can find the modelization of each data type here: https://datashare.orange.com/dev/streams.html

To filter by date, you can use the fromDate and toDate parameters

For example to get the data between the 2016-06-04 and 2016-06-05 you can use:

GET /users/me/data/activity/steps?fromDate=2016-06-04T00%3A00%3A00.000Z,2016-06-05T00%3A00%3A00.000Z
Headers:
  Authorization: Bearer 9b02b1be-a5fe-4299-8b35-d9199bfdb471
  Accept: application/json

You can also paginate the data thanks to the dates and page size parameter, please look at the pagination documentation in https://datashare.orange.com/dev/pagination.html

You can user filters, for example to filter by source device or specific value.

For example if I want to filter to only have steps data from "source": "withings:ActivityTracker@2186606#0" I can use the following filter:

{
  "metadata": {
    "source": {"eq": "withings:ActivityTracker@2186606#0"}
  }
}

This JSON has to be URL encoded in a filter parameter in the GET call.

GET /users/me/data/timeseries/activity/steps?filter=%7B%22metadata%22%3A%20%7B%22source%22%3A%7B%22eq%22%3A%20%22withings%3AActivityTracker%402186606%230%22%20%7D%7D%7D
Headers:
  Authorization: Bearer 9b02b1be-a5fe-4299-8b35-d9199bfdb471
  Accept: application/json

You can combine filters with date searches.

More on filters in the documentation: https://datashare.orange.com/dev/filtering.html

Notifications API

Most of the time, the devices from your users won't send data continuously, but when the object synch or when there is an alert. For example, for the Gym Club, the users will probably synch their fitness bands every few hours, and will step on the weightscale once per day.

Instead of polling the API all the time to know when those new data are available, Data Share provides a notification API you can subscribe to. This way, every time there is a new data for a stream and a user you are interested in, and have his consent, you can be notified on the URL of your choose.

To subscribe to receive a notification, you need to use the following API:

PUT /users/me/subscriptions/{key} 
Headers:
  Authorization: Bearer 9b02b1be-a5fe-4299-8b35-d9199bfdb471
  Content-Type: application/json
  Accept: application/json
Body:
    {
      "filter": {
        "metadata": {
          "device": UDI
        }
      },
      "path": DATA_PATH,
      "url": "YOUR_CALLBACK"
    }

For example, to subscribe to receive a notification when new weight data is available, you will use the following API call:

PUT /users/me/subscriptions/user3-weight 
Headers:
  Authorization: Bearer 9b02b1be-a5fe-4299-8b35-d9199bfdb471
  Content-Type: application/json
  Accept: application/json
Body:
    {
      "path": "/me/body/weight",
      "url": "http://www.MyGreatGymClub.com/notification/User3/weight"
    }

As you can see, the metadata filter is optional, but can help you filter on devices.

The key parameter is required. it gives you a way to know which notification you are receiving. A subscription is unique based on the combination of key/client_id/user

You will then receive a notification when there is a new data available for the path you have chosen:

[
    {
        "key": "user3-weight",
        "startDate": "2016-06-06T17:13:45.000Z",
        "duration": null,
        "size": 1,
        "path": "/me/body/weight",
        "inlined": {
              "timestamp": "2016-06-06T17:13:45.000Z",
              "created": "2016-08-04T12:31:12.000Z",
              "model": "/me/body/weight",
              "location": null,
              "metadata": {
                "source": "fitbit:aria@YBCW8F4M5J8CQXOI"
              }
              "tags": [
                "owner:fa049f57"
              ]
              "value": {
                "value": 61.4,
                "duration": 60
              }
            }
    }
]

In case of a notification with multiple data in it (for example after synching a fitness tracker) the inlined object will be null and you will have a size and duration parameter to tell you the number of data that was received that you should now get. For example if you receive new steps count for your user:

[
        {
            "key": "user3-steps",
            "startDate": "2016-06-06T17:13:30.000Z",
            "duration": 900000,
            "size": 15,
            "path": "/me/activity/steps",
            "inlined": null
        }
    ]

In this particular notification you can note that the new data started on 2016-06-06T17:13:30.000Z with 15 new data (size) for a total duration of 15 minutes ("duration": 900000). Therefore you could make a GET request for new data between 2016-06-06T17:13:30.000Z and 2016-06-06T17:13:45.000Z with a pageSize=15 on the /me/activity/steps path to get this new data. In most of the cases, it will still be more interesting to get the new data since the last one you have (in case you missed a notification).

We also added some layers of security for you to know what we are sending the notification. See https://datashare.orange.com/dev/notification.html for more information.

Commands

Data Share gives you also great flexibility to send commands and actions to devices. You can turn lights off, change thermostat mode and temperature settings etc...

Normalization philosophy

We made the same commitment and work to normalize the commands in the same way we normalized the data. Therefore you can for example turn on or off a light bulb whatever the compatible brand is.

Sending commands

All commands are PUT requests. For example, you can choose to turn off all lights with:

PUT /users/me/commands/light/state
    Headers:
        Authorization: Bearer 9b02b1be-a5fe-4299-8b35-d9199bfdb471
        Content-Type: application/json
        Accept: application/json
    Body:
        {
        "params": {
            "on": false
        },
        "byUdi": [
          "UDI1",
          "UDI2",
          "UDI3",
          ]
        }
        }

This will work with any brand connected to Data Share

Every command you make will be added to the corresponding stream, with the mention of type: command and also the real vendor value command sent to the object manufacturer.

More about commands here: https://datashare.orange.com/dev/commands.html and on our swagger.

To go deeper...

You can find the full documentation for Data Share here: https://datashare.orange.com/dev/ and ask us questions through Orange Developer contact form