Skip to main content
federico.vitale
Problem Solver I
Problem Solver I
September 30, 2024
Solved

Authentication error with Python SDK

  • September 30, 2024
  • 4 replies
  • 215 views

Hi all!

One quick questions about a thing I’m trying to do in Django Python: I’m setting up a signal that creates/updates the user data to Klaviyo when the user is created/updated.

I tried to do the same via http requests in the same environment (same key, same objects) and it all works.

When trying with the Python API, it returns an unathorized error (401). I troubleshooted the issue checking:

  • that the key has both the string and the key, it has
  • that the key has the correct permissions, it has

At this point I’m out of all ideas. I’m afraid something is missing from my code, but as far as I saw on the guides on GitHub I cannot find the missing element.

My code is this:

from django.conf import settings
from klaviyo_api import KlaviyoAPI

import pprint
import traceback

private_key = settings.KLAVIYO_PRIVATE_KEY
klaviyo = KlaviyoAPI(api_key=private_key, max_delay=5, max_retries=3)

def create_update_profile(user):
payload = {
"data": {
"type": "profile",
"attributes": {
"email": user.email,
"phone_number": user.prefix + user.phone,
"external_id": str(user.id),
"first_name": user.first_name,
"last_name": user.last_name,
"location": {
"address1": user.address,
"city": user.city,
"country": "Italy",
"region": user.province,
"zip": user.zipCode,
"timezone": "Europe/Rome"
},
"properties": {
"Gender": user.gender,
"Birthday": user.birthday.strftime('%Y-%m-%d')
}
}
}
}

try:
k_profile = klaviyo.Profiles.create_or_update_profile(payload)
pprint(f'Job done: {k_profile}')
return k_profile

except Exception as e:
pprint.pprint(e)
traceback.print_exc()
return None

And this is the error:

openapi_client.exceptions.UnauthorizedException: (401)
Reason: Unauthorized
HTTP response headers: HTTPHeaderDict({'Date': 'Mon, 30 Sep 2024 09:07:41 GMT', 'Content-Type': 'application/vnd.api+json', 'Content-Length': '264', 'Connection': 'keep-alive', 'CF-Ray': '8cb31067ca4dbabe-MXP', 'CF-Cache-Status': 'DYNAMIC', 'Allow': 'POST, OPTIONS', 'Content-Language': 'en-us', 'Strict-Transport-Security': 'max-age=31536000; includeSubDomains; preload', 'Vary': 'Accept-Language, Cookie, Accept-Encoding', 'WWW-Authenticate': 'Bearer, Klaviyo-API-Key', 'Content-Security-Policy': "script-src 'report-sample' 'strict-dynamic' 'unsafe-eval'; object-src 'none'; base-uri 'none'; frame-ancestors 'self' login.bigcommerce.com *.mybigcommerce.com admin.shopify.com klaviyo.file.force.com klaviyo.lightning.force.com klaviyo.my.salesforce.com; report-uri /csp/", 'X-Content-Type-Options': 'nosniff', 'X-Robots-Tag': 'noindex, nofollow', 'Server': 'cloudflare'})
HTTP response body: errors=[GetAccounts4XXResponseErrorsInner(id='e8249737-283b-4db2-b1b1-fa324fe71f02', code='not_authenticated', title='Authentication credentials were not provided.', detail='Missing or invalid authorization scheme. Please use Klaviyo-API-Key.', source=GetAccounts4XXResponseErrorsInnerSource(pointer='/data/', parameter=None))]

Can any of you help me out on this?

Thank you in advance!

