Using refresh_token to refresh the API access_token


I’ve reached out to support about this but hoping the community might have some input as well.

I have an API Access project that gets issued OAuth2 access tokens for access to users’ locations. The access tokens expire after 24 hours, after which I’m supposed to use the refresh token issued along with to access token to get a new access token.

Unfortunately, the docs are all jumbled on OAuth2 right now, and links that should explain how (and where) to use the refresh token are now broken, or point to generic pages that don’t even mention the refresh_token.

Here’s an example of what I’m trying to do, but I always get either a 401 unauthorized error or a redirect depending on how I compose the POST request or which oauth endpoint I target.

curl -v -XPOST -H "Content-type: application/json" -d '{
    "grant_type": "refresh_token",
    "refresh_token": "<REFRESH_TOKEN>",
    "client_id": "<MY_CLIENT_ID>",
    "client_secret": "<MY_CLIENT_SECRET>"
  }' 'OAuth URL'

I’ve tried including the expired access token as well (both in the body and header of the request) and still no dice. However, I can confirm that, until it expired, the access token was valid, so the 401 unauthorized isn’t an indicator that I’m using the wrong credentials or something.

Does anyone know how to use the refresh_token with the latest version of the ST API (specifically for API Access projects, which may differ from regular SmartApp projects)?

Any guidance is appreciated. Thanks!

Edit: tagging @nayelyz

The request to refresh the Access Token is similar to the one to get the token for the first time. It only changes:

  • The value in “grant_type” from authorization_code to refresh_token.
  • Instead of sending the property code you send refresh_token with the corresponding value

The values of client_id and client_secret must be in the header as “Basic” authorization, concatenated like client_id:client_secret and base64 encoded. For example, using postman, the code for cURL is:

curl --location --request POST 'OAuth URL' \
--header 'Authorization: Basic xxxxxxxx' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=refresh_token' \
--data-urlencode 'refresh_token=xxxxx-xxxxx' \
--data-urlencode 'redirect_uri=https://....'
1 Like

Thanks, Nayely! After getting your example to work in hoppscotch, I was able to put together a minimal working example in Python (which was my ultimate target):

import requests

    "grant_type": "refresh_token", 
    "refresh_token": REFRESH_TOKEN,
    "redirect_uri": REDIRECT_URI

headers={"Content-type": "application/x-www-form-urlencoded"}

resp =


A few notes for anyone happening across this in the future…

  1. Content-Type has to be application/x-www-form-urlencoded, not application/json
  2. This is a POST, not GET, so in be sure to pass data=data, not params=data.
  3. The refresh_token target url is the same as the initial auth url.

@nayelyz One last question – the redirect_uri doesn’t get hit even when the refresh request succeeds. Any idea why?

Thanks again!

What do you mean?
Are you expecting a request in the redirect URI after you receive the response with the new Access Token?

Kinda… What’s the purpose of the redirect_uri?

Mmm…I’m trying to get that information from the engineering team. I’ve only seen that we receive an error in the request if it doesn’t match the one registered in the project of the Developer Workspace.

Ok, in the case of getting the Access Token for the first time, you do need to include the redirect uri but it seems to be used only as a confirmation because it verifies the value matches with the one registered for the API access app in the Developer Workspace.
No request to that URI is received, I just verified that…

However, we don’t need to include the redirect_uri to refresh the Access Token anymore, so it won’t affect if you include the parameter or not.

Thanks, Nayely. This makes total sense. In the initial authorization flow, the redirect_uri is part of the UX – an endpoint to let the end user know that the authorization process is complete, or to alert if something went wrong.

Since the token refresh is purely programmatic, there’s no user (or browser) to redirect at the end of the operation.

I appreciate the followup on this.

1 Like