User profiles import
Use this feature to UPSERT or DELETE user profiles in your datamart.
How-to
Use the bulk import endpoints to create a document import with theUSER_PROFILE
document type and APPLICATION_X_NDJSON
mime type. Only ndjson
data is supported for user profiles.
You can, of course, upload multiple user profiles at once. Note the uploaded data is in ndjson
and not json
. That means the different profiles are not separated by commas, but by a line separator \n
Then, create an execution with your user profile import commands formatted in ndjson
.
User profile import command
Each line in the uploaded file can have the following properties:
operation
Enum
Either UPSERT
or DELETE
compartment_id
String (Optional)
The Compartment ID, acting as a user identifier in correlation with user_account_id
user_account_id
String (Optional)
The User Account ID, acting as an identifier in correlation with compartment_id
update_strategy
Enum (Optional)
Only considered when operation == UPSERT
Values are PARTIAL_UPDATE
, PARTIAL_DELETE
, FORCE_REPLACE
user_profile
JSON Object (Optional)
Mandatory when operation == UPSERT.
JSON Object representing the User Profile. Please refer to the user profile object for more information.
When importing profiles with identifiers, only one identifier is allowed per line. For example, you shouldn't specify the user agent ID if the Email Hash is already used in a line.
Example
First create the document import using the call below. You can also reuse a document import that was previously created
curl -X POST \
https://api.mediarithmics.com/v1/datamarts/<DATAMART_ID>/document_imports \
-H 'Authorization: <YOUR_API_TOKEN>' \
-H 'Content-Type: application/json' \
-d '{
"document_type": "USER_PROFILE",
"mime_type": "APPLICATION_X_NDJSON",
"encoding": "utf-8",
"name": "<YOUR_DOCUMENT_IMPORT_NAME>"
}'
Each user profile import you do will be a new execution of the document import created. Here is an example :
# Here we use the combination of compartment_id and user_account_id acting as identifier
curl -X POST \
https://api.mediarithmics.com/v1/datamarts/<DATAMART_ID>/document_imports/<DOCUMENT_IMPORT_ID>/executions \
-H 'Authorization: <API_TOKEN>' \
-H 'Content-Type: application/x-ndjson' \
-d '{
"operation": "UPSERT",
"compartment_id": "<COMPARTMENT_ID>",
"user_account_id": "<USER_ACCOUNT_ID>",
"user_profile": {
this": "is",
"a":"test"
}
}'
Available update strategies when updating existing user profiles
When doing an UPSERT
if you want to update existing profiles in your datamart you should use the update_strategy
property.
PARTIAL_UPDATE and PARTIAL_DELETE
If you wish to perform targeted updates on existing profiles without overwriting the whole existing user profile object, you should use the PARTIAL_UPDATE
or PARTIAL_DELETE
values of the update_strategy
property.
When dealing with arrays of objects, these options work together with a directive @UpdateStrategyKey
that should be defined on the schema of the datamart you are working on. In this case, you should first update the schema in order to include this new directive.
The directive is needed when you need to update values inside of an array of objects.
You should mark a field with the directive @UpdateStrategyKey
inside the given object you would like to make updates on. Inside of a given object, the field that has the directive will serve to identify the given object based on the value of this field in the update request.
For example of where the directive is needed, see use cases #1 to #5 below.
When there are no arrays of objects involved, you can still use the PARTIAL_UPDATE
but the directive is not necessary. For example not needing the directive, check use cases #6 and #7.
Application use cases of PARTIAL_UPDATE and PARTIAL_DELETE using the @UpdateStrategyKey
directive
@UpdateStrategyKey
directive#1 - Add an object in array of objects - PARTIAL_UPDATE
// Existing profile
{
"compartment_id": "<COMPARTMENT_ID>",
"user_account_id": "<USER_ACCOUNT_ID>",
"loyalty": {
"cards": [
{
"card_id": "abc",
"benefits": 500,
"last_visit_date": "2024-01-01"
}
]
}
}
//Profile in update payload with update_strategy == PARTIAL_UPDATE
{
"compartment_id": "<COMPARTMENT_ID>",
"user_account_id": "<USER_ACCOUNT_ID>",
"loyalty": {
"cards": [ //adding a new cards object
{
"card_id": "def",
"benefits": 100,
"last_visit_date": "2025-01-01"
}
]
}
}
//New profile
{
"compartment_id": "<COMPARTMENT_ID>",
"user_account_id": "<USER_ACCOUNT_ID>",
"loyalty": {
"cards": [ // the cards object contains both cards
{
"card_id": "abc",
"benefits": 500,
"last_visit_date": "2024-01-01"
},
{
"card_id": "def",
"benefits": 100,
"last_visit_date": "2025-01-01"
}
]
}
}
#2 - Update a property in an array of objects - PARTIAL_UPDATE
// Existing profile
{
"compartment_id": "<COMPARTMENT_ID>",
"user_account_id": "<USER_ACCOUNT_ID>",
"loyalty": {
"cards": [
{
"card_id": "abc",
"benefits": 500,
"last_visit_date": "2024-01-01"
}
]
}
}
//Profile in update payload with update_strategy == PARTIAL_UPDATE
{
"compartment_id": "<COMPARTMENT_ID>",
"user_account_id": "<USER_ACCOUNT_ID>",
"loyalty": {
"cards": [ //request changing the benefits value of the existing card
{
"card_id": "abc", // value of the field marked with @UpdateStrategyKey of the inner object to update
"benefits": 100
}
]
}
}
//New profile
{
"compartment_id": "<COMPARTMENT_ID>",
"user_account_id": "<USER_ACCOUNT_ID>",
"loyalty": {
"cards": [ //
{
"card_id": "abc",
"benefits": 100, // value has been updated
"last_visit_date": "2024-01-01"
}
]
}
}
// Extract of existing profile
{
"compartment_id": "<COMPARTMENT_ID>",
"user_account_id": "<USER_ACCOUNT_ID>",
"my_array_of_scalars": [1,2,3],
...
}
//Profile in update payload with update_strategy == PARTIAL_UPDATE
{
"compartment_id": "<COMPARTMENT_ID>",
"user_account_id": "<USER_ACCOUNT_ID>",
"my_array_of_scalars": [4,5,6],
...
}
//New profile
{
"compartment_id": "<COMPARTMENT_ID>",
"user_account_id": "<USER_ACCOUNT_ID>",
"my_array_of_scalars": [4,5,6], // the value of the property has been replaced by the new value
...
}
#3 - Delete a property inside an array of objects - PARTIAL_UPDATE
For a non mandatory value you can also set a given field to null
(but not an object directly). For instance in the previous example you could have done the following :
// Existing profile
{
"compartment_id": "<COMPARTMENT_ID>",
"user_account_id": "<USER_ACCOUNT_ID>",
"loyalty": {
"cards": [
{
"card_id": "abc",
"benefits": 500,
"last_visit_date": "2024-01-01"
}
]
}
}
//Profile in update payload with update_strategy == PARTIAL_UPDATE
{
"compartment_id": "<COMPARTMENT_ID>",
"user_account_id": "<USER_ACCOUNT_ID>",
"loyalty": {
"cards": [
{
"card_id": "abc",
"benefits": null // set the value to null
}
]
}
}
//New profile
{
"compartment_id": "<COMPARTMENT_ID>",
"user_account_id": "<USER_ACCOUNT_ID>",
"loyalty": {
"cards": [ // benefits value has been cleared
{
"card_id": "abc",
"last_visit_date": "2024-01-01"
}
]
}
}
#4 - Update object inside an array and add new object - PARTIAL_UPDATE
// Existing profile
{
"compartment_id": "<COMPARTMENT_ID>",
"user_account_id": "<USER_ACCOUNT_ID>",
"loyalty": {
"cards": [
{
"card_id": "abc",
"benefits": 500,
"last_visit_date": "2024-01-01"
}
]
}
}
//Profile in update payload with update_strategy == PARTIAL_UPDATE
{
"compartment_id": "<COMPARTMENT_ID>",
"user_account_id": "<USER_ACCOUNT_ID>",
"loyalty": {
"cards": [
{
"card_id": "abc",
"benefits": 100 //updating exsisting object
},
{
"card_id": "def", //adding a new object
"benefits": 600,
"last_visit_date": "2025-01-01"
}
]
}
}
//New profile
{
"compartment_id": "<COMPARTMENT_ID>",
"user_account_id": "<USER_ACCOUNT_ID>",
"loyalty": {
"cards": [
{
"card_id": "abc",
"benefits": 100, // value has been updated
"last_visit_date": "2024-01-01"
},
{
"card_id": "def", // object has been added
"benefits": 600,
"last_visit_date": "2025-01-01"
}
]
}
}
#5 - Delete an object in an array of objects - PARTIAL_DELETE
//Existing profile
{
"compartment_id": "<COMPARTMENT_ID>",
"user_account_id": "<USER_ACCOUNT_ID>",
"loyalty": {
"cards": [
{
"card_id": "abc",
"benefits": 100,
"last_visit_date": "2024-01-01"
},
{
"card_id": "def",
"benefits": 600,
"last_visit_date": "2025-01-01"
}
]
}
}
//Profile in update payload with update_strategy == PARTIAL_DELETE
{
"compartment_id": "<COMPARTMENT_ID>",
"user_account_id": "<USER_ACCOUNT_ID>",
"loyalty": {
"cards": [
{
"card_id": "abc" // value of the field marked with @UpdateStrategyKey of the inner object to delete
}
]
}
}
//New profile
{
"compartment_id": "<COMPARTMENT_ID>",
"user_account_id": "<USER_ACCOUNT_ID>",
"loyalty": {
"cards": [ // the card with card_id = "abc" has been deleted
{
"card_id": "def",
"benefits": 600,
"last_visit_date": "2025-01-01"
}
]
}
}
If you wish to delete a specific property value inside an object, you should use PARTIAL_UPDATE. Please refer to use case #3.
Application use cases of PARTIAL_UPDATE and PARTIAL_DELETE not needing the directive
#6 - Update properties inside the UserProfile - PARTIAL_UPDATE
//Existing profile
{
"compartment_id": "<COMPARTMENT_ID>",
"user_account_id": "<USER_ACCOUNT_ID>",
"first_name" : "john"
"last_name" : "doe"
}
//Profile in update payload with update_strategy == PARTIAL_UPDATE
{
"compartment_id": "<COMPARTMENT_ID>",
"user_account_id": "<USER_ACCOUNT_ID>",
"first_name" : null
"last_name" : "smith"
}
//New profile
{
"compartment_id": "<COMPARTMENT_ID>",
"user_account_id": "<USER_ACCOUNT_ID>",
"last_name" : "smith"
}
#7 - Update a property inside an object - PARTIAL_UPDATE
//Existing profile
{
"compartment_id": "<COMPARTMENT_ID>",
"user_account_id": "<USER_ACCOUNT_ID>",
"geo_location": {
"address": "1 main street",
"city": "paris",
"postal_code" : "0001",
"country" : "France"
}
}
//Profile in update payload with update_strategy == PARTIAL_UPDATE
{
"compartment_id": "<COMPARTMENT_ID>",
"user_account_id": "<USER_ACCOUNT_ID>",
"geo_location": {
"address": null,
"city": "New york",
}
}
//New profile
{
"compartment_id": "<COMPARTMENT_ID>",
"user_account_id": "<USER_ACCOUNT_ID>",
"geo_location": {
"city": "new york",
"postal_code" : "0001",
"country" : "France"
}
}
Constraints and limitations
Schema related constraints :
The update request must respect the datamart schema :
If a property is in the payload of the request but not declared in the schema, the whole request will fail. However, if a property is already present in the profile but not declared in the schema, it will not be overwritten by a partial update or delete. In fact it will not be possible to update such property unless using
FORCE_REPLACE
If the types of the properties in the payload of the request do not respect the schema, the whole request will fail.
#This is allowed
type LoyaltyCard {
card_id:String @UpdateStrategyKey
benefits: Int
last_visit_date: String
other_information : [OtherInformation]
}
type OtherInformation {
info_id: String @UpdateStrategyKey
}
################################
#This is not allowed
type LoyaltyCard {
card_id:String @UpdateStrategyKey
benefits: Int @UpdateStrategyKey
last_visit_date: Date
}
Limitations :
If a property in the schema has a directive such as
@Property(path: “[parent].property”)
(referencing [parent] in path) : this property cannot be updated with the partial updateUpdatable properties cannot be computed values such as : computed field, ML function, results of function.
FORCE_REPLACE
When importing user profiles using UPSERT
, if you wish to update existing profiles by completely overwriting the existing profiles you should use the FORCE_REPLACE
value of the update_strategy
property: the user profile will be completely replaced by the object passed in the user_profile
property.
# Stored profile:
{
"compartment_id": "<COMPARTMENT_ID>",
"user_account_id": "<USER_ACCOUNT_ID>",
"loyalty": {
"cards": [
{
"benefits": 200,
"card_id": "abc",
"last_visit_date": "2024-01-01"
}
]
}
}
# New profile in request payload
curl -X POST \
https://api.mediarithmics.com/v1/datamarts/<DATAMART_ID>/document_imports/<DOCUMENT_IMPORT_ID>/executions \
-H 'Authorization: <API_TOKEN>' \
-H 'Content-Type: application/x-ndjson' \
-d '{
"operation": "UPSERT",
"compartment_id": "<COMPARTMENT_ID>",
"user_account_id": "<USER_ACCOUNT_ID>",
"update_strategy": "FORCE_REPLACE",
"user_profile": {
"compartment_id": "<COMPARTMENT_ID>",
"user_account_id": "<USER_ACCOUNT_ID>",
"loyalty": {
"cards": [
{
"benefits": 500,
"card_id": "xyz",
"last_visit_date": "2025-01-01"
}
]
}
}
}'
# New saved profile:
{
"compartment_id": "<COMPARTMENT_ID>",
"user_account_id": "<USER_ACCOUNT_ID>",
"loyalty": {
"cards": [
{
"benefits": 500,
"card_id": "xyz",
"last_visit_date": "2025-01-01"
}
]
}
}
Legacy parameters
force_replace
Boolean (Optional)
Mandatory when the operation is UPSERT
.
If true, then the User Profile will be completely replaced by the object passed in the user_profile
field.
If false, the object passed in the user_profile
field will be merged with the existing User Profile of the User Point.
merge_objects
Boolean (Optional)
Only considered if force_replace
is false.
Manage the comportement between two objects with a same property.
If false (default value), the new object overrides the existing one.
If true the new object is merged in deep to the existing one (see example).
More details on merge_objects
behavior :
# Stored profile:
{
"my_property_1": "value1",
"my_property_2": "value1",
"my_array_property": ["value1"]
"my_array_object_property": [
{
"my_sub_array_object_property_1": "value1",
"my_sub_array_object_property_2": "value1"
}
],
"my_object_property": {
"my_sub_object_property_1": "value1",
"my_sub_object_property_2": "value1"
}
}
# New profile in request payload
curl -X POST \
https://api.mediarithmics.com/v1/datamarts/<DATAMART_ID>/document_imports/<DOCUMENT_IMPORT_ID>/executions \
-H 'Authorization: <API_TOKEN>' \
-H 'Content-Type: application/x-ndjson' \
-d '{
"operation": "UPSERT",
"compartment_id": "<COMPARTMENT_ID>",
"user_account_id": "<USER_ACCOUNT_ID>",
"force_replace": false,
"merge_objects": true,
"user_profile": {
"my_property_2": "value2",
"my_property_3": "value3",
"my_array_property": ["value2"]
"my_array_object_property": [
{
"my_sub_array_object_property_2": "value2"
"my_sub_array_object_property_3": "value3"
}
],
"my_object_property": {
"my_sub_object_property_2": "value2"
"my_sub_object_property_3": "value3"
}
}
}'
# New saved profile:
{
"my_property_1": "value1",
"my_property_2": "value2", # override scalar property
"my_property_3": "value3",
"my_array_property": ["value1","value2"] # merge arrays
"my_array_object_property": [ # merge arrays
{
"my_sub_array_object_property_1": "value1"
"my_sub_array_object_property_2": "value1"
},
{
"my_sub_array_object_property_2": "value2"
"my_sub_array_object_property_3": "value3"
}
],
"my_object_property": { # merge objects
"my_sub_object_property_1": "value1"
"my_sub_object_property_2": "value2" # override scalar property within object
"my_sub_object_property_3": "value3"
}
}
Last updated
Was this helpful?