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)userTokenis the user's token to authenticate with thePDA.userDomainis the user'sPDA addressneeded to form the url to fetch the availableData Debits.succesfulCallBackis a callback. This is called when the request is successful with a type of@escaping (([DataDebitObject], String?) -> Void). The first parameter is an array ofDataDebitObject. This is the structure ofData Debits. More on that in the next section.The second parameter is an optional
String, the refreshed user token that thePDAreturns.failCallBackis a callback that is called when the request has failed. The type of the function is@escaping ((Data PlugError) -> Void).Data PlugErroris 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"
}
}
]dataDebitKeyis the data debit key, defined when creating theData Debit. It's unique across thePDA.dateCreatedis the date that thisData Debitwas created. The date is inISOformat asString.permissionsis thepermissionsinfo for thisData Debit. WhatURLsit has accessed, from which date to which date, etc.:dateCreatedis the date that thisData Bundlewas created. The date is inISOformat asString.purposeis a short description for theData Bundleexplaining its purpose. Optionalstartis the start date that thisData Bundlehas become active. The date is inISOformat. Optionalendis the start date that thisData Bundlewill surpass the assigned duration stated inperiod. The date is inISOformat. OptionalcancelAtPeriodEndis a flag indicating if the permissions will auto cancel when theData Debitwill endtermsUrlis aURLto show the user the terms and conditions for thisData Bundleperiodis the duration that theData Bundlecan be active. Value in seconds.activeindicates if theData Bundleis activeacceptedindicated if theData Bundlehas been acceptedbundleis the part where the permissions are defined. Like whatendpointsthisData Debitwill have access to, which fields from thatendpoint, aname, under what circumstances etc.:nameis name of thebundle. This has to be unique.bundleis aDictionaryof typeDictionary<String, DataOfferRequiredDataDefinitionBundleKeyV2>, it allows definition of multiple differentendpointsby giving a different name. This means that you can combine multiple and differentendpointseach with its own requirements:endpointsis an array ofDataOfferRequiredDataDefinitionBundleKeyEndpointsV2containing thePDA URLsto include, a desired `mapping` or `filtering` for the fields:endpointthe actualendpointthat you would like access to, for examplerumpel/profilemappingis the selected fields from thisendpointthat you would like to have in theData Debitfilterslets you filter a field by some requirements. For example, you can define something likeagebetween 18 and 35. Optional:fieldis the field that you would like to apply filtering totransformationis the transformation type to be done on the field. There are 4 different options: Optionalidentitykeep the value as-is, effect is the same as if transformation was not defineddatetimeExtractwithpart– extract part of a date from an ISO 8601 formatted date fieldtimestampExtractwithpart– extract part of a date from a UNIX timestamp date fieldsearchableconvert the field to searchable text. Must be used together with the find operator below 3.operatoris the type of the filtering. There are 4 different types with different structure each. You can read more into checking outHATOperatorclass inHatForiOShere. Optional:findallows you to search a particularString, field name:search. Also, you can nest moreoperators, field name:operatorcontainsallows you to search if a particular substring is contained into aString, field name:valueof typeBoolbetweenallows you to search if anIntis between 2 values namedupperandlowerintogether withvaluefield set to check if field is in (is contained by)value
linkseachendpointcan contain otherendpointobjects. Optional
orderBylets you define the field to order the data. Optionalorderinglets you define theorderingof the data.ascendingordescending. Optionallimitis anIntwhich lets you define how many data points you like from thisendpoint. Optional
conditionscheckbundlefor the structure. The purpose is that theData Bundlecan have some conditions, that have to be fulfilled first, attached to it in order to becomeactive. Optional
requestClientNameis the name of the client that created thisData DebitrequestClientUrlis theURLto the website of the clientrequestClientLogoUrlis aURLfor the logo of the clientrequestDescriptionis a description for theData Debit. OptionalrequestApplicationIdIf theData Debitis tied to anApplicationthis will be the application id. Otherwise it's nil. Optionalactiveindicates if theData Debitis activeacceptedindicates if theData Debithas been acceptedstartis the date that thisData Debithas started. The date is inISOformat asString. Optionalendis the date that thisData Debitwill end. The date is inISOformat asString. OptionalpermissionsActiveLatest activepermissions. Look atpermissions. OptionalpermissionsLatestLatestpermissions. Look atpermissions.
A request that has failed will look like this:
{
"error": "Not Authenticated",
"message": "Not Authenticated"
}erroris the error that has occurredmessageis a more descriptive message about theerrorthat 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 theHAT endpointyou would like access to.DataOfferRequiredDataDefinitionBundleKeyEndpointsV2also allows you to setup mapping and filtering if you wish. The minimum requirement is to specify the endpoint you want to use.bundleis a grouping of differentendpointsunder one category. You can define one category, with thenameparameter, but you can have multipleendpointsin thebundlesection. Note thatnamehas to be unique.dataDebitKeyis a key to the specificData debit. This has to be unique.purposeis a small description of the purpose for thisData Debitstartis the start date that thisData Debitcan become available. The date is inISOformat.periodis the duration that theData Debitwill be active in secondstermsUrlis theURLfor the terms and conditions for thisData DebitcancelAtPeriodEndis a bool flag for if theData Debitshould be cancelled with theperiodpassesrequestClientNameis the name of the client that created thisData DebitrequestClientUrlis theURLto the website of the clientrequestClientLogoUrlis aURLfor the logo of the clientbundleis 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"
}erroris the error that has occurredmessageis a more descriptive message about theerrorthat 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"hatAddressis the (fully qualified domain) address of the PDA, e.g.postman.hubat.netdataDebitIDis the data debit id that you want to approveappSchemeis the URL where the user should be sent to after completing authentication. Optional. For aniOSapplication that would probably be:\(applicationName)://successand has to be added in theinfo.plistfile of the project in Xcode as a known URL.You can read more here.
dataDebitHostis a string after the://part in the app url Scheme. For exampledataswift-sandbox://dataDebitHost. With thedataswift-sandbox://iOSwill launch your app. With thedataDebitHostyou will know that thisURLis specifically for theData 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)dataDebitKeyis the data debit key that we want the values from.userTokenis the user's token to authenticate with thePDA.userDomainis the user'sPDA addressused to form the url to fetch the values of theData Debit.succesfulCallBackis 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 optionalString, the refreshed user token that thePDAreturns.failCallBackis a callback that is called when the request has failed. The type of the function is@escaping ((Data PlugError, String?) -> Void).Data PlugErroris 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"
}erroris the error that has occurredmessageis a more descriptive message about theerrorthat has occurred
Last updated
Was this helpful?