Skip to main content

I was previously using these URLs for OAuth which have since been deprecated https://developers.klaviyo.com/en/docs/set_up_oauth
 

Authorization URL: 'https://www.klaviyo.com/oauth/authorize'

Token URL: 'https://www.klaviyo.com/oauth/token’


I attempted to update to these URLs
 

Authorization URL: 'https://a.klaviyo.com/oauth/authorize'

Token URL: 'https://a.klaviyo.com/oauth/token'


However, the Authorization URL does not work for me. Whenever I hit the new URL(https://a.klaviyo.com/oauth/authorize) with the same parameters used with the previous authorization url(https://www.klaviyo.com/oauth/authorize) I am redirected to a blank page and nothing happens.

I now have a split solution where I am using the following and everything is functioning: 

 

Authorization URL: 'https://www.klaviyo.com/oauth/authorize'

Token URL: 'https://a.klaviyo.com/oauth/token'

Is there a known bug with the new Authorization URL(https://a.klaviyo.com/oauth/authorize)? I am unable to kick of the OAuth flow using it.

hopefully code below helps you.  It allows you to perform the OAuth handshake using a Python app you can run locally using Flask library (you will need to enter the CLIENT_ID and CLIENT_SECRET values for your OAuth app created in Klaviyo):

from flask import Flask, request, redirect

app = Flask(__name__)



import urllib.parse

import requests

import base64



# use  https://tonyxu-io.github.io/pkce-generator/ to generate these

CODE_CHALLENGE = "”

CODE_VERIFIER = ""



REDIRECT_URI = "http://localhost:5001/callback"

BASE_URL = "http://klaviyo.com"

ASYNC_BASE_URL = "https://a.klaviyo.com"



CLIENT_ID = ""

CLIENT_SECRET = ""


# feel free to modify as suitable
SCOPES = "accounts:read accounts:write campaigns:read campaigns:write catalogs:read catalogs:write data-privacy:read data-privacy:write events:read events:write flows:read flows:write images:read images:write lists:read lists:write metrics:read metrics:write profiles:read profiles:write segments:read segments:write subscriptions:read subscriptions:write tags:read tags:write templates:read templates:write webhooks:read webhooks:write list-and-segments:read list-and-segments:write push-tokens:read push-tokens:write coupons:read coupons:write coupon-codes:read coupon-codes:write conversations:read conversations:write reviews:read reviews:write forms:read forms:write"



ENCODED_CLIENT_INFO = base64.b64encode(f"{CLIENT_ID}:{CLIENT_SECRET}".encode()).decode()



@app.get("/")

def read_root():

params = dict(

client_id=CLIENT_ID,

response_type="code",

redirect_uri=REDIRECT_URI,

scope=SCOPES,

state="NONCE",

code_challenge_method="S256",

code_challenge=CODE_CHALLENGE,

)

encoded_params = urllib.parse.urlencode(params)

return redirect(f"{BASE_URL}/oauth/authorize?{encoded_params}")



@app.route('/callback', methods=t'GET'])

def callback():

code = request.args.get('code')

print(code)

response = requests.post(

f"{ASYNC_BASE_URL}/oauth/token",

headers={

"Authorization": f"Basic {ENCODED_CLIENT_INFO}",

"Content-Type": "application/x-www-form-urlencoded",

},

data=dict(

grant_type="authorization_code",

code=code,

code_verifier=CODE_VERIFIER,

redirect_uri=REDIRECT_URI,

),

)

print(response.request.headers, response.request.body)

return response.json()



if __name__ == "__main__":

app.run(port=5001)

When you run this app.  It calls Klaviyo and tries to perform the OAuth.  Once successful it will return a JSON with the access token and refresh token as described in:

https://developers.klaviyo.com/en/docs/set_up_oauth#use-the-received-access-token