Revision 2023-07-15 Relationships migration
Migrate to the standardized Relationships object released in the 2023-07-15 revision.
Klaviyo is standardizing how we handle relationships in our APIs and implemented consistently typed objects across API endpoints. Following the 2023-07-15
revision changes, you can create a profile in our APIs in the same shape, regardless of whether you’re calling the profiles endpoint or the events endpoint.
The kinds of changes include:
- 1:1 relationships now use singular tense and an object, instead of plural and an array.
- Example: GET
https://a.klaviyo.com/api/flow-actions/{flow_action_id}/?include=flow
, nowflow
instead offlows
.
- Example: GET
- Related object IDs relocated from the attributes payload to relationships.
- Example: POST
https://a.klaviyo.com/api/tags/
.
- Example: POST
- Specifying a relationship between two Klaviyo objects allows for improved consistency and greater interoperability across endpoints.
- Example: You can now create/update a profile for an event in the same way you would when using the profiles API directly with a POST request to
https://a.klaviyo.com/api/events/
.
- Example: You can now create/update a profile for an event in the same way you would when using the profiles API directly with a POST request to
Events API
Why
Events are related to other top-level profile and metric objects. Consistently specify the attributes for profiles, as well as metrics, when creating events for a particular profile or creating or updating a profile.
You can also specify a profile for an event in the same way as using the Profiles API.
Before and after
POST request to https://a.klaviyo.com/client/events
:
{
"data": {
"type": "event",
"attributes": {
"profile": {
"$email": "[email protected]",
"$phone_number": "+19148675309",
"$kid": "12234345",
"$id": "abc123",
"$exchange_id": "ksdfxl-sdfssdf",
"fun fact": "i like coffee",
},
"metric": {
"name": "Viewed Product"
},
"properties": {
"itemId": "123"
},
"time": "2022-11-08T00:00:00",
"value": 9.99
}
}
}
{
"data": {
"type": "event",
"attributes": {
"profile": {
"data": {
"type": "profile",
"id": "12234345",
"attributes": {
"email": "[email protected]",
"phone_number": "+19148675309",
"anonymous_id": "123456",
"external_id": "abc123",
"\_kx": "ksdfxl-sdfssdf",
"properties": {
"fun fact": "i like coffee"
}
}
},
"metric": {
"data": {
"type": "metric",
"attributes": {
"name": "Viewed Product"
}
}
},
"properties": {
"itemId": "123"
},
"time": "2022-11-08T00:00:00",
"value": 9.99
}
}
}
Get Event and Get Events
The metric_id
and profile_id
have been removed from the top-level attributes on the event payload.
The relationships keys are now singular.
Why
The metric and profile IDs are related object IDs and can be accessed under relationships.
The relationships between an event and profile and event and metric are 1:1, which should be specified as singular.
Before and after
GET request to /api/events/{event_id
:
{
"data": {
"type": "event",
"attributes": {
"metric_id": "AbC123",
"profile_id": "01F2VWQ645BES947MP1BPAKVMB",
"timestamp": 1688154729,
"event_properties": {
...
},
"datetime": "2023-06-30 19:52:09+00:00",
"uuid": "98fbfa80-177f-11ee-8001-f71585a038b4"
},
"relationships": {
"profiles": {
"data": [
{"type": "profile", "id": "01F2VWQ645BES947MP1BPAKVMB"}
]
},
"metrics": {
"data": [
{"type": "metric", "id": "AbC123"}
]
},
}
}
{
"data": {
"type": "event",
"attributes": {
"timestamp": 1688154729,
"event_properties": {
...
},
"datetime": "2023-06-30 19:52:09+00:00",
"uuid": "98fbfa80-177f-11ee-8001-f71585a038b4"
},
"relationships": {
"profile": {
"data": {"type": "profile", "id": "01F2VWQ645BES947MP1BPAKVMB"}
},
"metric": {
"data": {"type": "metric", "id": "AbC123"}
},
}
}
Flows API
When including the related flow for a flow action, or related action for a message, specify as singular instead of plural.
Why
This is a to-one relationship, which should be specified as singular.
Before and after
GET request to /api/flow-actions/(flow_action_id}/?include=flow
:
{
"data": {
"type": "flow-action",
"attributes": {...},
"relationships": {
"flows": {
"data": [
{"type": "flow", "id": "HgkVeu"}
]
}
}
}
{
"data": {
"type": "flow-action",
"attributes": {...},
"relationships": {
"flow": {
"data": {"type": "flow", "id": "HgkVeu"}
}
}
}
The relationship to the flow will return a singular object instead of an array.
GET request to /api/flow-actions/{flow_action_id}/relationships/flow/
:
{
"data": [
{
"type": "flow",
"id": "HgkVeu"
}
]
}
{
"data": {
"type": "flow",
"id": "HgkVeu"
}
}
Tags API
When creating a tag, the related tag group must now be specified as a relationship instead of using a tag_group_id
field.
Why
This is the standard JSON:API method for assigning relationships when creating resources.
Before and after
POST request to /api/tags/
:
{
"data": {
"type": "tag",
"attributes": {
"name": "My Tag",
"tag_group_id": "zyxw9876-vu54-ts32-rq10-zyxwvu654321"
}
}
}
{
"data": {
"type": "tag",
"attributes": {
"name": "My Tag",
},
"relationships": {
"tag-group": {
"type": "tag-group",
"id": "zyxw9876-vu54-ts32-rq10-zyxwvu654321"
}
}
}
}
The response from this endpoint will return a single object now, the related tag group, instead of a list containing one object.
Why
Singular-to-one relationships (i.e. "tag-group", not "tag-groups") will return single objects.
Before and after
GET request to /api/tags/1/tag-group/
:
{
"data": [
{
"type": "tag-group",
"id": "zyxw9876-vu54-ts32-rq10-zyxwvu654321"
...
}
]
}
{
"data": {
"type": "tag-group",
"id": "zyxw9876-vu54-ts32-rq10-zyxwvu654321"
...
}
}
Campaigns API
Get Campaigns, Create Campaign, Get Campaign, Update Campaign, Create Campaign Clone, Get Campaign Message, Update Campaign Message, and Assign Campaign Message Template
When using the campaigns API, the related campaign message (for campaigns) and the related campaign (for campaign messages) will no longer be returned in a message
or campaign_id
string field. Instead it will be returned as a relationship, in the relationship section of the response.
When using the Campaign Message API, any related templates will be referenced using relationships.
Why
This is the standard JSON:API method for posting and returning relationship data from a resource.
Before and after
GET request to /api/campaigns/{campaign_id}/
:
{
"data": {
"type": "campaign",
"id": "1",
"attributes": {
...
"message": "123"
}
}
}
{
"data": {
"type": "campaign",
"id": "1",
"attributes": {
...
},
"relationships": {
"campaign-messages": {
"data": [
{
"type": "campaign-message",
"id": "123"
}
]
}
}
}
}
GET request to /api/campaign-messages/{campaign_message_id}/
:
{
"data": {
"type": "campaign-message",
"id": "1",
"attributes": {
...
"content": {
"subject": "Hello",
"template_id": "1",
"template_name": "My Template"
}
}
}
}
{
"data": {
"type": "campaign-message",
"id": "1",
"attributes": {
...
"content": {
"subject": "Hello",
}
},
"relationships": {
"templates": {
"data": {
"type": "template",
"id": "1"
}
}
}
}
}
GET request to /api/campaign-messages/{campaign_message_id/?include=template
:
{
"data": {
"type": "campaign-message",
"id": "1",
"attributes": {
...
"content": {
"subject": "Hello",
"template_id": "1",
"template_name": "My Template"
}
}
}
}
{
"data": {
"type": "campaign-message",
"id": "1",
"attributes": {
...
"content": {
"subject": "Hello",
}
},
"relationships": {
"template": {
"data": {
"type": "template",
"id": "1"
}
}
}
},
"included": [
{
"type": "template",
"id": "1",
"attributes": {
"name": "My Template"
}
}
]
}
Catalogs API
When creating a catalog variant, the related item will be specified as a singular-to-one relationship using the item
field, rather than a list containing one item using items
.
Why
This relationship is singular, and should be specified as a single item.
Before and after
POST request to /api/catalog-variants/
:
{
"data": {
"type": "catalog-variant",
"attributes": {
...
},
"relationships": {
"items": {
"data": [
{
"type": "catalog-item",
"id": "$custom:::$default:::SAMPLE-DATA-ITEM-1"
}
]
}
}
}
}
{
"data": {
"type": "catalog-variant",
"attributes": {
...
},
"relationships": {
"item": {
"data": {
"type": "catalog-item",
"id": "$custom:::$default:::SAMPLE-DATA-ITEM-1"
}
}
}
}
}
Spawn Create Items Job, Spawn Update Items Job, Spawn Delete Items Job, Spawn Create Variants Job, Spawn Update Variants Job, Spawn Delete Variants Job, Spawn Create Categories Job, Spawn Update Categories Job, and Spawn Delete Categories Job
The request payload for the bulk catalog APIs is changing slightly: an additional data
element is inserted into the payload before the resource array.
Why
This is standardization to align with the similar structure in the relationships section of payloads.
Before and after
POST request to /api/catalog-item-bulk-create-jobs/
:
{
"data": {
"type": "catalog-item-bulk-create-job",
"attributes": {
"items": [
{"type": "catalog-item", ...}
]
}
}
}
{
"data": {
"type": "catalog-item-bulk-create-job",
"attributes": {
"items": {
"data": [
{"type": "catalog-item", ...}
]
}
}
}
}
Client API and Profiles API
When subscribing a profile, the related list will be specified as a relationship instead of an embedded list_id
, and the profiles to subscribe will be specified as profile resource objects instead of email
, phone_number
, or id
.
Why
This is the standard JSON:API method for assigning relationships when creating resources.
Before and after
POST request to /api/profile-subscription-bulk-create-jobs/
:
{
"data": {
"type": "profile-subscription-bulk-create-job",
"attributes": {
"list_id": "Y6nRLr",
"subscriptions": [
{"email": "[email protected]", "channels": {...}},
...
],
}
}
}
{
"data": {
"type": "profile-subscription-bulk-create-job",
"attributes": {
"profiles": {
"data": [
{
"type": "profile",
"attributes": {
"email": "[email protected]",
"subscriptions": {...}
},
...
]
}
}
},
"relationships": {
"list": {
"data": {"type": "list", "id": "Y6nRLr"}
}
}
}
}
List and profiles are specified via relationships, and the URL path and type have been updated.
Before and after
POST request to /api/profile-unsubscription-bulk-create-jobs/
:
{
"data": {
"type": "profile-subscription-bulk-create-job",
"attributes": {
"list_id": "Y6nRLr",
"subscriptions": [
{"email": "[email protected]", "channels": {...}},
...
],
}
}
}
{
"data": {
"type": "profile-subscription-bulk-delete-job",
"attributes": {
"profiles": {
"data": [
{
"type": "profile",
"attributes": {
"email": "[email protected]"
},
},
...
]
}
}
},
"relationships": {
"list": {
"data": {"type": "list", "id": "Y6nRLr"}
}
}
}
}
Profiles are specified under profiles
, and the URL path and resource type have been updated.
Before and after
POST request to /api/profile-suppression-bulk-create-jobs/
:
{
"data": {
"type": "profile-suppression-bulk-create-job",
"attributes": {
"suppressions": [
{
"email": "[email protected]",
},
...
]
}
}
}
{
"data": {
"type": "profile-suppression-bulk-create-job",
"attributes": {
"profiles": {
"data": [
{
"type": "profile",
"attributes": {
"email": "[email protected]",
},
...
]
}
}
}
}
Profiles are specified under profiles
, and the URL path and resource type have been updated.
Before and after
POST request to /api/profile-unsuppression-bulk-create-jobs
:
{
"data": {
"type": "profile-unsuppression-bulk-create-job",
"attributes": {
"suppressions": [
{
"email": "[email protected]"
}
]
}
}
}
{
"data": {
"type": "profile-suppression-bulk-delete-job",
"attributes": {
"profiles": {
"data": [
{
"type": "profile",
"attributes": {
"email": "[email protected]",
},
...
]
}
}
}
}
Data Privacy API
When requesting deletion of a profile, the related profile will be specified as a relationship to the profile resource instead of top level identifiers.
Why
This is the standard JSON:API method for specifying relationships to other resources.
Before and after
POST request to /api/data-privacy-deletion-jobs/
:
{
"data": {
"type": "data-privacy-deletion-job",
"attributes": {
"profile_id": "01F2VWQ645BES947MP1BPAKVMB",
"email": "[email protected]",
"phone_number": "+15005550006"
}
}
}
{
"data": {
"type": "data-privacy-deletion-job",
"attributes": {
"profile": {
"data": {
{
"type": "profile",
"id": "01F2VWQ645BES947MP1BPAKVMB",
"attributes": {
"email": "[email protected]",
"phone_number": "+15005550006"
}
}
}
}
}
}
}
Updated about 1 year ago