Links

4. Data Debits

PDA Data I/O: Reading (Data Debits)

PDA Data Debits are the cornerstone of consented data exchange. It is the only way data can be retrieved from the PDA by anyone other than the owner and it enforces a strictly-defined format defining the specific data requested for the user to review and approve. Read more on the Data Debit API.

Fetch Data Debits

You can fetch the available Data Debits by using the next function:
HATDataDebitsService.getAvailableDataDebits(
userToken: userToken,
userDomain: userDomain,
succesfulCallBack: gotDataDebits,
failCallBack: failedGettingDataDebits)
  • userToken is the user's token to authenticate with the PDA.
  • userDomain is the user's PDA address needed to form the url to fetch the available Data Debits.
  • succesfulCallBack is a callback. This is called when the request is successful with a type of @escaping (([DataDebitObject], String?) -> Void). The first parameter is an array of DataDebitObject. This is the structure of Data Debits. More on that in the next section.
    The second parameter is an optional String, the refreshed user token that the PDA returns.
  • failCallBack is a callback that is called when the request has failed. The type of the function is @escaping ((Data PlugError) -> Void). Data PlugError
    is a custom object describing the errors that have occurred during the querying of the Data Plugs.
A successful response will have statusCode 200 and look like this:
[
{
"dataDebitKey": "97a0748f-bf81-4aaa-8f39-97ac2557d920",
"dateCreated": "2018-01-02T15:22:42+0000",
"permissions": [
{
"dateCreated": "2018-01-02T15:22:42+0000",
"purpose": "This Data Debit is in a legacy format, and the HAT App is unable to display all the information associated with it fully. This may include a logo, title and full description",
"start": "2018-01-02T15:23:02.000Z",
"period": 86400000,
"cancelAtPeriodEnd": true,
"termsUrl": "",
"bundle": {
"name": "97a0748f-bf81-4aaa-8f39-97ac2557d920",
"bundle": {
"iphone/locations": {
"endpoints": [
{
"endpoint": "iphone/locations",
"mapping": {
"accuracy": "accuracy",
"latitude": "latitude",
"longitude": "longitude",
"timestamp": "timestamp",
"lastUpdated": "lastUpdated",
"locations.accuracy": "locations.accuracy",
"locations.latitude": "locations.latitude",
"locations.longitude": "locations.longitude",
"locations.timestamp": "locations.timestamp"
},
"filters": []
}
]
},
"rumpel/locations/ios": {
"endpoints": [
{
"endpoint": "rumpel/locations/ios",
"mapping": {
"speed": "speed",
"course": "course",
"altitude": "altitude",
"latitude": "latitude",
"longitude": "longitude",
"dateSynced": "dateSynced",
"dateCreated": "dateCreated",
"dateCreatedLocal": "dateCreatedLocal",
"verticalAccuracy": "verticalAccuracy",
"horizontalAccuracy": "horizontalAccuracy"
},
"filters": []
}
]
}
}
},
"accepted": false,
"active": false,
"end": "2018-01-03T15:23:02.000Z"
}
],
"requestClientName": "Data Exchange",
"requestClientUrl": "https://dex.hubofallthings.com/",
"requestClientLogoUrl": "https://dex.hubofallthings.com/assets//images/dex.png",
"active": false,
"accepted": false,
"start": "2018-01-02T15:23:02.000Z",
"end": "2018-01-03T15:23:02.000Z",
"permissionsActive": null,
"permissionsLatest": {
"dateCreated": "2018-01-02T15:22:42+0000",
"purpose": "This Data Debit is in a legacy format, and the HAT App is unable to display all the information associated with it fully. This may include a logo, title and full description",
"start": "2018-01-02T15:23:02.000Z",
"period": 86400000,
"cancelAtPeriodEnd": true,
"termsUrl": "",
"bundle": {
"name": "97a0748f-bf81-4aaa-8f39-97ac2557d920",
"bundle": {
"iphone/locations": {
"endpoints": [
{
"endpoint": "iphone/locations",
"mapping": {
"accuracy": "accuracy",
"latitude": "latitude",
"longitude": "longitude",
"timestamp": "timestamp",
"lastUpdated": "lastUpdated",
"locations.accuracy": "locations.accuracy",
"locations.latitude": "locations.latitude",
"locations.longitude": "locations.longitude",
"locations.timestamp": "locations.timestamp"
},
"filters": []
}
]
},
"rumpel/locations/ios": {
"endpoints": [
{
"endpoint": "rumpel/locations/ios",
"mapping": {
"speed": "speed",
"course": "course",
"altitude": "altitude",
"latitude": "latitude",
"longitude": "longitude",
"dateSynced": "dateSynced",
"dateCreated": "dateCreated",
"dateCreatedLocal": "dateCreatedLocal",
"verticalAccuracy": "verticalAccuracy",
"horizontalAccuracy": "horizontalAccuracy"
},
"filters": []
}
]
}
}
},
"accepted": false,
"active": false,
"end": "2018-01-03T15:23:02.000Z"
}
}
]
  • dataDebitKey is the data debit key, defined when creating the Data Debit. It's unique across thePDA.
  • dateCreated is the date that this Data Debit was created. The date is in ISO format as String.
  • permissions is the permissions info for this Data Debit. What URLs it has accessed, from which date to which date, etc.:
    1. 1.
      dateCreated is the date that this Data Bundle was created. The date is in ISO format as String.
    2. 2.
      purpose is a short description for the Data Bundle explaining its purpose. Optional
    3. 3.
      start is the start date that this Data Bundle has become active. The date is in ISO format. Optional
    4. 4.
      end is the start date that this Data Bundle will surpass the assigned duration stated in period. The date is in ISO format. Optional
    5. 5.
      cancelAtPeriodEnd is a flag indicating if the permissions will auto cancel when the Data Debit will end
    6. 6.
      termsUrl is a URL to show the user the terms and conditions for this Data Bundle
    7. 7.
      period is the duration that the Data Bundle can be active. Value in seconds.
    8. 8.
      active indicates if the Data Bundle is active
    9. 9.
      accepted indicated if the Data Bundle has been accepted
    10. 10.
      bundle is the part where the permissions are defined. Like what endpoints this Data Debit will have access to, which fields from that endpoint, a name, under what circumstances etc.:
      1. 1.
        name is name of the bundle. This has to be unique.
      2. 2.
        bundle is a Dictionary of type Dictionary<String, DataOfferRequiredDataDefinitionBundleKeyV2>, it allows definition of multiple different endpoints by giving a different name. This means that you can combine multiple and different endpoints each with its own requirements:
        1. 1.
          endpoints is an array of DataOfferRequiredDataDefinitionBundleKeyEndpointsV2 containing the PDA URLs to include, a desired `mapping` or `filtering` for the fields:
          1. 1.
            endpoint the actual endpoint that you would like access to, for example rumpel/profile
          2. 2.
            mapping is the selected fields from this endpoint that you would like to have in the Data Debit
          3. 3.
            filters lets you filter a field by some requirements. For example, you can define something like age between 18 and 35. Optional:
            1. 1.
              field is the field that you would like to apply filtering to
            2. 2.
              transformation is the transformation type to be done on the field. There are 4 different options: Optional
              1. 1.
                identity keep the value as-is, effect is the same as if transformation was not defined
              2. 2.
                datetimeExtract with part – extract part of a date from an ISO 8601 formatted date field
              3. 3.
                timestampExtract with part – extract part of a date from a UNIX timestamp date field
              4. 4.
                searchable convert the field to searchable text. Must be used together with the find operator below 3. operator is the type of the filtering. There are 4 different types with different structure each. You can read more into checking out HATOperator class in HatForiOS here. Optional:
                1. 1.
                  find allows you to search a particular String, field name: search. Also, you can nest more operators, field name: operator
                2. 2.
                  contains allows you to search if a particular substring is contained into a String, field name: value of type Bool
                3. 3.
                  between allows you to search if an Int is between 2 values named upper and lower
                4. 4.
                  in together with value field set to check if field is in (is contained by) value
          4. 4.
            links each endpoint can contain other endpoint objects. Optional
        2. 2.
          orderBy lets you define the field to order the data. Optional
        3. 3.
          ordering lets you define the ordering of the data. ascending or descending. Optional
        4. 4.
          limit is an Int which lets you define how many data points you like from this endpoint. Optional
    11. 11.
      conditions check bundle for the structure. The purpose is that the Data Bundle can have some conditions, that have to be fulfilled first, attached to it in order to become active. Optional
  • requestClientName is the name of the client that created this Data Debit
  • requestClientUrl is the URL to the website of the client
  • requestClientLogoUrl is a URL for the logo of the client
  • requestDescription is a description for the Data Debit. Optional
  • requestApplicationId If the Data Debit is tied to an Application this will be the application id. Otherwise it's nil. Optional
  • active indicates if the Data Debit is active
  • accepted indicates if the Data Debit has been accepted
  • start is the date that this Data Debit has started. The date is in ISO format as String. Optional
  • end is the date that this Data Debit will end. The date is in ISO format as String. Optional
  • permissionsActive Latest active permissions. Look at permissions. Optional
  • permissionsLatest Latest permissions. Look at permissions.
