API Version 3
You're seeing the newest version of System of Record API. Looking for the old one? Click here.
In order to use this version of the API, please add the value "application/vnd.fa.v3"
to the Accept
header of the request.
Endpoint and Authentication
Please refer to the API overview section to get the API endpoint, query format and authentication process
Retrieve Attribute Values
Retrieve Customer Attribute Values
This API returns all the Customer Attribute values of the given Customer Profile, for a specific System of Record. It concerns both custom and SDK SORs. Please note that this API is not adapted to massive retrieving that should rather use exports API.
GET /api/attribute_values?sor_id=sor_id&customer_id=c_id&customer_type=type&with_validity_dates
Query parameter
Property | Type | Description | Default |
---|---|---|---|
sor_id | string | The identifier of the Custom or SDK System of Record to fetch the results from. | required |
customer_id | string | Customer id to retrieve the profile. If your customer id is an e-mail, for instance, don't forget to encode both the @ and . signs in the URL to ensure the APIs receive the full parameter, e.g. me@gmail.com becomes me%40gmail%2Ecom . |
required |
customer_type | string | Filter by the type of customer_id, user_id or device_id . If the sor_id param does not correspond to a Custom SOR, and the customer_type is device_id , the API returns instead the attributes for the last user that used the device provided. |
required |
with_validity_dates | boolean | Request the values with the latest dates they became valid, or without these. If this value is true , the format of the response will be adapted. For set attributes, the date corresponds to the last update made globally to the set. |
false |
Response
Without requesting dates ( with_validity_dates=false
):
Status: 200 OK
{
"success": true,
"result":
{
"customer_id": "maximillian",
"customer_id_type": "user_id",
"attribute_values": {
"first_name": "maximillian",
"last_name": "weber",
"contract_type": "Premium",
"client_type": null,
"hobbies": [],
"favorite_team": "France",
"languages": ["French", "English"],
"city": null,
"region": null,
}
}
}
With the validity dates ( with_validity_dates=true
):
Status: 200 OK
{
"success": true,
"result":
{
"customer_id": "maximillian",
"customer_id_type": "user_id",
"attribute_values": {
"first_name": {
"value": "maximillian",
"since": "2017-10-25T23:48:46:299Z"
},
"last_name": {
"value": "weber",
"since": "2017-10-25T23:48:46:299Z"
},
"contract_type": {
"value": "Premium",
"since": "2017-11-13T06:55:21:437Z"
},
"client_type": {
"value": null,
"since": null
},
"hobbies": {
"value": [],
"since": null,
},
"languages": {
"value": ["French", "English"],
"since": "2017-12-05T11:34:51:701Z",
},
"city": {
"value": null,
"since": null
},
"region": {
"value": null,
"since": null
},
}
}
}
Export Customer Profiles
This API exports a batch of customer profiles along with the associated attributes values.
GET /api/customer_profiles/export?sor_identifiers=sor_identifiers&customer_id_type=customer_id_type&attribute_keys=attribute_keys&updated_since=updated_since
!!! Using updated_since
query parameter is recommended to speed up the processing time.
By using this parameter, the API returns only the list of attribute values that changed since the specified date.
The other filters and pagination are also used to limit the amount of profiles for each request.
Query parameters
Property | Type | Description | Default |
---|---|---|---|
customer_id_type | string | Filter by the type of customer id, options: user_id , device_id |
- |
customer_ids | string | List of customer IDs, separated by commas, used to filter the customer profiles returned in the API output | - |
sor_identifiers | string | List of SOR identifiers separated by commas, used to define the Systems of Records to return for each profile in the output | - |
attribute_keys | string | List of attribute keys separated by commas, used to filter the SOR keys to return for each profile in the API output: only SORs containing a key matching this parameter will be returned, and only this key will be listed | - |
page | integer | The page number to fetch. This number must be a positive integer greater then or equal to 1 | 1 |
num_per_page | integer | The maximal number of profiles per page. This number must be a positive integer greater than or equal to 1 and lower than or equal to 10000 | 2000 |
updated_since | datetime | If provided, returns only the list of profiles for which there were attribute changes since this date. Attributes that were removed before this date are not returned. If the attribute was removed after the date and there has been other changes to this attribute after the date, the property removed is marked as true. For set attributes, returns the current state of the set if the set suffered any modifications since the date. |
- |
Example
system_of_record_identifier;customer_attribute_identifier;customer_attribute_key;customer_attribute_value;customer_id_type;customer_id
SOR-SDK_2a116e0767a7dc76e85a5ef85434d92b;FACA_lEDOA5CbP5YzFKcM;team;team1;device_id;3f976ddac73f7d80
SOR-SDK_2a116e0767a7dc76e85a5ef85434d92b;FACA_lEDOA5CbP5YzFKcM;team;team2;user_id;user1
Feed Customer Attributes
FollowAnalytics Ruby gem
We provide a ruby gem to help you modify values for profiles stored in FollowAnalytics.
Define attribute types
To avoid having incoherence in the attribute values it's preferable to define attribute types before starting the feeding.
Limit of attribute values
For both feeding and import APIs, there is a limit of 1000 values for attributes of type SET
and each element of the set must be a string of at most 256 characters, if these limits are exceeded the request will be rejected.
Feed Customer Attributes with values
Feeding a Customer Profile with values can be done either from the SDK or from other external systems. This chapter does not cover the SDK functionality, but focuses on external systems.
This API is adapted to small data sets
If you intend to send large data sets on a regular basis, please use the batch CSV imports documented below.
POST https://sor.follow-apps.com/api/attribute_values
Body parameters
It takes a JSON object containing the following keys:
Property | Type | Description | Default |
---|---|---|---|
sor | string | The System of Record identifier | required |
api_key | string | The API Key associated to this SOR | required |
customer_attribute_values | array of objects | An array of customer_attribute_value object (called CAV below to simplify reading) |
required |
CAV[attribute_key] | string | The Attribute key. | required |
CAV[attribute_value] | string | The value of this attribute for this Customer. Possible values are listed below. | required |
CAV[customer_id] | string | The customer identifier | required |
CAV[action_type] | string | Used to ADD or REMOVE a specific value to/from the attribute. You can also use DEL to empty the set or UPSERT to replace all set values at once. |
required for SET type, for the other types it's not required, when it's not speicified it simply adds the value |
Possible attribute values:
Value | Type | Description |
---|---|---|
Test |
string | Limit of 256 Unicode characters |
10 |
number | Limit: 2**63 - 1 |
-1420.2 |
number | Limit: -(2**63 - 1) |
true |
boolean | |
false |
boolean | |
2016-12-22 |
date | |
2016-12-22T13:02:53Z |
datetime | |
null |
any | Removes the value |
Here is the description of the possible action types:
action_type | For attributes of type set |
For scalar attribute values (other than set type) |
---|---|---|
ADD |
adds the provided element to the set | replaces the attribute value by the provided one |
REMOVE |
removes the provided element from the set | ignored, it's considered as an UPSERT |
DEL |
deletes ALL the elements of the set | removes the current attribute value regardless of the provided attribute_value |
UPSERT |
replaces the whole content of the set with new values. The new values should be provided in the parameter value, separated by ; : "value":"one;2;three;etc..." . If a set value contains itself a semicolon ; it's recommended to use an ADD request for each value. For example to add value1; and value2 , it's recommended to use 2 ADD requests, one for value1; and another one for value2 |
replaces the attribute value by the provided one |
Example
{
"sor": "SOR_XXXX",
"api_key": "XXXXXXXX",
"customer_attribute_values": [
{
"customer_id" : "098713490",
"attribute_key" : "contract_type",
"attribute_value" : "Premium"
},
{
"customer_id" : "098713490",
"attribute_key" : "hobbies",
"attribute_value" : "Sport",
"action_type" : "ADD"
},
{
"customer_id" : "098713490",
"attribute_key" : "hobbies",
"attribute_value" : "Reading",
"action_type" : "REMOVE"
},
{
"customer_id" : "098713490",
"attribute_key" : "hobbies",
"attribute_value" : "Reading;Hiking;Singing",
"action_type" : "UPSERT"
},
{
"customer_id" : "098713491",
"attribute_key" : "fav_team",
"attribute_value" : "France"
},
{
"customer_id" : "098713492",
"attribute_key" : "fav_team",
"attribute_value" : "Italy"
}
]
}
In the example above contract_type
and fav_team
are attributes of type String
.hobbies
is an attribute of type SET
.
The request body above will imply the following:
- Add
Premium
value tocontract_type
for the customer098713490
, - Add
Sport
value to the set of values ofhobbies
for the customer098713490
, - Remove
Reading
from the set of values ofhobbies
for the customer098713490
if this value is part of the set, otherwise, it does nothing, - Replace all set values by
Reading;Hiking;Singing
for the customer098713490
, - Add
France
tofav_team
for customer098713491
, - Add
Italy
tofav_team
for customer098713492.
Response
The response will return the request_id that will allow to track the progress of the request.
Status: 200 OK
{
"success" : true,
"result": {
"requestId": "1522771731812-vl9cUtxfZtMl"
},
"errorMessage": null,
"errorCode": 0
}
Import attribute values from CSV
For large attribute data sets and recurrent imports, it's recommended to send CSV files with attribute values to Followanalytics through the following API. All CSV files must use UTF-8 encoding and it's preferable to compress them as gzip files.
Use the common end-point
This uses the regular, common end-point given in the API overview page, contrary to the JSON upload of attributes which is done through a specific one.
POST /api/attribute_values/batch_import
Query parameter
Property | Type | Description | Default |
---|---|---|---|
file_url | string | URL to the CSV file, gzipped or not | required unless uploaded as part of request |
sor_id | string | The System of Record identifier | required |
api_key | string | The API Key associated to this SOR | required |
request_headers | map | Key-values to use as headers in the call to the file URL, if necessary. Useful for Authentication, e.g. { "Authorization": "abcd", "x-ms-blob-type": "def", ...} |
- |
skip_email | boolean | Indicates if FA should send an email to notify about the status of the import | false |
You can also upload the file directly as if part of a web form. The key for the file must be file
.
Response
Processing is done asynchronously, including the download of your file. When you call the API, a job ID is returned if all parameters are valid.
Use this job ID in communicating with us if you have an issue with your jobs.
Status: 200 OK
{
"success": true,
"result": {
"jid": "c98de272c6e42d93e7d2b969",
"import_id": "import_id_1"
}
}
CSV file content
It's recommended to use gzip compressed files to increase the performance. The CSV file itself must be encoded with UTF-8 and have the following header:
user_id,attribute_key,value,action_type
The key must match an existing attribute of the right type
This API will ignore values for keys not found for the provided SOR identifier. The action_type accepts the 'ADD', 'REMOVE', 'DEL', and 'UPSERT' actions, with 'UPSERT' being the default if the column is empty.
Set values
Each line for a Set attribute is considered as the new full state of the Set. In other words, for a given user and given Set attribute, any list of values provided replaces all current values.
Values for a given user and set are put on the same line, separated by semi-colons. For instance, a CSV line where we set value1
and value2
as the two new and only values of the Set identified by the key my_set
is as follows:
abcd,my_set,value1;value2,UPSERT
Example
The following CSV file:
user_id,attribute_key,value,action_type
abcd,my_set,value1;value2,UPSERT
abcd,my_set,value3;value4
efgh,my_set,value2,REMOVE
xyzw,my_set,,DEL
xyzw,my_set,value1,ADD
efgh,my_number,1234,
- sets values
value1
andvalue2
for Set of keymy_set
, for userabcd
- sets values
value3
andvalue4
for Set of keymy_set
, for userabcd
- removes value
value2
from the Set of keymy_set
, for userefgh
- removes all values of the Set of key
my_set
, for userxyzw
- adds
value1
to the Set of keymy_set
, for userxyzw
- sets value
1234
for Number attribute of keymy_number
, for userefgh
Hosted at https://path.to/my/file.csv
, you would send it as follows:
{
"file_url": "https://path.to/my/file.csv",
"sor_id": "SOR_767yUpsMJoTWi0mz",
"api_key": "XXXXXXXX"
}
CSV attributes import generation
Generate a CSV template that can be used for the batch CSV import API.
GET /api/attribute_values/template
Query parameter
Property | Type | Description | Default |
---|---|---|---|
sor_id | string | The identifier of a System of Record | required |
api_key | string | The API Key associated to the System of Record | required |
Monitoring of CSV imports
You can verify the status of your recent imports. The import job ids and the details of import errors are available for one week.
GET /api/attribute_values/import_jobs
Query parameter
There are no parameters for this query.
Response
The query returns the list of import jobs for the currently logged in user.
Status: 200 OK
{
"success": true,
"result": {
"import_id_1": "2019-01-02 11:12:13",
"import_id_2": "2019-02-03 11:12:13",
"import_id_3": "2019-03-03 11:12:13"
}
}
GET /api/attribute_values/import_errors?import_id=import_id
Query parameter
Property | Type | Description | Default |
---|---|---|---|
import_id | string | The identifier of the import | required |
Response
The query returns the list of import jobs for the currently logged in user or, in alternative, for a specific customer.
Status: 200 OK
{
"success": true,
"result": {
"attribute_errors": [
{
"import_id": "import_id_1",
"error_type": "empty_key",
"customer_id": "Bob",
"key": "age",
"date": "2019-01-02T11:12:13",
"message": "attributeKey is empty",
"raw": "{\n\"sor\":\"SOR_XXXX\",\n\"api_key\":\"XXXXXXXX\",\n\"customer_attribute_values\": [\n{\n\"customer_id\" :\"098713490\",\n\"attribute_key\" :\"contract_type\",\n\"attribute_value\" :\"Premium\"\n}\n]\n}",
"sor": "SOR_XXX",
"source": "AttributeCleaner",
}
]
}
}
key
: attribute keysource
: technical field identifying the part of the processing pipeline where the error has occuredmessage
: the description of the errorraw
: raw json of the original attribute value requesterror_type
: the type of the error.
error_type
can be a technical error :
KAFKA_DELIVERY_FAILED
: failed to send attribute values to KafkaFILE_TRANSFER_ERROR
: failed to retrieve import file
Or a content error :
EMPTY_SOR
: the System of Records identifier is not specifiedINVALID_CUSTOMER_ID
: the customer id is invalidEMPTY_KEY
: the attribute key is not specifiedTOO_LONG_KEY
: the attribute key has more than 256 charactersEMPTY_VALUE
: the attribute value is not specifiedINVALID_VALUE
: the attribute value is invalidTOO_LONG_VALUE
: the attribute value or a value in theSET
has more than 256 charactersTOO_LONG_SET_SIZE
: the attribute of typeSET
has more than 1000 elementsUNDEFINED_ATTRIBUTE
: the attribute is not defined in System of RecordsDISABLED_ATTRIBUTE
: the attribute is disabledUNKNOWN_TYPE
: the type of the attribute is unknownINVALID_ACTION
: the action specified is invalidPARSING_FAILED
: failed to parse the import fileFILE_ENCODING
: the content of the import file is not properly UTF-8 configured. Can also indicate that the file transfer did not work correctly
Systems of Records
List of SORs
GET /api/system_of_records?type=type
This call lists all the Systems Of Records available for your entity.
There are two types of systems of records (key type
):
app
: SDK-based SoR, related to an appcustom
: a custom SoR, defined by a user of your entity
If the param type
is invalid, no system of records are returned.
Query parameter
Property | Type | Description | Default |
---|---|---|---|
type | string | Filter results by type. Can be app and custom . |
- |
Response
Status: 200 OK
{
"success": true,
"result": [
{
"name": "SOR for app XYZ",
"identifier": "SOR-SDK_your.package.name",
"type": "app",
"api_keys": [
"FH7nIacl4f"
],
"attributes_count": 0,
"disabled": false,
"customer_attributes": []
},
{
"name": "Custom SOR",
"identifier": "SOR_rldYf1ypGTfvKjl-",
"type": "custom",
"api_keys": [
"2ypbGlj7g0SHOe"
],
"attributes_count": 2,
"disabled": true,
"customer_attributes": [
{
"identifier": "FACA__eTzcrLpnuJq",
"key": "key1",
"label": "label_name1",
"value_type": "String",
"disabled": false
},
{
"identifier": "FACA_t7NiJiYd_kGj",
"key": "key2",
"label": "label_name1",
"value_type": "Number",
"disabled": false
}
]
}
]
}
View SOR
GET /api/system_of_records/sor_identifier
Gets information about a single System of Records. This is more detailed than the list because it contains information about the attributes as well.
Query parameter
Property | Type | Description | Default |
---|---|---|---|
sor_identifier | string | The System of Records identifier to view | required |
Response
Status: 200 OK
{
"success": true,
"result":{
"name": "Custom SOR",
"identifier": "SOR_rldYf1ypGTfvKjl-",
"type": "custom",
"api_keys": [
"2ypbGlj7g0SHOe"
],
"attributes_count": 2,
"disabled": true,
"customer_attributes": [
{
"identifier": "FACA__eTzcrLpnuJq",
"key": "key1",
"label": "label_name1",
"value_type": "String",
"disabled": false
},
{
"identifier": "FACA_t7NiJiYd_kGj",
"key": "key2",
"label": "label_name1",
"value_type": "Number",
"disabled": false
}
]
}
}
Create, Update, Delete SOR
Create
Creates a custom SoR, with a name.
Please note that SDK-based Systems of Records are created automatically, so there is no need to create on manually.
POST /api/system_of_records
Body parameter
Property | Type | Description | Default |
---|---|---|---|
name | string | Name of the new SOR | required |
Example
{
"name": "My Custom SoR"
}
Response
Status: 200 OK
{
"success": true,
"result": {
"name": "My Custom SoR",
"identifier": "SOR_767yUpsMJoTWi0mz",
"type": "custom",
"api_keys": [
"tBqL8qvvAhfyAQ"
],
"attributes_count": 0,
"disabled": false
}
}
Update
Modifies a System of Records.
Only custom system of records can be modified.
PUT /api/system_of_records/sor_identifier
Query parameter
Property | Type | Description | Default |
---|---|---|---|
sor_identifier | string | The System of Records identifier | required |
Body parameter
Property | Type | Description | Default |
---|---|---|---|
name | string | New name for the SOR | required |
Example
{
"name": "My Custom SoR"
}
Response
Status: 200 OK
{
"success": true,
"result": {
"name": "My Custom SoR",
"identifier": "SOR_767yUpsMJoTWi0mz",
"type": "custom",
"api_keys": [
"tBqL8qvvAhfyAQ"
],
"attributes_count": 0,
"disabled": false
}
}
Delete
Deletes a System of Records.
Please note that this is not very useful for live SDK-based Systems of Records, as the entry will automatically be regenereted upon next call. In that case, disabling the System of Records is advised.
Also, please note that only custom system of records can be deleted.
DELETE /api/system_of_records/sor_identifier
Query parameter
Property | Type | Description | Default |
---|---|---|---|
sor_identifier | string | Identifier for the SOR to delete | required |
Response
Status: 200 OK
{
"success": true
}
Disable & Enable SOR
Disable
Disables a System of Records. Trying to disable an already disabled system of record will result in an API error.
PUT /api/system_of_records/sor_identifier/disable
Query parameter
Property | Type | Description | Default |
---|---|---|---|
sor_identifier | string | Identifier of the SOR to disable | required |
Response
Status: 200 OK
{
"success": true
}
Enable
Enables a System of Records. Trying to enable an already enabled system of record will result in an API error.
PUT /api/system_of_records/sor_identifier/enable
Query parameter
Property | Type | Description | Default |
---|---|---|---|
sor_identifier | string | Identifier of the SOR to enable | required |
Response
Status: 200 OK
{
"success": true
}
Customer Attributes
This section covers the definition of the attributes onto SORs: key, type, and so on.
View Customer Attribute
GET /api/customer_attributes/ca_identifier
Gets information about a single customer attribute.
Query parameter
Property | Type | Description | Default |
---|---|---|---|
ca_identifier | string | The Customer Attribute identifier | required |
Response
Status: 200 OK
{
"success": true,
"result": {
"identifier": "FACA_eVYy7KP9PZqP_B8w",
"key": "is_valid",
"label": "Is valid",
"value_type": "Boolean",
"disabled": false,
"system_of_record_identifier": "SOR-SDK_2a116e0767a7dc76e85a5ef85434d92b"
}
}
Create, Update, Delete Customer Attribute
Create
Creates a customer attribute, with a custom label and a type.
POST /api/customer_attributes
Body parameter
Property | Type | Description | Default |
---|---|---|---|
system_of_record_identifier | String | The Customer Attribute related SOR | required |
key | String | The Customer Attribute key. Cannot contain more than 256 characters. | required |
label | String | The Customer Attribute displayed name | required |
type | String | The Customer Attribute value type: String , Number , Boolean , Date , DateTime or Set |
required |
Example
{
"system_of_record_identifier": "SOR-SDK_c7a5a35762fd9e50006fd77215599dfb",
"key": "My Attr",
"label": "my_attr",
"type": "String"
}
Response
Status: 200 OK
{
"success": true,
"result": {
"identifier": "FACA_0OkzOc8",
"key": "My Attr",
"label": "my_attr",
"value_type": "String",
"disabled": false
}
}
Modify
Modifies a customer attribute. Only the label
of a customer attribute can be changed.
PUT /api/customer_attributes/ca_identifier
Query parameter
Property | Type | Description | Default |
---|---|---|---|
ca_identifier | string | The Customer Attribute identifier | required |
Body parameter
Property | Type | Description | Default |
---|---|---|---|
label | String | The new label of the customer attribute. Leave it empty if you don't wish to change it | required |
Example
{
"label": "Test"
}
Response
Status: 200 OK
{
"success": true,
"result": {
"identifier": "FACA_eVYy7KP9PZqP_B8w",
"key": "is_valid",
"label": "Test",
"value_type": "Boolean",
"disabled": false
}
}
Delete
Deletes a customer attribute along with all the values associated to it.
It is not advised to delete attributes from a live System of Records. Because of auto-declaration, the attribute is going to be recreated upon the next receival of a value. If you don't want to receive these values, but you cannot modify the external system, you can disable the attribute instead.
An attribute that is currently being used in the filters of a campaign or segment cannot be deleted.
DELETE /api/customer_attributes/ca_identifier
Query parameter
Property | Type | Description | Default |
---|---|---|---|
ca_identifier | string | The Customer Attribute identifier | required |
Response
Status: 200 OK
{
"success": true
}
Disable & Enable Customer Attribute
Disable
By default, all attributes are enabled, but it is possible to disable one. By doing so, all future values sent for this attribute will be refused, until the attribute is enabled again.
Query parameter
Property | Type | Description | Default |
---|---|---|---|
ca_identifier | string | The Customer Attribute identifier | required |
Response
Status: 200 OK
{
"success": true
}
Enable
Enables a previously disabled attribute. Enabling an already enabled attribute is a no-op.
PUT /api/customer_attributes/ca_identifier/enable
Query parameter
Property | Type | Description | Default |
---|---|---|---|
ca_identifier | string | The Customer Attribute identifier | required |
Response
Status: 200 OK
{
"success": true
}
Attributes removed since a praticular date
GET /api/removed_attributes?since=since?system_of_record_identifier=system_of_record_identifier
Returns all the attributes removed for the given system of record.
Query parameter
Property | Type | Description | Default |
---|---|---|---|
system_of_record_identifier | string | The identifier of a system of record | required |
since | timestamp | If provided, only the attributes removed since this date will returned. Must be a valid date string (eg: '2020-01-01'), a timestamp string (eg: '2020-01-01 20:30') or a unix timestamp integer (eg: 1577910000) | - |
Response
Status: 200 OK
{
"success":true,
"result":[
{
"id":32500,
"system_of_record_id":1,
"key":"attr1",
"value_type":"Number",
"label":"attributeTest1",
"created_at":"2019-09-03T16:01:55.852Z",
"updated_at":"2020-01-06T11:00:26.082Z",
"identifier":"FACA_FgzfBvu",
"removed":true,
"disabled":false
},
{
"id":33050,
"system_of_record_id":1,
"key":"attr2",
"value_type":"String",
"label":"attributeTest2",
"created_at":"2019-09-25T14:52:04.261Z",
"updated_at":"2019-12-26T16:54:33.275Z",
"identifier":"FACA_2BmN8T0",
"removed":true,
"disabled":false
}
]
}