Skip to content

Commit

Permalink
version 13.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
klaviyo-sdk committed Sep 23, 2024
1 parent 3fd7b7a commit 3367929
Show file tree
Hide file tree
Showing 35 changed files with 369 additions and 271 deletions.
169 changes: 3 additions & 166 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,173 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

NOTE: For more granular API-specific changes, please see our [API Changelog](https://developers.klaviyo.com/en/docs/changelog_)

## [12.0.0] - 2024-07-15
### Added
- Added several method aliases based on previous operation IDs
## [13.0.0] - 2024-07-15
### Fixed
- **Breaking**
- Removed incorrect `links` property from several DTO classes. From issue https://github.com/klaviyo/klaviyo-api-python/issues/64


## [11.0.1] - 2024-07-15
### Fixed
- Typing error when using `additional_fields_profile=['subscriptions']` on `get_profiles`. From issue https://github.com/klaviyo/klaviyo-api-python/issues/61


## [11.0.0] Typed SDK - revision 2024-07-15

### Added
- 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:
```python
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](src/openapi_client/models/get_profile_response_collection_compound_document.py).

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` vs `profile['data']['id']`. We have provided a [backwards compatibility strategy](#backwards-compatibility) to smooth the transition from dictionary responses to typed responses.

#### Backwards Compatibility
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 this `options` argument:
```python
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 using `dictionary_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](README.md#untyped-response-data-for-specific-apis) in the README for more details.
- Filter Builder - A new class to help construct filter query parameters.
```python
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)"
```


## [10.0.0] - revision 2024-07-15

### Added

- 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

### Changed
- `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.


## [9.0.0] - revision 2024-06-15

### Added
- 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](https://developers.klaviyo.com/en/reference/segments_api_overview).

- Flows Api
- New delete flows endpoint `FlowsApi.deleteFlow()`


## [8.0.1] - revision 2024-05-15

### Added

- Fixes issue where `filter` query params for any API call were being duplicated on request send. See issue: https://github.com/klaviyo/klaviyo-api-python/issues/51


## [8.0.0] - revision 2024-05-15

### Added

- 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](https://developers.klaviyo.com/en/reference/events_api_overview).

### Changed

- Accounts API
- `Accounts.get_account` and `Accounts.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
1. If a profile is subscribed to SMS marketing and [age-gating is enabled](https://help.klaviyo.com/hc/en-us/articles/4408311712667) but age_gated_date_of_birth is not provided, or the DOB does not meet the region's requirements.
2. If the account does not have a sending number in the phone number’s region.
3. If the phone number is in a region not supported by Klaviyo.
4. If consented_at is set and the list or global setting is double opt-in.
- 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 to `datetime_`
- `date`: renamed to `date_`

This is to manage compatibility with Pydantic v2. An example of this can be seen in [StaticScheduleOptions](src/openapi_client/models/static_schedule_options.py).

```python
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_)
```

- Fixed types in several DTO classes

## [7.0.0] - revision 2024-02-15

Expand Down Expand Up @@ -448,4 +285,4 @@ For EmailMarketing:
- client name: `Client``KlaviyoAPI`
- Client variable name in readme examples: `client``klaviyo`
- Some functions have changed name
- New resources and endpoints: see [API Changelog](https://developers.klaviyo.com/en/docs/changelog_) for full details
- New resources and endpoints: see [API Changelog](https://developers.klaviyo.com/en/docs/changelog_) for full details
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Klaviyo Python SDK

- SDK version: 12.0.0
- SDK version: 13.0.0
- API revision: 2024-07-15

## Table of Contents
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "openapi_client"
version = "12.0.0"
version = "13.0.0"
description = "Klaviyo API"
authors = ["Klaviyo Developer Experience Team <[email protected]>"]
license = "License"
Expand Down
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[metadata]
name = klaviyo-api
version = 12.0.0
version = 13.0.0
author = Klaviyo Developers
author_email = [email protected]
description = Klaviyo Python SDK
Expand Down
14 changes: 8 additions & 6 deletions src/openapi_client/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
""" # noqa: E501


__version__ = "12.0.0"
__version__ = "13.0.0"

# import apis into sdk package
from openapi_client.api.accounts_api import AccountsApi
Expand Down Expand Up @@ -467,6 +467,7 @@
from openapi_client.models.get_form_version_form_relationship_response import GetFormVersionFormRelationshipResponse
from openapi_client.models.get_form_version_form_relationship_response_data import GetFormVersionFormRelationshipResponseData
from openapi_client.models.get_form_version_response import GetFormVersionResponse
from openapi_client.models.get_form_version_response_collection import GetFormVersionResponseCollection
from openapi_client.models.get_image_response import GetImageResponse
from openapi_client.models.get_image_response_collection import GetImageResponseCollection
from openapi_client.models.get_import_error_response_collection import GetImportErrorResponseCollection
Expand All @@ -485,11 +486,11 @@
from openapi_client.models.get_list_retrieve_response_compound_document import GetListRetrieveResponseCompoundDocument
from openapi_client.models.get_list_retrieve_response_compound_document_data import GetListRetrieveResponseCompoundDocumentData
from openapi_client.models.get_list_tag_relationship_list_response_collection import GetListTagRelationshipListResponseCollection
from openapi_client.models.get_metric_response_collection import GetMetricResponseCollection
from openapi_client.models.get_metric_response import GetMetricResponse
from openapi_client.models.get_metric_response_collection_compound_document import GetMetricResponseCollectionCompoundDocument
from openapi_client.models.get_metric_response_collection_data_inner import GetMetricResponseCollectionDataInner
from openapi_client.models.get_metric_response_collection_data_inner_all_of_relationships import GetMetricResponseCollectionDataInnerAllOfRelationships
from openapi_client.models.get_metric_response_compound_document import GetMetricResponseCompoundDocument
from openapi_client.models.get_metric_response_data import GetMetricResponseData
from openapi_client.models.get_metric_response_data_all_of_relationships import GetMetricResponseDataAllOfRelationships
from openapi_client.models.get_profile_import_job_list_relationships_response_collection import GetProfileImportJobListRelationshipsResponseCollection
from openapi_client.models.get_profile_import_job_profile_relationships_response_collection import GetProfileImportJobProfileRelationshipsResponseCollection
from openapi_client.models.get_profile_import_job_response_collection_compound_document import GetProfileImportJobResponseCollectionCompoundDocument
Expand All @@ -500,17 +501,18 @@
from openapi_client.models.get_profile_import_job_response_collection_compound_document_data_inner_all_of_relationships_lists_data_inner import GetProfileImportJobResponseCollectionCompoundDocumentDataInnerAllOfRelationshipsListsDataInner
from openapi_client.models.get_profile_import_job_response_compound_document import GetProfileImportJobResponseCompoundDocument
from openapi_client.models.get_profile_list_relationships_response_collection import GetProfileListRelationshipsResponseCollection
from openapi_client.models.get_profile_response import GetProfileResponse
from openapi_client.models.get_profile_response_collection import GetProfileResponseCollection
from openapi_client.models.get_profile_response_collection_compound_document import GetProfileResponseCollectionCompoundDocument
from openapi_client.models.get_profile_response_collection_data_inner import GetProfileResponseCollectionDataInner
from openapi_client.models.get_profile_response_collection_data_inner_all_of_relationships import GetProfileResponseCollectionDataInnerAllOfRelationships
from openapi_client.models.get_profile_response_compound_document import GetProfileResponseCompoundDocument
from openapi_client.models.get_profile_response_compound_document_data import GetProfileResponseCompoundDocumentData
from openapi_client.models.get_profile_response_compound_document_data_all_of_relationships import GetProfileResponseCompoundDocumentDataAllOfRelationships
from openapi_client.models.get_profile_response_compound_document_data_all_of_relationships_lists import GetProfileResponseCompoundDocumentDataAllOfRelationshipsLists
from openapi_client.models.get_profile_response_compound_document_data_all_of_relationships_lists_data_inner import GetProfileResponseCompoundDocumentDataAllOfRelationshipsListsDataInner
from openapi_client.models.get_profile_response_compound_document_data_all_of_relationships_segments import GetProfileResponseCompoundDocumentDataAllOfRelationshipsSegments
from openapi_client.models.get_profile_response_compound_document_data_all_of_relationships_segments_data_inner import GetProfileResponseCompoundDocumentDataAllOfRelationshipsSegmentsDataInner
from openapi_client.models.get_profile_response_data import GetProfileResponseData
from openapi_client.models.get_profile_response_data_all_of_relationships import GetProfileResponseDataAllOfRelationships
from openapi_client.models.get_profile_segment_relationships_response_collection import GetProfileSegmentRelationshipsResponseCollection
from openapi_client.models.get_segment_list_response_collection_compound_document import GetSegmentListResponseCollectionCompoundDocument
from openapi_client.models.get_segment_list_response_collection_compound_document_data_inner import GetSegmentListResponseCollectionCompoundDocumentDataInner
Expand Down
10 changes: 5 additions & 5 deletions src/openapi_client/api/coupons_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -3858,7 +3858,7 @@ def get_coupon_for_coupon_code(
_headers: Optional[Dict[StrictStr, Any]] = None,
_host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
options: Dict[str, Any] = {},
) -> Union[GetCouponResponseCollection, Dict[str, object]]:
) -> Union[GetCouponResponse, Dict[str, object]]:
"""Get Coupon For Coupon Code
Get the coupon associated with a given coupon code ID.<br><br>*Rate limits*:<br>Burst: `75/s`<br>Steady: `700/m` **Scopes:** `coupons:read`
Expand Down Expand Up @@ -3899,7 +3899,7 @@ def get_coupon_for_coupon_code(
)

_response_types_map: Dict[str, Optional[str]] = {
'200': "GetCouponResponseCollection",
'200': "GetCouponResponse",
'4XX': "GetAccounts4XXResponse",
'5XX': "GetAccounts4XXResponse",
}
Expand Down Expand Up @@ -3947,7 +3947,7 @@ def get_coupon_for_coupon_code_with_http_info(
_headers: Optional[Dict[StrictStr, Any]] = None,
_host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
options: Dict[str, Any] = {},
) -> ApiResponse[GetCouponResponseCollection]:
) -> ApiResponse[GetCouponResponse]:
"""Get Coupon For Coupon Code
Get the coupon associated with a given coupon code ID.<br><br>*Rate limits*:<br>Burst: `75/s`<br>Steady: `700/m` **Scopes:** `coupons:read`
Expand Down Expand Up @@ -3988,7 +3988,7 @@ def get_coupon_for_coupon_code_with_http_info(
)

_response_types_map: Dict[str, Optional[str]] = {
'200': "GetCouponResponseCollection",
'200': "GetCouponResponse",
'4XX': "GetAccounts4XXResponse",
'5XX': "GetAccounts4XXResponse",
}
Expand Down Expand Up @@ -4073,7 +4073,7 @@ def get_coupon_for_coupon_code_without_preload_content(
)

_response_types_map: Dict[str, Optional[str]] = {
'200': "GetCouponResponseCollection",
'200': "GetCouponResponse",
'4XX': "GetAccounts4XXResponse",
'5XX': "GetAccounts4XXResponse",
}
Expand Down
Loading

0 comments on commit 3367929

Please sign in to comment.