Skip to main content
Contributor I
April 30, 2025
Solved

Klaviyo Oauth Endpoint Not Working

  • April 30, 2025
  • 1 reply
  • 105 views

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.

    Best answer by whereisjad

    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=['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

     

    1 reply

    whereisjad
    Expert Problem Solver IV
    Expert Problem Solver IV
    April 30, 2025

    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=['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

     

    — Jad A | Klaviyo + Shopify + API Integrations Specialist • 7+ Years' Experience Helping with new setups, seamless integrations, and API connections—happy to connect. http://ja-technical-consulting.xyz/