All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
NOTE: For more granular API-specific changes, please see our API Changelog
- Get and Update Reviews APIs
- Retrieve all reviews with
Reviews.get_reviews
or return a review with a specified ID using theReviews.get_review
endpoint. - Manage your reviews programmatically with the
Reviews.update_review
endpoint, which allows you to change the status of a review, such as to reject or approve it. This endpoint modifies the moderation status of a review based on the provided review ID and status.
- Retrieve all reviews with
- Get and Create Flows APIs
- Return a flow with the given flow ID using the
Flows.get_flow
endpoint. - Create a new flow with the
Flows.create_flow
endpoint.
- Return a flow with the given flow ID using the
- Campaigns API
- Manage the images for your campaigns with a new set of endpoints for the
Campaigns
API, including:get_image_for_campaign_message
,get_image_id_for_campaign_message
, andupdate_image_for_campaign_message
.
- Manage the images for your campaigns with a new set of endpoints for the
- Breaking: Subscription endpoints required field
- Calls to
Profiles.bulk_subscribe_profiles
andProfiles.unsubscribe_profiles
now require thesubscriptions
field, which grants or revokes consent for the indicated message types on the specified channels, such as email or sms.
- Calls to
- Breaking: Campaigns API push notification support
- The Campaigns API now supports the push notification channel.
- Support for push notifications includes significant changes to the following endpoints:
get_campaigns
,get_campaign
,create_campaign
,update_campaign
,create_campaign_clone
,get_messages_for_campaign
,get_campaign_message
,update_campaign_message
,get_campaign_for_campaign_message
,get_campaign_id_for_campaign_message
. - We recommend that you review the Campaigns API Overview for more detailed information about changes to the structure and responses of these endpoints.
- Breaking: Pagination updates
- The
Flows.get_messages_for_flow_action
andFlows.get_action_id_for_flow_message
endpoints have been updated from offset pagination to cursor pagination.
- The
- Create Template API
- The
Templates.create_template
endpoint now supports the creation of hybrid templates wheneditor_type
isUSER_DRAGGABLE
and hybrid template HTML is included.
- The
- Profiles API
- The following server-side APIs have been updated to an enhanced identity resolution processor to better follow the Klaviyo identity resolution identifier priority order.
Profiles.create_profile
Profiles.update_profile
- The following server-side APIs have been updated to an enhanced identity resolution processor to better follow the Klaviyo identity resolution identifier priority order.
- Breaking: Renamed models
AudiencesSubObject
->Audiences
GetCampaignTagRelationshipListResponseCollection
->GetCampaignTagsRelationshipsResponseCollection
GetCatalogCategoryItemListResponseCollection
->GetCatalogCategoryItemsRelationshipsResponseCollection
GetCatalogCategoryItemListResponseCollectionDataInner
->GetCatalogCategoryItemsRelationshipsResponseCollectionDataInner
GetCatalogItemCategoryListResponseCollection
->GetCatalogItemCategoriesRelationshipsResponseCollection
GetCatalogItemCategoryListResponseCollectionDataInner
->GetCatalogItemCategoriesRelationshipsResponseCollectionDataInner
GetCouponRelationshipCouponCodesListResponseCollection
->GetCouponCodesRelationshipsResponseCollection
GetCouponRelationshipCouponCodesListResponseCollectionDataInner
->GetCouponCodesRelationshipsResponseCollectionDataInner
GetEventMetricRelationshipResponseData
->GetEventResponseCollectionCompoundDocumentDataInnerAllOfRelationshipsMetricData
GetFlowResponseCompoundDocument
->GetFlowResponseCompoundDocument
GetFlowTagRelationshipListResponseCollection
->GetFlowTagsRelationshipsResponseCollection
GetFormFormVersionRelationshipsResponseCollection
->GetFormVersionsRelationshipsResponseCollection
GetListRelationshipsResponseCollection
->GetListProfilesRelationshipsResponseCollection
GetListTagRelationshipListResponseCollection
->GetListTagsRelationshipsResponseCollection
GetProfileImportJobProfileRelationshipsResponseCollection
->GetProfileBulkImportJobProfilesRelationshipsResponseCollection
GetProfileListRelationshipsResponseCollection
->GetProfileListsRelationshipsResponseCollection
GetProfileSegmentRelationshipsResponseCollection
->GetProfileSegmentsRelationshipsResponseCollection
GetReviewResponseDTO20240715CollectionCompoundDocument
->GetReviewResponseDTOCollectionCompoundDocument
GetReviewResponseDTO20240715CollectionCompoundDocumentDataInner
->GetReviewResponseDTOCollectionCompoundDocumentDataInner
GetReviewResponseDTO20240715CollectionCompoundDocumentDataInnerAllOfRelationships
->GetReviewResponseDTOCollectionCompoundDocumentDataInnerAllOfRelationships
GetReviewResponseDTO20240715CollectionCompoundDocumentDataInnerAllOfRelationshipsEvents
->GetReviewResponseDTOCollectionCompoundDocumentDataInnerAllOfRelationshipsEvents
GetReviewResponseDTO20240715CollectionCompoundDocumentDataInnerAllOfRelationshipsEventsDataInner
->GetReviewResponseDTOCollectionCompoundDocumentDataInnerAllOfRelationshipsEventsDataInner
GetReviewResponseDTO20240715CompoundDocument
->GetReviewResponseDTOCompoundDocument
GetReviewResponseDTO20240715CompoundDocument
->GetReviewResponseDTOCompoundDocument
GetSegmentTagRelationshipListResponseCollection
->GetSegmentTagsRelationshipsResponseCollection
ReviewResponseDTO20240715ObjectResource
->ReviewResponseDTOObjectResource
ReviewResponseDTO20240715ObjectResourceAttributes
->ReviewResponseDTOObjectResourceAttributes
- Breaking: New
RetryWithExponentialBackoff
class for smart retries to replace thetenacity
retry decorator that wraps each API method. - Breaking: Renamed models:
GetCampaignMessagesRelationshipListResponseCollection
->GetCampaignMessagesRelationshipsResponseCollection
GetCampaignMessagesRelationshipListResponseCollectionDataInner
->GetCampaignMessagesRelationshipsResponseCollectionDataInner
GetTagGroupTagRelationshipsResponseCollection
->GetTagGroupTagsRelationshipsResponseCollection
GetTagGroupTagRelationshipsResponseCollectionDataInner
->GetListListResponseCollectionCompoundDocumentDataInnerAllOfRelationshipsTagsDataInner
GetTagTagGroupRelationshipsResponse
->GetTagGroupRelationshipResponse
GetTagTagGroupRelationshipsResponseData
->GetTagResponseCollectionCompoundDocumentDataInnerAllOfRelationshipsTagGroupData
GetCouponCodeRelationshipCouponResponse
->GetCouponCodeCouponRelationshipResponse
GetCouponCodeRelationshipCouponResponseData
->GetCouponCodeCouponRelationshipResponseData
GetFlowMessageFlowActionRelationshipResponse
->GetFlowMessageActionRelationshipResponse
GetMetricPropertyRelationshipMetricResponse
->GetMetricPropertyMetricRelationshipResponse
GetMetricPropertyRelationshipMetricResponseData
->GetEventMetricRelationshipResponseData
GetMetricRelationshipMetricPropertyResponseCollection
->GetMetricPropertiesRelationshipsResponseCollection
GetMetricRelationshipMetricPropertyResponseCollectionDataInner
->GetMetricPropertiesRelationshipsResponseCollectionDataInner
GetProfileImportJobListRelationshipsResponseCollection
->GetProfileBulkImportJobListsRelationshipsResponseCollection
- Lazy imports (optional)
- Set
KLAVIYO_PYTHON_SDK_LAZY_IMPORTS
environment variable totrue
to use lazy imports, which will reduce initial load time of library - Note that using this option may break imports from
openapi_client
- See README for more details
- Set
- Breaking: renamed several models:
GetCampaignMessageTemplateRelationshipListResponse
->GetCampaignMessageTemplateRelationshipResponse
GetListFlowTriggersRelationshipResponseCollection
->GetListFlowTriggersRelationshipsResponseCollection
GetMetricFlowTriggersRelationshipResponseCollection
->GetMetricFlowTriggersRelationshipsResponseCollection
PostListCreateResponseDataRelationshipsFlowTriggers
->GetMetricResponseCollectionCompoundDocumentDataInnerAllOfRelationshipsFlowTriggers
GetMetricFlowTriggersRelationshipResponseCollectionDataInner
->GetMetricResponseCollectionCompoundDocumentDataInnerAllOfRelationshipsFlowTriggersDataInner
- Universal Content API
- Read, update, and delete universal content
- For more information, see our Universal Content API overview
- Form Reporting API
- Query form performance
- For more information, see our Reporting API overview
- Segment Reporting API
- Query segment growth data
- For more information, see our Reporting API overview
- Reviews API
- Get and list reviews
- For more information, see our Reviews API overview
- Tracking Settings API
- Read and update the Tracking Settings for an account (Account -> Settings -> UTM Tracking in UI)
- For more information, see our Tracking Settings API documentation
- Metric Properties API
- Access the properties for a given metric (e.g. "Placed Order")
- For more information, see our Metric Properties API documentation
- Suppress/Unsuppress profile job APIs
- Monitor the status of jobs created by Suppress Profiles and Unsuppress Profiles requests
- For more information, see our Suppress Profiles Job API documentation
Profiles.create_or_update_profile
has been updated to an enhanced identity resolution processor to better follow the Klaviyo identity resolution identifier priority order- Added support for
$locale
property forProfiles
- Numerous methods have been renamed as part of a large renaming effort - the old methods are now deprecated aliases
- Breaking
- Fixed types in several DTO classes
- Added several method aliases based on previous operation IDs
- Breaking
- Removed incorrect
links
property from several DTO classes. From issue #64
- Removed incorrect
- Typing error when using
additional_fields_profile=['subscriptions']
onget_profiles
. From issue #61
- Typed Responses (Breaking change)
-
By default, all API methods will return a type representing the response payload instead of dictionary, as was the case in previous versions of this SDK. Using the typed response, you can access fields of a response using dot notation, like so:
from klaviyo_api import KlaviyoAPI client = KlaviyoAPI( api_key, max_delay=0, max_retries=0 ) profiles = client.Profiles.get_profiles() profile_id = profiles.data[0].id profile = client.Profiles.get_profile(profile_id) profile_id = profile.data.id profile_email = profile.data.attributes.email print(type(profile).__name__) # prints GetProfileResponseCompoundDocument
The class used in this example is found here.
This is a breaking change, as response objects will now require dot notation to access their fields versus the subscriptable access method used for dictionaries, i.e.
profile.data.id
vsprofile['data']['id']
. We have provided a backwards compatibility strategy to smooth the transition from dictionary responses to typed responses.To maintain backwards compatibility with previous versions of this SDK, we have added an
options
argument that allows you to continue using dictionaries as response values. There are two ways to use thisoptions
argument:from klaviyo_api import KlaviyoAPI from openapi_client.api_arg_options import USE_DICTIONARY_FOR_RESPONSE_DATA client = KlaviyoAPI( api_key, max_delay=0, max_retries=0 ) # 1: Passing options to an individual API method profiles = client.Profiles.get_profiles(options= { USE_DICTIONARY_FOR_RESPONSE_DATA: True }) profile_id = profiles["data"][0]['id'] profile_email = profiles["data"][0]['attributes']['email'] # 2: Passing options to API Client dictionary_client = KlaviyoAPI( api_key, max_delay=0, max_retries=0, options={USE_DICTIONARY_FOR_RESPONSE_DATA : True} ) profiles_ = dictionary_client.Profiles.get_profiles() profile_0_id = profiles_["data"][0]['id'] profile_0 = dictionary_client.Profiles.get_profile(id=profile_0_id) profile_0_email = profile_0["data"]['attributes']['email']
The first way will only return a dictionary for that specific
get_profiles
call. The second makes it so that all API methods called usingdictionary_client
will return dictionaries as responses. -
Some API methods still return response data that is not fully typed. See the Untyped Response Data for Specific APIs in the README for more details.
-
- Filter Builder - A new class to help construct filter query parameters.
old_date = datetime.datetime(2023, 8, 15, 12, 30, 0, 0, tzinfo=datetime.timezone.utc) f = FilterBuilder() f.any("email", ["[email protected]", "[email protected]"]) f.greater_than("created", old_date) # f.build() returns 'any(email,["[email protected]","[email protected]"]),greater-than(created,2023-08-15T12:30:00+00:00)' profile_response = client.Profiles.get_profiles(filter=f.build()) # You can also chain FilterBuilder methods f = FilterBuilder() filters = f.any("email", ["[email protected]", "[email protected]"]).greater_than("created", date).build() assert filters == "any(email,['[email protected]','[email protected]']),greater-than(created,2023-08-15T12:30:00+00:00)"
- Forms API
- New
klaviyo.Forms
class with methods to get forms, form versions and relationships - Webhooks API
- new
klaviyo.Webooks
class containing CRUD operations for webhooks
klaviyo.Profiles.subscribe()
- added
historical_import
flag for importing historically consented profiles can now be optionally supplied in the payload for the Subscribe Profiles endpoint. - When using this flag, a consented_at date must be provided and must be in the past.
-
Segments Api
- New create segment endpoint
SegmentsApi.createSegment()
. - New delete segment endpoint
SegementsApi.deleteSegment()
. - Updated exisiting segments endpoints to include the segment definition
- For more information, see our Segments API overview.
- New create segment endpoint
-
Flows Api
- New delete flows endpoint
FlowsApi.deleteFlow()
- New delete flows endpoint
- Fixes issue where
filter
query params for any API call were being duplicated on request send. See issue: #51
- Bulk Create Events API with
- We have added support for creating events in bulk via the EventsApi.bulkCreateEvents method
- Create multiple events for new and existing profiles and/or update profile properties in a single API call. For more information, see our Events API overview.
-
Accounts API
Accounts.get_account
andAccounts.get_accounts
have been updated to return the account's locale, e.g."en-US"
.
-
Breaking
- Subscribe API Synchronous Validation Improved
- To provide better feedback for handling SMS subscriptions, we’ve added improved validation behavior to ProfilesApi.subscribeProfiles method. In prior revisions, such requests may appear as 202s but will fail to update SMS consent. To handle this issue, 400 validation errors are returned for the following cases
- If a profile is subscribed to SMS marketing and age-gating is enabled but age_gated_date_of_birth is not provided, or the DOB does not meet the region's requirements.
- If the account does not have a sending number in the phone number’s region.
- If the phone number is in a region not supported by Klaviyo.
- If consented_at is set and the list or global setting is double opt-in.
- To provide better feedback for handling SMS subscriptions, we’ve added improved validation behavior to ProfilesApi.subscribeProfiles method. In prior revisions, such requests may appear as 202s but will fail to update SMS consent. To handle this issue, 400 validation errors are returned for the following cases
- Pydantic V2
- This SDK now uses Pydantic V2. This may cause some compatibility issues if your source code depends on Pydantic V1.
- Renamed Fields in SDK
-
As of the 2024-05-15 release, some models fields are named differently than they appear in API documentation. These fields are
datetime
: renamed todatetime_
date
: renamed todate_
This is to manage compatibility with Pydantic v2. An example of this can be seen in StaticScheduleOptions.
class StaticScheduleOptions(BaseModel): """ StaticScheduleOptions """ # noqa: E501 datetime_: datetime = Field(description="The time to send at", alias="datetime") schedule_options = StaticScheduleOptions(datetime_=datetime.datetime.strptime("2024-05-19T00:00:00+00:00", "%Y-%m-%dT%H:%M:%S%z") print(schedule_options.datetime_)
-
- Subscribe API Synchronous Validation Improved
-
New
ReportingApi
allows you to request campaign and flow performance data that you can view in the Klaviyo UI. -
campaign_values_query
- Request campaign analytics data, for example, a campaign performance report on the open rate over the past 30 days.
-
flow_values_query
- Request flow analytics data, for example, a flow performance report on the revenue per recipient value over the past 3 months.
-
flow_series_query
- Fetch flow series data for a specific interval and timeframe, for example, a flow performance report on weekly click rates over the past 12 months.
-
New
ProfilesApi
endpoint allows you to create or update a profile with a set of profile attributes.create_or_update_profile
- This endpoint operates synchronously and offers an upsert pattern similar to the v1/v2 Identify API.
-
Removed the $attribution field from event_properties in get_event and get_events (breaking change).
- To include this data in your request, add include=attributions to your request.
We have added the following endpoints to enable bulk profile imports:
Profiles.spawn_bulk_profile_import_job
Profiles.get_bulk_profile_import_job
Profiles.get_bulk_profile_import_jobs
Profiles.get_bulk_profile_import_job_lists
Profiles.get_bulk_profile_import_job_profiles
Profiles.get_bulk_profile_import_job_import_errors
Profiles.get_bulk_profile_import_job_relationships_profiles
Profiles.get_bulk_profile_import_job_relationships_lists
When using Profiles.subscribe_profiles
, the relationships
field of the payload is now optional (see Profiles.subscribe_profiles reference for details).
A bug was introduced in version 5.0.0 until this patch, that resulted in this SDK specifically returning None upon success for the following operation Metrics.query_metrics_aggregates.
Support for returning list suppressions via the /profiles endpoint
We now support filtering on list suppression with the get profiles endpoint, which brings us to parity with v2 list suppression endpoint that was the previously recommended solution.
Rules for suppression filtering:
- You may not mix-and-match list and global filters
- You may only specify a single date filter
- You may or may not specify a reason
- You must specify a list_id to filter on any list suppression properties
Examples:
- To return profiles who were suppressed after a certain date:
filter="greater-than(subscriptions.email.marketing.suppression.timestamp,2023-03-01T01:00:00Z)"
- To return profiles who were suppressed from a specific list after a certain date:
filter="greater-than(subscriptions.email.marketing.list_suppressions.timestamp,2023-03-01T01:00:00Z),equals(subscriptions.email.marketing.list_suppressions.list_id,\"LIST_ID\")"
- To return all profiles who were suppressed for a specific reason after a certain date:
filter="greater-than(subscriptions.email.marketing.suppression.timestamp,2023-03-01T01:00:00Z),equals(subscriptions.email.marketing.suppression.reason,\"user_suppressed\")"
Optionally retrieve subscription status on Get List Profiles, Get Segment Profiles, Get Event Profile
Now you can retrieve subscription status on any endpoint that returns profiles, including Get List Profiles, Get Segment Profiles and Get Event Profile. Use additional_fields_profile="subscriptions"
on these endpoints to include subscription information.
The subscription object is no longer returned by default with get profile(s) requests. However, it can be included by adding the additional_fields_profile="subscriptions"
to the request. This change will allow us to provide a more performant experience when making requests to Get Profiles without including the subscriptions object.
In the interest of providing more clarity and information on the subscription object, we have renamed several fields, and added several as well. This will provide more context on a contact's subscriptions and consent, as well as boolean fields to see who you can or cannot message.
For SMSMarketing:
timestamp
is nowconsent_timestamp
last_updated
is a new field that mirrorsconsent_timestamp
can_receive_sms_marketing
is a new field which isTrue
if the profile is consented for SMS
For EmailMarketing:
timestamp
is nowconsent_timestamp
can_receive_email_marketing
is True if the profile does not have a global suppressionsuppressions
is nowsuppression
last_updated
is a new field that is the most recent of all the dates on the object
Images
API- We now support the following operations to work with images:
get_image
get_images
update_image
upload_image_from_file
upload_image_from_url
- We now support the following operations to work with images:
Coupons
API- We now support CRUD operations for both Coupons and Coupon Codes
- Check out Coupons API guide for more information.
- Additional filtering/sorting option for getting profiles from
Lists
andSegments
:joined_group_at
- New profile merge endpoint:
Profiles.merge_profiles
- Increased the maximum page size limit for
Lists.get_list_relationships_profiles
andSegments.get_segment_relationships_profiles
to 1000
- override
api_key
with OAuth access token by setting clientaccess_token
keyword arg
- Fixed a bug that was impacting the
unset
functionality forupdate_profile
- Flow Message Template endpoints:
- You can now retrieve the templates associated with flow messages using
Flows.get_flow_message_template()
orFlows.get_flow_message_relationships_template()
. You can also include the template HTML for a flow message usingFlows.get_flow_message(id, include=['template'])
.
- You can now retrieve the templates associated with flow messages using
- Create or Update Push Token endpoint:
- We have added an endpoint to create or update push tokens,
Profiles.create_push_token()
. This endpoint can be used to migrate profiles and their push tokens from another platform to Klaviyo. If you’re looking to register push tokens from users’ devices, please use our mobile SDKs.
- We have added an endpoint to create or update push tokens,
- To override the client-level
api_key
for a specific request, you will now need to use the following new keyword arg:_request_auth
- previously, this keyword arg was called
api_key
- previously, this keyword arg was called
- Fixed errors that were occurring on requests using oneOf schemas
- Back-In-stock APIs
- We have added support for subscribing profiles to back-in-stock notifications, for both email and SMS, using the new create_back_in_stock_subscription endpoint.
- New functionality to Campaigns API
- CRUD support for SMS campaigns is now available
- You can now also retrieve all messages for a campaign to determine performance data on campaigns where you’re running A/B tests
- To support this functionality, we introduced a relationship between campaigns and campaign messages, and between campaign messages and templates
- Relationship Standardization
- We are making a number of changes across endpoints to standardize how we handle relationships in our APIs and leverage consistently typed objects across endpoints. For example, 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 changes include:
- Updating 1:1 relationships to use singular tense and an object (instead of plural and an array)
- example: for get_flow_action, if you want to use the
include
param, you would setinclude=
to"flow"
(instead of"flows"
)
- example: for get_flow_action, if you want to use the
- Moving related object IDs from the attributes payload to relationships
- example: The format for the body of create_tag has changed, with
tag_group_id
previously atdata.attributes.tag_group_id
being removed and replaced by adata
object containingtype
+id
and located atdata.relationships.tag-group.data
.
- example: The format for the body of create_tag has changed, with
- Specifying a relationship between two Klaviyo objects to allow for improved consistency and greater interoperability across endpoints
- example: for create_event, you can now create/update a profile for an event in the same way you would when using the profiles API directly
- Updating 1:1 relationships to use singular tense and an object (instead of plural and an array)
- NOTE: The examples for the above relationship changes are illustrative, not comprehensive. For a complete list of ALL the endpoints that have changed and exactly how, please refer to our latest API Changelog
- For get_campaigns endpoint,
filter
param is now required, to, at minimum, filter onmessages.channel
- We removed the
company_id
from the response for get_template and get_templates. If you need to obtain the company ID / public API key for an account, please use the Accounts API.
- Accounts API is now available, this will allow you to access information about the Klaviyo account associated with your API key.
get_accounts
get_account
Note: You will need to generate a new API key with either the Accounts
scope enabled or Full Access
to use these endpoints.
- The names of positional arguments have changed from
[resource_type]_id
toid
(i.e.campaign_id
toid
) for some relationship endpoints. If keyword arguments were used instead of positional arguments for[resource_type]_id
you might need to slightly refactor the code.
- All
client
endpoint:create_client_event
create_client_profile
create_client_subscription
- Profiles API now returns predictive analytics when calling
get_profile
andget_profiles
by passing inadditional_fields_profile = ["predictive_analytics"]
.
- Relationship endpoints that were previously grouped together are now split into related-resource-specific endpoints. This means that all relationship endpoints have new function names.
- To migrate to this latest version, all calls to relationship endpoints need to be updated, as in the following example:
get_campaign_relationships(campaign_id, "tags")
will becomeget_campaign_relationships_tags(campaign_id)
.
- Added
page_size
support for paging through endpoints that return profiles.
- Fixed a bug that caused paging through events to periodically fail.
- Added support for Campaigns (which were previously in our Beta API/SDKs).
- Pagination for Flows changed from page offset to cursor.
- Added the following endpoints (which were previously in our Beta API/SDKs):
- Data Privacy
- All Tags endpoints, as well as the following related resource-specific endpoints:
- Get Flow Tags
- Get List Tags
- Get Segment Tags
- Initial release
- Namespace changes:
- Pypi package name:
klaviyo–sdk-beta
→klaviyo-api
- Module name:
klaviyo_sdk_beta
→klaviyo_api
- client name:
Client
→KlaviyoAPI
- Client variable name in readme examples:
client
→klaviyo
- Some functions have changed name
- Pypi package name:
- New resources and endpoints: see API Changelog for full details