Using the developer workspace and refresh_token expiration in 30 days in our private workspace smartApp

Hi Everyone,
@erickv @nayelyz We ported from the groovy IDE to the API using the developer mode workspace. The workspace gens the client_id and client_secret which we store away. We refresh the access_token using the refresh_token frequently and with each access store the new refresh_token which is required for the next access_token request. I think I just hit the 30 refresh limit on my test connector for the refresh_token and suddenly the access_token request fails. So the first question:

  1. Does the new refresh_token that comes with the new access_token give you another 30 days after each request? We assumed it would but it may not?

Since ST does not provide a means of publishing our smartApp connector yet we created a private workspace for each of our customers and our concern is that the private workspace has a thirty day limit and then you have to reinstall the connector to start a new cycle. With 50 private workspaces this would be a real problem. So…

  1. Are private workspaces limited to 30 days? If so this is a super problem for us.

I’ve tried getting a new auth code using the SmartThings. Add a little smartness to your things. and reissue but I keep getting a status of 302 (redirect)…

  1. Does the private workspace approach prevent getting a new auth code?

Any help is appreciated,

Hi, @tryagain. As we will discuss some private information regarding your integration, please send an email to with the following information:

  • Confirm the integration type you’re referring to, as I understand you’re developing a SmartApp connector.
  • How often are you refreshing your Access token? it has a 24hrs expiration time. For the refresh token, it is different depending on the integration type:
    • For ST Schema (C2C with OAuth), the refresh token expires when the user removes the integration from his account
    • For SmartApps (thus SmartApp Connectors) and API Access integrations, the refresh token expires in 30 days it doesn’t matter where they were created. (Let me double-check this expiration time)
  • What do you mean by “created a private workspace for each customer”?
  • It would be helpful if you shared the Groovy code you’re trying to migrate to the new development tools. This would help us get more context and provide better suggestions.

Note: Using a private developer workspace should not affect the integration’s behavior. We can discuss this situation further once you send us the email.

Hi Nayely…thank you for getting back to me.

I create a SmartApp connector. In porting from the Groovy IDE I use the API by first creating a project using the ST location Developer Workspace

I follow the create project steps which auto assigns the client_id and client_secret and the appId. The access_token and refresh_token are stored on the St platform and during the INSTALL and UPDATE lifecycles I store both tokens in the database.

There are two types of projects. The first is private and the second is organizational. Organizational is where there is a source owner and other developers have read access to the APIs only. Currently we have 50 customers and some investors interested in our technology and since we can’t publish the Smartapp connector we create a Samsung account for each customer In the groovy IDE with a common redirect_uri to our server. This is tedious but it works. Since there is no publishing support yet in the API we took the same approach. The organizational project failed because only the Orgainzational project owner can access device attributes with the stored access_token. Instead we then created private workspace for each customer account using a common redirect_uri. This works as each Samsung account has there own stored tokens.

We refresh the access_token in a few places of our code along with a scheduled access once a day. This is working fine for each account. Every new access_token also sends a new refresh_token. The new refresh_token is required for the next request of a new access_token. The accesses have worked fine for my test account until I hit the 30 day limit from when I originally installed the ST connector. I assumed that the new refresh_token provided another 30 day refresh_token every time I get it. If I remote the connector and reinstall I appear to get a fresh 30 days.

Question 1 : Does the project setup limit me to 30 days from the day the St connector install? This would kill us as the Groovy IDE does not have an expiry limit for the access or refresh tokens.

We absolutely need a means to programmatically refresh the refresh_token. We can’t uninstall and reinstall the connector for potentially 100s of customers. I tried to get a new auth code from uri SmartThings. Add a little smartness to your things. but keep getting a 302 redirect.

Is there a way to get a new 30 refresh_token?

As far as a groovy ide example…hhmm… its 4k+ lines of code and the access_token is created at install and never expires. So we just pass it along for each customer.

If we could get a way to programmatically get a fresh 30 day refresh token that would fix this.

Nayely, @nayelyz I never tagged you for the above reply…whoops.

No problem, I still get a notification as I configured this post as “watching”.

Thank you for the info, I have some more follow-up questions:

It’s weird that you reach a rate limit if you’re updating the access token once a day. Each new refresh token should expire after 30 days. You’re making this request using each customer client_id and client_secret, right?
Are you using the Node JS SmartApp SDK?

What does your SmartApp Connector do?
This is important because it is recommended when:

  • Your cloud doesn’t support the OAuth 2.0
  • You will use it to create devices combined with a SmartApp functionality

In Groovy IDE, the API access or OAuth integrations were also called SmartApps. If your Groovy SmartApp’s purpose is getting info from the devices of each customer (registered in SmartThings) and provide for example a dashboard to monitor the status, then OAuth Integration is the best option because:

Ok, we are getting closer.

I use the refresh_token to get the access_token example snippet:
def refreshAccessToken(Locations location) {

    String authToken = location.authToken
    String refreshToken = location.refreshToken
    String clientId = location.client_id
    String clientSecret = location.client_secret
 //   String url = ''
    String url = ''
    String basicAuth = Base64.getEncoder().encodeToString((clientId + ':' + clientSecret).getBytes(StandardCharsets.UTF_8))
    MultiValueMap<String,String> params = new LinkedMultiValueMap<String,String>()
    params.add('grant_type', 'refresh_token')
    params.add('refresh_token', refreshToken)
    params.add('client_id', clientId)
    params.add('client_secret', clientSecret)

    String combine = "Basic "+ basicAuth
    def rest = new RestBuilder()
    def response = {
    if(response.status == 200) {
        location.authToken = response.json.access_token
        location.refreshToken = response.json.refresh_token true, flush: true)

This works well and I don’t see a rate time out of any kind. We have an extensive dashboard and can scan the customer base, selecting a residence and query for behavioral activity, movement history, etc…

I do use subscriptions for device activity , a (motionSensor, contactSensor, waterSensor,temperatureMeasurement, and a few others), one minute scheduler, a 10 minute scheduler, hub health (hub online, offline), device health. The subscriptions are based on capability. It works well and very efficient. Each API smartApp connector (one per Samsung Account) can send their events to us through there own smartApp connector which we install using the developer tools (private workspace). All subscriptions do not require access_tokens.

I really only need the access_token per residence to query the devices for their battery value attribute and to do an action on the remote premise…ie open/close locks or raise/lower a garage door or on/off a switch. So that is why the token is required…

I’ve been trying getting a new authorization code but I keep getting a 302 redirect when I use this snippet to try and get another refresh token:
Am I using the right endpoint? I can’t shake the redirect…

def getAuthCode(Locations location) {
String authToken = location.authToken
String refreshToken = location.refreshToken
String url = ‘SmartThings. Add a little smartness to your things.
MultiValueMap<String,String> params = new LinkedMultiValueMap<String,String>()
params.add(‘response_type’, ‘code’)
params.add(‘client_id’, location.client_id)

    println "fred **GETTING** authcode using client_id: ${location.client_id}"

    def rest = new RestBuilder()
    def response = {

I sent you a direct message @tryagain, please review it and we’ll continue our conversation there.