A request that has failed will look like this:
{
"error": "Not Authenticated",
"message": "Not Authenticated"
}
  • error is the error that has occurred
  • message is a more descriptive message about the error that has occurred

Create Data Debit

You can also create a Data Debit by using the function below:
let endpoint = DataOfferRequiredDataDefinitionBundleKeyEndpointsV2(endpoint: "rumpel/profile")
let bundle = DataOfferRequiredDataDefinitionObjectV2(
name: "test1",
bundle: ["rumpel/profile": DataOfferRequiredDataDefinitionBundleKeyV2(endpoints: [endpoint])])
let dataDebitToCreate = DataDebitCreationObject(
dataDebitKey: "test1",
purpose: "none",
start: "2018-11-14T23:51:40+0000",
period: 432000000,
termsUrl: "none",
cancelAtPeriodEnd: false,
requestClientName: "none",
requestClientUrl: "none",
requestClientLogoUrl: "none",
bundle: bundle)
  • endpointis the HAT endpoint you would like access to. DataOfferRequiredDataDefinitionBundleKeyEndpointsV2 also allows you to setup mapping and filtering if you wish. The minimum requirement is to specify the endpoint you want to use.
  • bundle is a grouping of different endpoints under one category. You can define one category, with the name parameter, but you can have multiple endpoints in the bundle section. Note that name has to be unique.
  • dataDebitKey is a key to the specific Data debit. This has to be unique.
  • purpose is a small description of the purpose for this Data Debit
  • start is the start date that this Data Debit can become available. The date is in ISO format.
  • period is the duration that the Data Debit will be active in seconds
  • termsUrl is the URL for the terms and conditions for this Data Debit
  • cancelAtPeriodEnd is a bool flag for if the Data Debit should be cancelled with the period passes
  • requestClientName is the name of the client that created this Data Debit
  • requestClientUrl is the URL to the website of the client
  • requestClientLogoUrl is a URL for the logo of the client
  • bundle is the description of what endpoints we want to have access to
