REST API
Data Handler API allows clients (browsers, devices etc) to interact with Profile Cloud's backend. The API complies with HTTP/1.1 protocol specifications and follows the REST architectural style as much as possible. This document explains the usage of the API and the related data structures.
IMPORTANT NOTE: This article is not being maintained and is scheduled for sunsetting by end of 2017. Readers are encouraged to use the new API reference here: http://docs.innomdc.com/
If new profiles are created from a device (web, mobile device or any other connection that is not a secure server-to-server connection) then then UUIDs should be chosen or profile IDs should otherwise chosen from a keyspace with large number of random bits (for instance, web library generates keys with 32 characters a-z0-9, example eser4xdjclozet5rrtqwyfz9rnrjerkg).
A profile has three main parts, namely, "Sessions", "Attributes" and "Services". Each of these in turn have their own structures. The structure of a profile can be represented by the following JSON structure. Please read the Profile Format Specification document for more details about the profile.
{ "id":"<profileId>", "version":"1.0", "createdAt":<timestamp milliseconds>, "sessions":[ { "id":"<sessionId>", "createdAt":<timestamp milliseconds>, "collectApp":"<collect app name>", "section":"<section name>", "data":{ "key":"value" }, "services":[ { "id":"geo", "data":{ "countryCode":0, "countryName":"<a country>", "region":"<a region>", "city":"<a city>", "postalCode":null, "latitude":0.0, "longitude":0.0, "dmaCode":0, "areaCode":0, "metroCode":0 } } ], "events":[ { "id":"<eventId>", "createdAt":<Timestamp milliseconds>, "definitionId":"<definitionId>", "data":{ "key":"value" }, "services":[ ] } ] } ], "attributes":[ { "collectApp": "<collect app name>", "section": "<section name>", "data": { "key": "value" } "services": [ ] } ], "services":[ ] } |
The table below describes the profile in further detail
Key | Type | Required | Description |
---|---|---|---|
attributes | Array of attributes | No | An array of attributes |
createdAt | Number | No | Represents the time this profile was created. createdAt can be specified by the client. If no createdAt is specified, the server will add a createdAt value. The createdAt value can never be modified and all future createdAt values will be ignored. This value will be interpreted in milliseconds. |
id | String | Yes | Represents a profile. The API expects the "id" to be created by the caller. The "id" should be unique |
mergedProfiles | Array of strings | No | Id of profiles merged into this profile. Profile merging is a special function that combines multiple temporary profiles into a single canonical profile. Please read the Merge section for more details. |
services | Array of services | No | An array of services. Some services such as "geo location" will be included in the profile by the API. |
sessions | Array of sessions | No | An array of sessions. |
version | String | No | Represents the version of profile JSON. The API does not expect it from the caller and will ignore it if supplied. |
A new profile can be created from either the profiles resource or profile resource.
- A new profile can be created by calling the url /v1/companies/<companyId>/buckets/<bucketId>/profiles. The method should be POST and a successful profile creation will result in a response status 201 CREATED.
- This can also be done by calling the url /v1/companies/<companyId>/buckets/<bucketId>/profiles/<profileId>. The method should be POST and a successful profile creation will result in a response status 201 CREATED.
Required permission profile.create
Request Headers
Header | Required | Acceptable Value(s) | Description |
---|---|---|---|
Content-type | Yes | application/json | |
Accept | Yes | application/json, application/javascript, image/* | Image response will return a 1x1 pixel result. |
Content-encoding | No | gzip | Caller can send a gzipped request to the API and set the Content-encoding as gzip. |
Accept-encoding | No | gzip | Caller can request a gzipped response from the API and set the Accept-encoding as gzip. |
Query Parameters
Key | Required | Description |
---|---|---|
app_key | No | An app key refers to a collectApp. If an app key is specified, the profile data is added as the collectApp corresponding to that app key. If no app key is specified then profile data is added using the default collectApp "web" |
max_return_size | No | Max return size refers to the size of the profile to be returned to the caller. If no max_return_size is specified, the profile of size 500 is returned to the caller. Please read the documentation about profile trimming to learn more about how the profile is trimmed to the specified size. |
max_return_events | No | Max return events refers to the the total number of events to be returned to the caller. The returned events can be distributed over several sessions. The max_return_events can be less than expected in the response if the profile does not have enough events or if the profile becomes larger than the max_return_size. |
Response Headers
Header | Description |
---|---|
Location | Absolute url of the newly created resource. |
Content-type | Content type of the response body. |
Vary | Will contain the Accept-encoding header. |
Content-encoding | Will contain encoding "gzip". |
Example 1: A typical request and response body
|
|
Example 2: A minimal request and response body
|
Minimal Response Body
|
A profile can be updated by calling the url /v1/companies/<companyId>/buckets/<bucketId>/profiles/<profileId>. The method should be POST and a successful profile update will result in a response status 200 OK. The update to a profile is a partial update and any portion of the profile namely "session", "attributes" or "services" can be updated. The resource still takes a profile representation as request body. Sessions, attributes or services in this profile will by inserted into the existing profile. If any session (or events inside a session), attribute or service matches with an existing session (or events inside the session), attribute or service, the exiting will be updated to the new with priority to the new values.
Required permission profile.update
Request Headers
Header | Required | Acceptable Value(s) | Description |
---|---|---|---|
Content-type | Yes | application/json | |
Accept | Yes | application/json, application/javascript, image/* | Image response will return a 1x1 pixel result. |
Content-encoding | No | gzip | Caller can send a gzipped request to the API and set the Content-encoding as gzip. |
Accept-encoding | No | gzip | Caller can request a gzipped response from the API and set the Accept-encoding as gzip. |
Query Parameters
Key | Required | Description |
---|---|---|
app_key | No | An app key refers to a collectApp. If an app key is specified, the profile data is added as the collectApp corresponding to that app key. If no app key is specified then profile data is added using the default collectApp "web". Similarly, the response will return the collectApp data corresponding to the app key. The returned data will additionally be filtered though any whitelists and/or blacklists configured for this collect app. If no collect app is specified, data and; blacklist and whitelist configurations of collectApp "web" will be used. |
max_return_size | No | Max return size refers to the size of the profile to be returned to the caller. If no max_return_size is specified, the profile of size 500 is returned to the caller. Please read the documentation about profile trimming to learn more about how the profile is trimmed to the specified size. |
max_return_events | No | Max return events refers to the the total number of events to be returned to the caller. The returned events can be distributed over several sessions. The max_return_events can be less than expected in the response if the profile does not have enough events or if the profile becomes larger than the max_return_size. |
Response Headers
Header | Description |
---|---|
Location | Absolute url of the newly created resource. |
Content-type | Content type of the response body. |
Vary | Will contain the Accept-encoding header. |
Content-encoding | Will contain encoding "gzip". |
Example 1: Request and response body when updating existing profile with a new session
Assume that a profile represented with the following JSON exists
{ "id":"<profileId>", "createdAt":<timestamp milliseconds>, "sessions":[ { "id":"<sessionId>", "createdAt":<timestamp milliseconds>, "collectApp":"<collect app name>", "section":"<section name>", "data":{ "key":"value" }, "services":[ { "id":"geo", "data":{ "countryCode":0, "countryName":"<a country>", "region":"<a region>", "city":"<a city>", "postalCode":null, "latitude":0.0, "longitude":0.0, "dmaCode":0, "areaCode":0, "metroCode":0 } } ], "events":[ { "id":"<eventId>", "createdAt":<Timestamp milliseconds>, "definitionId":"<definitionId>", "data":{ "key":"value" } } ] } ] } |
Then an update is issued on this profile with the following JSON in request body
{ "id":"<profileId>", "sessions":[ { "id":"<sessionId 1>", "createdAt":<timestamp milliseconds 1>, "collectApp":"<collect app name 1>", "section":"<section name 1>", "data":{ "key1":"value1" }, "events":[ { "id":"<eventId 1>", "createdAt":<Timestamp milliseconds 1>, "definitionId":"<definitionId 1>", "data":{ "key1":"value1" } } ] } ] } |
The resultant JSON for this request will be
{ "profile":{ "id":"<profileId>", "version":"1.0", "createdAt":<timestamp milliseconds>, "sessions":[ { "id":"<sessionId>", "createdAt":<timestamp milliseconds>, "collectApp":"<collect app name>", "section":"<section name>", "data":{ "key":"value" }, "services":[ { "id":"geo", "data":{ "countryCode":0, "countryName":"Sweden", "region":"26", "city":"Stockholm", "postalCode":null, "latitude":59.333298, "longitude":18.050003, "dmaCode":0, "areaCode":0, "metroCode":0 } } ], "events":[ { "id":"<eventId 1>", "createdAt":<timestamp milliseconds>, "definitionId":"<definitionId>", "data":{ "key":"value" }, "services":[ ] } ] }, { "id":"<sessionId 1>", "createdAt":<timestamp milliseconds 1>, "collectApp":"<collect app name 1>", "section":"<section name 1>", "data":{ "key1":"value1" }, "services":[ { "id":"geo", "data":{ "countryCode":0, "countryName":"Sweden", "region":"26", "city":"Stockholm", "postalCode":null, "latitude":59.333298, "longitude":18.050003, "dmaCode":0, "areaCode":0, "metroCode":0 } } ], "events":[ { "id":"<eventId 1>", "createdAt":<timestamp milliseconds 1>, "definitionId":"<definitionId 1>", "data":{ "key1":"value1" }, "services":[ ] } ] } ], "attributes":[ ], "services":[ ], "mergedProfiles":[ ] }, "links":{ "self":"http://<host>/v1/companies/<companyId>/buckets/<bucketId>/profiles/<profileId>" } } |
Example 2: Request and response body when updating existing profile with an existing session but different event
Assume that a profile represented with the following JSON exists
{ "id":"<profileId>", "createdAt":<timestamp milliseconds>, "sessions":[ { "id":"<sessionId>", "createdAt":<timestamp milliseconds>, "collectApp":"<collect app name>", "section":"<section name>", "data":{ "key":"value" }, "services":[ { "id":"geo", "data":{ "countryCode":0, "countryName":"<a country>", "region":"<a region>", "city":"<a city>", "postalCode":null, "latitude":0.0, "longitude":0.0, "dmaCode":0, "areaCode":0, "metroCode":0 } } ], "events":[ { "id":"<eventId>", "createdAt":<Timestamp milliseconds>, "definitionId":"<definitionId>", "data":{ "key":"value" } } ] } ] } |
Then an update is issued on this profile with the following JSON in request body
{ "id":"<profileId>", "sessions":[ { "id":"<sessionId>", "createdAt":<timestamp milliseconds 1>, "collectApp":"<collect app name>", "section":"<section name>", "data":{ "key":"value1" "key1":"value1" }, "events":[ { "id":"<eventId 1>", "createdAt":<Timestamp milliseconds 1>, "definitionId":"<definitionId 1>", "data":{ "key1":"value1" } } ] } ] } |
The resultant JSON for this request will be
|
Example 3: Request and response body when updating existing profile with an existing session and existing event
Assume that a profile represented with the following JSON exists
{ "id":"<profileId>", "createdAt":<timestamp milliseconds>, "sessions":[ { "id":"<sessionId>", "createdAt":<timestamp milliseconds>, "collectApp":"<collect app name>", "section":"<section name>", "data":{ "key":"value" }, "services":[ { "id":"geo", "data":{ "countryCode":0, "countryName":"<a country>", "region":"<a region>", "city":"<a city>", "postalCode":null, "latitude":0.0, "longitude":0.0, "dmaCode":0, "areaCode":0, "metroCode":0 } } ], "events":[ { "id":"<eventId>", "createdAt":<Timestamp milliseconds>, "definitionId":"<definitionId>", "data":{ "key":"value" } } ] } ] } |
Then an update is issued on this profile with the following JSON in request body
{ "id":"<profileId>", "sessions":[ { "id":"<sessionId>", "createdAt":<timestamp milliseconds 1>, "collectApp":"<collect app name>", "section":"<section name>", "data":{ "key":"value1" "key1":"value1" }, "events":[ { "id":"<eventId>", "createdAt":<Timestamp milliseconds 1>, "definitionId":"<definitionId 1>", "data":{ "key1":"value1" } } ] } ] } |
The resultant JSON for this request will be
{ "profile":{ "id":"<profileId>", "version":"1.0", "createdAt":<timestamp milliseconds>, "sessions":[ { "id":"<sessionId>", "createdAt":<timestamp milliseconds>, "collectApp":"<collect app name>", "section":"<section name>", "data":{ "key":"value1", "key1":"value1" }, "services":[ { "id":"geo", "data":{ "countryCode":0, "countryName":"Sweden", "region":"26", "city":"Stockholm", "postalCode":null, "latitude":59.333298, "longitude":18.050003, "dmaCode":0, "areaCode":0, "metroCode":0 } } ], "events":[ { "id":"<eventId>", "createdAt":<timestamp milliseconds>, "definitionId":"<definitionId 1>", "data":{ "key1":"value1" }, "services":[ ] } ] } ], "attributes":[ ], "services":[ ], "mergedProfiles":[ ] }, "links":{ "self":"http://<host>/v1/companies/<companyId>/buckets/<bucketId>/profiles/<profileId>" } } |
An existing profile can be retrieved by calling the url /v1/companies/<companyId>/buckets/<bucketId>/profiles/<profileId>. The method should be GET and a successful profile get will result in a response status 200 OK.
Required permission profile.read
Request Headers
Header | Required | Acceptable Value(s) | Description |
---|---|---|---|
Accept | Yes | application/json, application/javascript, image/* | Image response will return a 1x1 pixel result. |
Accept-encoding | No | gzip | Caller can request a gzipped response from the API and set the Accept-encoding as gzip. |
Query Parameters
Key | Required | Description |
---|---|---|
app_key | No | An app key refers to a collectApp. If an app key is specified, only the profile data that was added as the collectApp and the data of those apps that are allowed through the configured whitelist and/or blacklist will be retrieved. If no app key is specified then collectApp web along with its configured whitelist and/or blacklist will be used. |
max_return_size | No | Max return size refers to the size of the profile to be returned to the caller. If no max_return_size is specified, the profile of size 500 is returned to the caller. Please read the documentation about profile trimming to learn more about how the profile is trimmed to the specified size. |
max_return_events | No | Max return events refers to the the total number of events to be returned to the caller. The returned events can be distributed over several sessions. The max_return_events can be less than expected in the response if the profile does not have enough events or if the profile becomes larger than the max_return_size. |
Response Headers
Header | Description |
---|---|
Content-type | Content type of the response body. |
Vary | Will contain the Accept-encoding header. |
Content-encoding | Will contain encoding "gzip". |
Example: Get an existing profile
{ "profile":{ "id":"<profileId>", "version":"1.0", "createdAt":<timestamp milliseconds>, "sessions":[ { "id":"<sessionId>", "createdAt":<timestamp milliseconds>, "collectApp":"<collect app name>", "section":"<section name>", "data":{ "key":"value" }, "services":[ { "id":"geo", "data":{ "countryCode":0, "countryName":"<a country>", "region":"<a region>", "city":"<a city>", "postalCode":null, "latitude":0.0, "longitude":0.0, "dmaCode":0, "areaCode":0, "metroCode":0 } } ], "events":[ { "id":"<eventId>", "createdAt":<timestamp milliseconds>, "definitionId":"<definitionId>", "data":{ "key":"value" }, "services":[ ] } ] } ], "attributes":[ { "collectApp": "<collect app name>", "section": "<section name>", "data": { "key": "value" } } ], "services":[ ] }, "links":{ "self":"http://<hostname>/v1/companies/<companyId>/buckets/<bucketId>/profiles/<profileId>" } } |
Merge profiles
Merge profiles is a special methodology that can merge two or more profiles (a.k.a temporary profiles) into a single profile (a.k.a canonical profile). The merged profiles are linked to the canonical profile i.e. a GET on a profile that was merged into the canonical profile will return the canonical profile. The API will create a new canonical profile if one does not exist at the time of the merge. However, a 404 Not Found will be returned if a the temporary profile being merged does not exist.
Profiles can be merged by making a request to url /v1/companies/<companyId>/buckets/<bucketId>/profiles/<profileId> where the canonical profile is represented by the <profileId>. The request should be POST and a successful merge with result in either a 201 CREATED if the merge results in the creation of a canonical profile or 200 OK if temporary profiles are merged into an existing canonical profile. Merge is analogous to update and both the processes can be triggered on a profile at the same time. For a profile to be merged with another, the profile representation posted in the request should contain an array with the key "mergedProfiles". The array can contain any number of temporary profile Ids that should be merged into the canonical profile.
The merge updates the canonical profile with the session (or events in the session), attributes and services of the temporary profile but prioritises sessions (or events in the session), attributes and services of the canonical profile over temporary profiles in case of a match.
NOTE: Merging is not reversible, please consult with your implementation consultant and account manager before performing profile merging on your account's production environment for help with best practices
Required permission profile.merge
Request Headers
Header | Required | Acceptable Value(s) | Description |
---|---|---|---|
Content-type | Yes | application/json | |
Accept | Yes | application/json, application/javascript, image/* | Image response will return a 1x1 pixel result. |
Content-encoding | No | gzip | Caller can send a gzipped request to the API and set the Content-encoding as gzip. |
Accept-encoding | No | gzip | Caller can request a gzipped response from the API and set the Accept-encoding as gzip. |
Query Parameters
Key | Required | Description |
---|---|---|
app_key | No | An app key refers to a collectApp. If an app key is specified, the profile data is added as the collectApp corresponding to that app key. If no app key is specified then profile data is added using the default collectApp "web". Similarly, the response will return the collectApp data corresponding to the app key. The returned data will additionally be filtered though any whitelists and/or blacklists configured for this collect app. If no collect app is specified, data and; blacklist and whitelist configurations of collectApp "web" will be used. |
max_return_size | No | Max return size refers to the size of the profile to be returned to the caller. If no max_return_size is specified, the profile of size 500 is returned to the caller. Please read the documentation about profile trimming to learn more about how the profile is trimmed to the specified size. |
max_return_events | No | Max return events refers to the the total number of events to be returned to the caller. The returned events can be distributed over several sessions. The max_return_events can be less than expected in the response if the profile does not have enough events or if the profile becomes larger than the max_return_size. |
Response Headers
Header | Description |
---|---|
Location | Absolute url of the newly created canonical profile resource if the merge resulted in the creation of a canonical profile. |
Content-type | Content type of the response body. |
Vary | Will contain the Accept-encoding header. |
Content-encoding | Will contain encoding "gzip". |
Example: Merging a temporary profile into a canonical profile
{
"id":"<canonicalProfileId>",
"mergedProfiles":[
"<temporaryProfileId>"
]
}
|
{ "profile":{ "id":"<canonicalProfileId>", "version":"1.0", "createdAt":<timestamp milliseconds>, "mergedProfiles":[ "<temporaryProfileId>" ] }, "links":{ "self":"http://<hostname>/v1/companies/<companyId>/buckets/<bucketId>/profiles/<canonicalProfileId>" } } |
A profile can be deleted by calling the url /v1/companies/<companyId>/buckets/<bucketId>/profiles/<profileId>.
The method should be DELETE and a successful profile deletion will result in a response status 204 NO CONTENT. A profile can be deleted using its temporary profile id(s) or its canonical profile id. Deleting a profile with multiple id(s) (temporary and canonical) will result in the removal of all those ids and corresponding data. These id(s) can be reused to create new profiles.
Required permission profile.delete
Query Parameters
Key | Required | Description |
---|---|---|
app_key | No | An app key refers to the app which has the permission to delete profiles. If app key is is not specified that "web" app should have the permission to delete profiles. |