Using refresh token always fails - any hints?

StuartStuart Member Posts: 5

Hi all, looking for any tips on successfully using the refresh token to generate a new access token. I am assuming I am missing something elementary but I've been staring at it too long not to ask.

I've attempted this in a variety of environments, such as cURL, Python, Javascript, and Postman.

Always with the same results:

  1. I can successfully generate a temporary token
  2. I can successfully use the temporary token to generate an accesss token & refresh token
  3. I can successfully use the access token to query the API (before expiry)
  4. But all attempts to use the refresh_token to generate a new access token fail with {'error': 'invalid_grant', 'error_description': "refresh_token doesn't exist or is invalid for the client"}

I've reviewed this documentation:

I've also read this comment from Lightspeed which implies the documentation is inaccurate:

And the code they link to:

And this code too:

In each instance, I'm using the same endpoint ( ) for requesting an access code & refresh code, and the only change is the payload. The grant_type changes and instead of the code attribute, I use the referesh_token attribute. The auth payload works, the refresh payload fails.

Here's some python I've tried, to generate an access code and then immediately use the refresh code. (I know you wouldn't normally do that right away, I'm just trying to get a demo working so I have the confidence go on and create something useful.)

Any hints or pointers would be welcome.


# enter temp token here

temporary_Token = 'abc123'

client_ID     = '1234567890'

client_Secret = 'abc123xyz789'

import requests

import json

url = ""

headers = { 'content-type': 'application/json' }

auth_payload = {

    "client_id": client_ID,

    "client_secret": client_Secret,

    "code": temporary_Token,

    "grant_type": "authorization_code"}

print('auth_payload:\n', auth_payload, '\n\n')

r = requests.request("POST", url, data=json.dumps(auth_payload), headers=headers )

#Logs credentials to the virtual console

print('auth response: \n', r.json(), '\n\n')

data = r.json()

access_token = data['access_token'];

refresh_token = data['refresh_token'];

print('access_token: ', access_token);

print('refresh_token: ', refresh_token);

refresh_payload = {

    "client_id": client_ID,

    "client_secret": client_Secret,

    "refresh_token": refresh_token,

    "grant_type": "refresh_token"}

print('refresh_payload:\n', refresh_payload, '\n\n')

r = requests.request("POST", url, data=json.dumps(refresh_payload), headers=headers )

#Logs credentials to the virtual console

print('auth response: \n', r.json(), '\n\n')

data = r.json()

Best Answer

  • StuartStuart Member Posts: 5
    Answer ✓

    This is resolved.

    It seems as if the client_ID is case sensitive when used to refresh the access token, but not when doing the initial temporary token or the initial access token.

    So my client_ID starts with a letter, which I guess got capitalized by an editor somewhere along the way, but the API allowed me to use it anyway so I didn't notice anything was wrong until I tried to refresh. Since I was using the same client_ID for all types of requests, it never occured to me that one would be case sensitive and another wouldn't.

    Would be great if this behaviour was either made consistent or at least documented :) but regardless it works now.

    This posting was the initial clue:


  • AlexBeaudetAlexBeaudet Member Posts: 35

    hahaha yep quite random indeed and you only get to know this by butting your head at the problem for a few hours before coming here...

    glad you got it worked out! Probably did the same thing as me in pasting the secret in OneNote and it capitalized it haha

Sign In or Register to comment.