A successful response will have statusCode 201 and look like this:
{
"dataDebitKey": "test1",
"dateCreated": "2018-11-14T23:51:40+0000",
"permissions": [
{
"dateCreated": "2018-11-14T23:51:40+0000",
"purpose": "none",
"start": "2018-11-14T23:51:40+0000",
"period": 432000000,
"cancelAtPeriodEnd": false,
"termsUrl": "none",
"conditions": {
"name": "data-debit-id-test-name",
"bundle": {
"test": {
"endpoints": [
{
"endpoint": "rumpel/profile"
}
]
}
}
},
"bundle": {
"name": "data-debit-id-test1",
"bundle": {
"test": {
"endpoints": [
{
"endpoint": "rumpel/profile"
}
]
}
}
},
"accepted": false,
"active": false,
"end": null
}
],
"requestClientName": "none",
"requestClientUrl": "none",
"requestClientLogoUrl": "none",
"requestDescription": "none",
"active": false,
"accepted": false,
"start": "2018-04-18T09:26:57.000Z",
"end": null,
"permissionsActive": null,
"permissionsLatest": {
"dateCreated": "2018-11-14T23:51:40+0000",
"purpose": "none",
"start": "2018-11-14T23:51:40+0000",
"period": 432000000,
"cancelAtPeriodEnd": false,
"termsUrl": "none",
"conditions": {
"name": "data-debit-id-test-name",
"bundle": {
"test": {
"endpoints": [
{
"endpoint": "rumpel/profile"
}
]
}
}
},
"bundle": {
"name": "data-debit-id-test1",
"bundle": {
"test": {
"endpoints": [
{
"endpoint": "rumpel/profile"
}
]
}
}
},
"accepted": false,
"active": false,
"end": null
}
}
For an explanation of what the above structure means, read here.
A failed request will look like this:
{
"error": "Not Authenticated",
"message": "Not Authenticated"
}
  • error is the error that has occurred
  • message is a more descriptive message about the error that has occurred

