Data Import
Import your customer data into Data Activation to build richer profiles
Data Activation (formerly Customer Data Platform) lets you enrich customer profiles with data from external sources using the data import feature. With richer profiles, you can create more accurate audience segments, deliver better personalization, and improve your activations.
Ways to import data
There are two ways to import data:
Using webhook imports
This option accepts JSON payloads from any external tool, even when you don’t control the request format. You map the incoming fields to the Data Activation profile attributes in the UI. This method works well when importing data from services like email marketing tools, for example, updating subscriber status from MailChimp. Learn how to set it up in our help center guide.
Using API
This option requires data in a specific format but doesn’t involve any setup in the UI. It's a more advanced method, and works best when you control how data is sent, for example, when importing data directly from your app or custom code.
How to import data via API
You can import data to Data Activation with a single HTTP API request (API endpoint).
In the following example, we'll enrich a profile with order data:
POST /api/cdp/profiles/public/v1/app/{app_id}/update-profile
curl -X POST 'https://<example>/api/cdp/profiles/public/v1/app/<app_id>/update-profile' -H "Content-Type: application/json" --data '{
"identifiers": {
"cookie_id": "0123456789ABCDEF",
"user_id": "[email protected]"
},
"attributes": {
"analytics.order_time": "2025-05-23T09:37:27+01:00",
"analytics.revenue": 500,
"analytics.order_id": "UK/2025/05/65343"
}
}'
await fetch('https://<example>/api/cdp/profiles/public/v1/app/<app_id>/update-profile', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
identifiers: {
"cookie_id": "0123456789ABCDEF",
"user_id": "[email protected]"
},
attributes: {
"analytics.order_time": "2025-05-23T09:37:27+01:00",
"analytics.revenue": 500,
"analytics.order_id": "UK/2025/05/65343"
}
})
});
import requests
response = requests.post(
'https://<example>/api/cdp/profiles/public/v1/app/<app_id>/update-profile',
headers={'Content-Type': 'application/json'},
json={
'identifiers': {
'cookie_id': '0123456789ABCDEF',
'user_id': '[email protected]'
},
'attributes': {
'analytics.order_time': '2025-05-23T09:37:27+01:00',
'analytics.revenue': 500,
'analytics.order_id': 'UK/2025/05/65343'
}
}
)
In your request, replace the placeholders with your own data:
<example>
with your account address. Example: example.piwik.pro<app_id>
with your application IDuser_id
andcookie_id
with the actual user identifiersattributes
with your custom data you want to add to the profile
Request payload structure
The request payload always has two parts:
- Identifiers - At least one ID that matches the profile (cookie ID, user ID, etc.). Learn more about identifiers in this guide.
- Attributes - At least one attribute value you want to add or update. Learn more about profile attributes in this guide.
Verify your import
After importing your data, you can check if the profile was updated correctly. In the UI, go to Menu > Data Activation > People to see recently updated profiles, or use the API.
Get profile example
GET /api/cdp/profiles/v1/app/{app_id}/profile/{identifier_type}/{identifier_value}
::: info This endpoint requires an authorization token. Learn more on how to obtain and use the token in this guide. :::
curl -X GET 'https://<example>/api/cdp/profiles/v1/app/<app_id>/profile/user_id/[email protected]' -H "Authorization: Bearer <your_access_token>"
Response example
{
"version": 1,
"id": "43b5f062c57526ff",
"app_id": "b8d3f43e-b36c-47a7-a018-f85e2caf0978",
"created_at": "2025-09-09T20:56:30.310720845Z",
"updated_at": "2025-09-09T21:23:31.821940Z",
"identifiers": {
"cookie_id": [
"0123456789ABCDEF"
],
"user_id": [
"[email protected]"
]
},
"predefined_attributes": {
"last_order_time": "2025-05-23T08:37:27Z",
"total_revenue": 500
},
"custom_dimension_attributes": {},
"custom_attributes": {}
}
A successful response will show the updated attributes.
Import data to custom attributes
In addition to predefined attributes, you can define custom attributes to capture data specific to your business.
First, you'll need to add a custom attribute with an event data key. Learn more about adding or editing a custom attribute in this guide. Then send data to it using the same API request format as for predefined attributes. For example, you might add custom fields like customer score, age, or favorite color.
Custom attributes example
curl -X POST 'https://<example>/api/cdp/profiles/public/v1/app/<app_id>/update-profile' -H "Content-Type: application/json" --data '{
"identifiers": {
"cookie_id": "0123456789ABCDEF",
"user_id": "[email protected]"
},
"attributes": {
"crm_user_score": 12,
"age": 28,
"favorite_color": "red",
"sex": "female"
}
}'
await fetch('https://<example>/api/cdp/profiles/public/v1/app/<app_id>/update-profile', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
identifiers: {
cookie_id: '0123456789ABCDEF',
user_id: '[email protected]'
},
attributes: {
"crm_user_score": 12,
"age": 28,
"favorite_color": "red",
"sex": "female"
}
})
});
import requests
response = requests.post(
'https://<example>/api/cdp/profiles/public/v1/app/<app_id>/update-profile',
headers={'Content-Type': 'application/json'},
json={
'identifiers': {
'cookie_id': '0123456789ABCDEF',
'user_id': '[email protected]'
},
'attributes': {
'crm_user_score': 12,
'age': 28,
'favorite_color': 'red',
'sex': 'female'
}
}
)
Q&A
Can I use this API from a browser?
Yes, the API supports CORS and can be called directly from browsers. This makes it perfect for Tag Manager implementations or client-side data collection.
Can I import data without authentication?
Yes, the API endpoint is public and works without authentication.
Can I import arrays or complex objects?
Webhook imports allow you to upload complex objects and choose in the UI which parts should be used for profile enrichment. This is perfect for importing data from external systems that send complex JSON structures.
API imports only support basic data types: strings, numbers, booleans, IPs, and date-time values.
How to format data for the import?
To format data for the import, use the following conventions for each data type:
-
String: Use plain text values. Example:
"favorite_color": "red"
-
Number: Use integer or floating-point values without quotes. Example:
"crm_user_score": 12
"analytics.revenue": 1.82
-
Boolean: Use
true
orfalse
(without quotes). Example:"is_subscribed": true
-
Date-time: Use ISO 8601 format as a string. Example:
"analytics.order_time": "2025-05-23T08:37:27Z"
-
IPv4 address: Use it as a string. Example:
"analytics.location_ipv4": "192.168.1.1"
-
IPv6 address: Use it as a string. Example:
"analytics.location_ipv6": "2001:0db8:85a3:0000:0000:8a2e:0370:7334"
What should I do if the import fails?
Check the response status code:
- 400 Bad Request - Fix the request format or missing required fields
- 402 Payment Required - CDP module is not enabled
- 404 Not Found - Incorrect App ID
- 422 Unprocessable Entity - Data validation failed
What happens when malformed data is sent to an attribute
When you send malformed data, the behavior depends on the import method:
Webhook imports:
- The request is received and processed
- Server responds with HTTP 202 (Accepted)
- The entire update is rejected
- Detailed error information is displayed in the UI
Update Profile API:
- The request is immediately rejected
- Server responds with HTTP 400 (Bad Request)
- Response contains specific error details about what went wrong
Updated about 4 hours ago