klaviyo / klaviyo-api-python

Python SDK for Klaviyo API
https://developers.klaviyo.com
MIT License
36 stars 6 forks source link

Unexpected Object Type As Response Instead of JSON #66

Closed ghost closed 1 month ago

ghost commented 1 month ago

When I use the SDK to receive profiles, I get an object of type _<class 'openapi_client.models.get_profile_response_collection_compound_document.GetProfileResponseCollectionCompoundDocument'>_:

from klaviyo_api import KlaviyoAPI
klaviyo = KlaviyoAPI("XXXXXXXX", max_delay=60, max_retries=3, test_host=None)

profiles = klaviyo.Profiles.get_profiles(
    filter='less-than(updated,2024-08-26T00:00:00Z),greater-than(updated,2024-08-24T00:00:00Z)'
)

print(type(profiles))
## <class 'openapi_client.models.get_profile_response_collection_compound_document.GetProfileResponseCollectionCompoundDocument'>

print(profiles)
## [GetProfileResponseCollectionDataInner(type=<ProfileEnum.PROFILE: 'profile'>, id='01HWJR6FX112VTGD2C28DGG0ZW', attributes=ProfileResponseObjectResourceExtendedAttributes(email='XXXXX@yahoo.com', phone_number='+XXXXXXX', .....

This type of response occurs with other endpoints as well.

How do I get a JSON-like response, which I receive when using the requests library?

import requests

url = "https://a.klaviyo.com/api/profiles/?page[size]=20"

headers = {
    "accept": "application/json",
    "revision": "2024-07-15",
    "Authorization": "Klaviyo-API-Key XXXXXXXXXXXX"
}

response = requests.get(url, headers=headers)

print(response.text)
## {"data":[{"type":"profile","id":"01HMGT9SNTPHXTW3B53MJJ37AQ","attributes":{"email":"XXXX@gmail.com","phone_number":null
sanfordj commented 1 month ago

The SDK has recently been converted to return types. It does provide an option to use dictionaries for responses. You can read about how to do that here: https://github.com/klaviyo/klaviyo-api-python/blob/main/CHANGELOG.md#backwards-compatibility

ghost commented 1 month ago

Thank you! Yes, that works. :)

What are the benefits of the new object type? And what would be the best way to loop through each profile in this object and access each profile's attributes?

sanfordj commented 1 month ago

The object types allow you to discover the requirements of the API via typing. It's useful in IDEs for completion, but also if you just want a codified version of the payloads and responses the API uses.

As our APIs implement JSON API protocol, the types themselves are quite nested. We are considering what we can do to pair down these types as part of future work.

Here is an example of what you asked for:

    client = KlaviyoAPI(
        api_key,
    )

    Playground.client = client

    profiles = client.Profiles.get_profiles()

    for profile in profiles.data:
        # access attributes by name
        email = profile.attributes.email
        first_name = profile.attributes.first_name
        print(f"{email} {first_name}")

        # access all attributes of a profile
        attributes_dictionary = profile.attributes.dict()
        for key, value in attributes_dictionary.items():
            print(f"{key}: {value}")
sanfordj commented 1 month ago

closing this issue as all questions were addressed.

ghost commented 1 month ago

Thank you for your help!