Approve Data Debits

Not all apps can directly approve Data Debits. This has to do with the permissions of the apps. Currently, only HAT App and web Rumpel can approve Data Debits. Due to the restrictions this guide will explain how to use the generic way of doing it, that will work on all apps. To approve a Data Debit you have to open the following URL in Safari:
"https://\(hatAddress)/#/data-debit/\(dataDebitID)/quick-confirm?redirect=\(appScheme)://\(dataDebitHost)&fallback=\(appScheme)/dataDebitFailure"
  • hatAddress is the (fully qualified domain) address of the PDA, e.g. postman.hubat.net
  • dataDebitID is the data debit id that you want to approve
  • appScheme is the URL where the user should be sent to after completing authentication. Optional. For an iOSapplication that would probably be: \(applicationName)://success and has to be added in the info.plist file of the project in Xcode as a known URL.
    You can read more here.
  • dataDebitHost is a string after the :// part in the app url Scheme. For example dataswift-sandbox://dataDebitHost. With thedataswift-sandbox:// iOS will launch your app. With the dataDebitHost you will know that this URL is specifically for the Data Debits.
The process is the same as when logging the user in. Safari will open, user will have to complete their password, and then one of the 2 redirect URL will be called, depending if the request was successful or has failed for some reason. The app should know how to handle both scenarios. If you aren't sure how to do it you can read here for how to redirect user to HAT login.

Getting Data Debit values

You can fetch the values of a specific Data Debit by using the next function:
HATDataDebitsService.getDataDebitValues(
dataDebitKey: dataDebitKey,
userToken: userToken,
userDomain: userDomain,
succesfulCallBack: gotDataDebits,
failCallBack: failedGettingDataDebits)
  • dataDebitKey is the data debit key that we want the values from.
  • userToken is the user's token to authenticate with the PDA.
  • userDomain is the user's PDA address used to form the url to fetch the values of the Data Debit.
  • succesfulCallBack is a callback function that is called when the request is successful, with a type of @escaping ((DataDebitValuesObject, String?) -> Void).
    This is the structure of Data Debit Values. More on that in the next section. The second parameter is an optional String, the refreshed user token that the PDA returns.
  • failCallBack is a callback that is called when the request has failed. The type of the function is @escaping ((Data PlugError, String?) -> Void). Data PlugError
    is a custom object describing the errors that have occurred during the querying of the Data Plugs. The second parameter is the dataDebitKey.
A successful response will have statusCode 200 and look like this:
{
"bundle": {
"profile": [
{
"endpoint": "rumpel/profile",
"recordId": "137e0409-effc-454f-b1f0-56fe87ad7762",
"data": {
"name": "",
"nick": "",
"photo_url": "https://postman.hubat.net/api/v2.6/files/content/rumpel1537454603415.jpg"
}
}
],
"notables": [
{
"endpoint": "rumpel/notablesv1",
"recordId": "d1d26a7d-0c7f-4ba2-8caa-13a4b5671444",
"data": {
"kind": "note",
"author": {
"name": "",
"phata": "postman.hubat.net",
"nickname": "",
"photo_url": ""
},
"shared": true,
"message": "oooo",
"shared_on": [
"phata"
],
"created_time": "2018-11-08T11:24:58Z",
"updated_time": "2018-11-08T11:24:58Z"
}
}
]
}
}
Inside the bundle there are 2 different values: profile and notables. Those 2 values are Arrays that contain the actual data for each endpoint specified when this Data Debit was created. In this example the 2 structures are the profile and notables.
A request that has failed will look like this:
{
"error": "Not Authenticated",
"message": "Not Authenticated"
}
  • error is the error that has occurred
  • message is a more descriptive message about the error that has occurred