Skip to main content
Solved

Authentication error with Python SDK

  • September 30, 2024
  • 4 replies
  • 61 views

federico.vitale
Problem Solver I
Forum|alt.badge.img+2

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

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 

View original
Did this topic or the replies in the thread help you find an answer to your question?

4 replies

chloe.strange
Community Manager
Forum|alt.badge.img+42
  • Community Manager
  • 433 replies
  • 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
Forum|alt.badge.img+2
  • Author
  • Problem Solver I
  • 12 replies
  • 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
Forum|alt.badge.img+42
  • Community Manager
  • 433 replies
  • Answer
  • 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
Forum|alt.badge.img+2
  • Author
  • Problem Solver I
  • 12 replies
  • October 4, 2024

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