Federico

    This topic has been closed for replies.
    Best answer by chloe.strange

    Hi @federico.vitale

    You have the following:
    private_key = 'Klaviyo-API-Key pk_0bc882e60f0b6c97975e27383c68e*****'

    Please try the following - note that it does not include the Klaviyo-API-Key prefix:
    private_key = pk_0bc882e60f0b6c97975e27383c68e*****

    If you were doing a raw http request, then this would be in the header but the client is expecting an API key without the prefix
    Authorization: Klaviyo-API-Key your-private-api-key'

    ~Chloe 

    4 replies

    chloe.strange
    Community Manager
    Community Manager
    October 3, 2024

    Hi @federico.vitale 

    The error indicates that there is a missing or invalid key passed in the authorization header in the request initiated by the Klaviyo python client

    1. please tell us what version of the python klaviyo API client you are using
    2. please try running this exact same operation creating a test user with the client in a script outside of django and set the API key manually to make sure there isn't an issue with django settings resolution
    3. please print the value of `settings.KLAVIYO_PRIVATE_KEY` in your example and verify it is set with the expected private key

    ~Chloe

    federico.vitale
    Problem Solver I
    Problem Solver I
    October 3, 2024

    Hi @chloe.strange!

    Thanks for getting back to me. Going through your list:

    please tell us what version of the python klaviyo API client you are using

    federicovitale@MacBook-Pro-di-Federico ~ % pip3 show klaviyo-api
    Name: klaviyo-api
    Version: 13.0.0
    Summary: Klaviyo Python SDK
    Home-page: https://github.com/klaviyo/klaviyo-api-python
    Author: Klaviyo Developers
    Author-email: developers@klaviyo.com
    License: UNKNOWN
    Location: /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages
    Requires: aenum, pydantic, python-dateutil, setuptools, tenacity, urllib3
    Required-by:

    2. please try running this exact same operation creating a test user with the client in a script outside of django and set the API key manually to make sure there isn't an issue with django settings resolution

    3. please print the value of `settings.KLAVIYO_PRIVATE_KEY` in your example and verify it is set with the expected private key

    I ran a script directly on the Python IDE, also outside any virtual environment (the key is redacted here but not when I ran the script):

    from klaviyo_api import KlaviyoAPI
    import pprint
    import traceback

    private_key = 'Klaviyo-API-Key pk_0bc882e60f0b6c97975e27383c68e*****'

    klaviyo = KlaviyoAPI(api_key=private_key)

    payload = {
    "data": {
    "type": "profile",
    "attributes": {
    "email": "federico@test.test",
    "first_name": "Federico",
    "last_name": "Vitale",
    "properties": {
    "Gender": "Male",
    "Birthday": "1987-09-21"
    }
    }
    }
    }

    try:
    k_profile = klaviyo.Profiles.create_or_update_profile(payload)
    pprint(k_profile)

    except Exception as e:
    pprint.pprint(e)
    traceback.print_exc()

    Here the result:

    UnauthorizedException()
    Traceback (most recent call last):
    File "/Users/federicovitale/Desktop/Test_klaviyo.py", line 25, in <module>
    k_profile = klaviyo.Profiles.create_or_update_profile(payload)
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages/klaviyo_api/wrapper.py", line 441, in _wrapped_func
    return func(*args,**kwargs)
    ^^^^^^^^^^^^^^^^^^^^
    File "/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages/tenacity/__init__.py", line 336, in wrapped_f
    return copy(f, *args, **kw)
    ^^^^^^^^^^^^^^^^^^^^
    File "/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages/tenacity/__init__.py", line 475, in __call__
    do = self.iter(retry_state=retry_state)
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages/tenacity/__init__.py", line 376, in iter
    result = action(retry_state)
    ^^^^^^^^^^^^^^^^^^^
    File "/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages/tenacity/__init__.py", line 398, in <lambda>
    self._add_action_func(lambda rs: rs.outcome.result())
    ^^^^^^^^^^^^^^^^^^^
    File "/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/concurrent/futures/_base.py", line 449, in result
    return self.__get_result()
    ^^^^^^^^^^^^^^^^^^^
    File "/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/concurrent/futures/_base.py", line 401, in __get_result
    raise self._exception
    File "/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages/tenacity/__init__.py", line 478, in __call__
    result = fn(*args, **kwargs)
    ^^^^^^^^^^^^^^^^^^^
    File "/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages/pydantic/validate_call_decorator.py", line 60, in wrapper_function
    return validate_call_wrapper(*args, **kwargs)
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages/pydantic/_internal/_validate_call.py", line 96, in __call__
    res = self.__pydantic_validator__.validate_python(pydantic_core.ArgsKwargs(args, kwargs))
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages/openapi_client/api/profiles_api.py", line 149, in create_or_update_profile
    return self.api_client.response_deserialize(
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages/openapi_client/api_client.py", line 328, in response_deserialize
    raise ApiException.from_response(
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages/openapi_client/exceptions.py", line 146, in from_response
    raise UnauthorizedException(http_resp=http_resp, body=body, data=data)
    openapi_client.exceptions.UnauthorizedException: (401)
    Reason: Unauthorized
    HTTP response headers: HTTPHeaderDict({'Date': 'Thu, 03 Oct 2024 16:02:47 GMT', 'Content-Type': 'application/vnd.api+json', 'Content-Length': '264', 'Connection': 'keep-alive', 'CF-Ray': '8cce2895ca37bad0-MXP', 'CF-Cache-Status': 'DYNAMIC', 'Allow': 'POST, OPTIONS', 'Content-Language': 'en-us', 'Strict-Transport-Security': 'max-age=31536000; includeSubDomains; preload', 'Vary': 'Accept-Language, Cookie, Accept-Encoding', 'WWW-Authenticate': 'Bearer, Klaviyo-API-Key', 'Content-Security-Policy': "object-src 'none'; frame-ancestors 'self' login.bigcommerce.com *.mybigcommerce.com admin.shopify.com klaviyo.file.force.com klaviyo.lightning.force.com klaviyo.my.salesforce.com; base-uri 'none'; script-src 'report-sample' 'strict-dynamic' 'unsafe-eval'; report-uri /csp/", 'X-Content-Type-Options': 'nosniff', 'X-Robots-Tag': 'noindex, nofollow', 'Server': 'cloudflare'})
    HTTP response body: errors=[GetAccounts4XXResponseErrorsInner(id='35b6281d-9f4c-465e-94aa-09543e5b892d', code='not_authenticated', title='Authentication credentials were not provided.', detail='Missing or invalid authorization scheme. Please use Klaviyo-API-Key.', source=GetAccounts4XXResponseErrorsInnerSource(pointer='/data/', parameter=None))]

    Thank you again for any assistance!

    chloe.strange
    Community Manager
    Community Manager
    October 3, 2024

    Hi @federico.vitale

    You have the following:
    private_key = 'Klaviyo-API-Key pk_0bc882e60f0b6c97975e27383c68e*****'

    Please try the following - note that it does not include the Klaviyo-API-Key prefix:
    private_key = pk_0bc882e60f0b6c97975e27383c68e*****

    If you were doing a raw http request, then this would be in the header but the client is expecting an API key without the prefix
    Authorization: Klaviyo-API-Key your-private-api-key'

    ~Chloe 

    federico.vitale
    Problem Solver I
    Problem Solver I
    October 4, 2024

    @chloe.strange, thank you so much!!! It works!