Skip to content
ShiftlyDevelopers
Documentation menu

Stay connected

At the end of this guide your app renews its credentials without anyone signing in again, and knows the difference between a credential that expired and a connection that stopped.

Before you start

  • A connection made with the offline_access permission, so you hold a refresh token.

Lifetimes

CredentialLastsThen
Access credential30 minutesRenew it with the refresh token.
Refresh token60 days from when it was issuedEach renewal issues a new one, so an app that is in use never reaches the end. A connection unused for 60 days stops.
Authorization code5 minutes, one useExchange it straight away.

1. Renew

POSThttps://host.shiftly.au/oauth/token

Renewal request
curl -X POST https://host.shiftly.au/oauth/token \
  -u "shf_your_client_id:shf_sk_your_client_secret" \
  -H "Content-Type: application/json" \
  -d '{ "grant_type": "refresh_token", "refresh_token": "shf_rt_..." }'

The response has the same shape as the first exchange, with a new access credential and a new refresh token. Store the new refresh token and discard the old one. Renew when a request answers 401 token_expired, or shortly before the 30 minutes are up.

2. Rotation, the grace window and reuse

Every renewal rotates the refresh token. If two of your processes renew with the same token within 60 seconds, both succeed and each receives its own new refresh token. Both new tokens work, so a race on startup does not break the connection; keep whichever one you store.

Outside that window, presenting a refresh token that has already been rotated is treated as a sign the token leaked. The connection is stopped, every credential for it is revoked, and the business is told the app needs reconnecting. Your renewal answers invalid_grant with reason reused.

3. Tell a stopped connection from an expired credential

What you seeWhat happenedWhat to do
401 token_expired on a v1 requestThe access credential has expired.Renew and retry.
401 invalid_token on a v1 requestThe access credential is missing or malformed.Send the credential as a bearer token.
403 connection_disconnected, connection_suspended or app_suspended on a v1 requestThe connection has stopped. The same three states as the renewal reasons below.Stop using the connection and follow the matching row below.
invalid_grant, reason disconnectedThe business disconnected your app in Shiftly.Stop using the connection. Ask the business to connect again from your product if they want to.
invalid_grant, reason suspendedThe connection stopped: the person who connected it left the business or closed their account, it went unused for 60 days, or a refresh token was reused.Ask someone at the business to connect your app again.
invalid_grant, reason app_suspendedShiftly has paused your app for every business.Contact Shiftly. Nothing to do per business.
403 permission_denied with a permission namedThe person who connected the app lost that permission, or never had it.Work without that permission, or have an owner connect the app again.

Shiftly does not send notifications to partner apps yet, so your app learns that a connection stopped from these answers, or by reading Connection.

4. Revoke

POSThttps://host.shiftly.au/oauth/revoke

When a business removes your product, revoke the connection so Shiftly shows it as disconnected. Authenticate your app as for the token endpoint and send the refresh token or an access credential as token. Revoking is idempotent and always answers 200. It ends one connection: to disconnect several businesses, revoke each connection's refresh token.

What can go wrong

You seeWhyWhat to do
invalid_grant with no reasonThe refresh token is unknown, expired after 60 days, or belongs to another app.The connection is gone. Ask the business to connect again.
429 on the token endpointMore than 60 token requests in a minute for your app.Renew once per connection and share the credential across your processes.