Company Access Tokens
Acquiring an Access Token
A company level token can be obtained by creating a partner managed company or going through the in app authorization code flow if the company is migrating to embedded payroll.
After creation of a partner managed company, you will receive an access_token, refresh_token, expires_in, and the uuid of the created company to make subsequent API calls on behalf of the company. expires_in is the number of seconds in which the access_token will expire. URL-safe base64 encoding is used when generating the access_token and refresh_token.
{
"access_token": "JKrGqRyrYfY1PB0YhsuRkbrrWBJ5iSUODDNA28D3yMc",
"refresh_token": "T0jHy4Oc3FWi7hDPEMPdpbGiLpB0rWeb1ZJOJVB36oU",
"company_uuid": "d525dd21-ba6e-482c-be15-c2c7237f1364",
"expires_in": 7200
}
Refreshing Access Tokens
This access token expires 2 hours after they are issued. If an access token is expired you will receive 401 Unauthorized errors. To refresh the access token, you will need the client_id, and client_secret from the application you created in the developer portal as well as your refresh_token. A refresh_token can be exchanged to get a new access_token and refresh_token.
To refresh your access_token use the POST oauth/token endpoint and include the refresh_token and "grant_type" : “refresh_token” in the request body.
The client_secret cannot be passed via API request URLs. Attempting to include the client_secret in the request URL will result in a 400 Bad Request error.
curl --location --request POST 'https://api.gusto-demo.com/oauth/token' \
--header 'Content-Type: application/json' \
--data-raw '{
"client_id": "{{client_id}}",
"client_secret": "{{client_secret}}",
"refresh_token": "T0jHy4Oc3FWi7hDPEMPdpbGiLpB0rWeb1ZJOJVB36oU",
"grant_type": "refresh_token"
}'import fetch from 'node-fetch';
const url = 'https://api.gusto-demo.com/oauth/token`;
const options = {
method: 'POST',
headers: {
accept:'application/json',
'content-type': 'application/json',
'Authorization': 'Token {{API_TOKEN}}'},
body: JSON.stringify({
'client_id': '{{client_id}}',
'client_secret': '{{client_secret}}',
'redirect_uri': 'https://localhost:3000',
'refresh_token': 'T0jHy4Oc3FWi7hDPEMPdpbGiLpB0rWeb1ZJOJVB36oU',
'grant_type': 'refresh_token'
})
};
fetch(url, options)
.then(res => res.json())
.then(json => console.log(json))
.catch(err => console.error('error:' + err));
The corresponding response will include a new access_token and refresh_token.
{
"access_token": "737HdeXfIqgx-NfaUFRuhV7JDe6ns6ptanJSMuQzjlc",
"token_type": "bearer",
"expires_in": 7200,
"refresh_token": "iEjL96L9Pndwmi-xVX3Q-xbrvvhnjHYGX87sopgGJ8E"
}The previous refresh_token will be revoked on the first usage of the new access_token. In our example, the previous refresh_token T0jHy4Oc3FWi7hDPEMPdpbGiLpB0rWeb1ZJOJVB36oU is only revoked when the new access_token 737HdeXfIqgx-NfaUFRuhV7JDe6ns6ptanJSMuQzjlc is used in the Authorization header of a Gusto API call. The expires_in value is provided in seconds from when the access_token was generated.
Token Management Recommendations
Access/refresh token pairs are specific to a resource, typically a company. The following gusto_auth_tokens table definition is an example of how Gusto tokens can be stored.
company_uuidis the Gusto company UUID. This column could also be a foreign key to your owncompaniestable which also contains agusto_company_uuidcolumn.access_token_expirationtheexpires_inresponse field is the expiration time in seconds of the newly generatedaccess_tokenwhether by Create a partner managed company or Refresh Access Token . The expiration time is 7200 seconds or 2 hours. To be safe, theaccess_token_expirationcan be set to (expires_in- 60) from when the response is received. This field can be used to proactively refresh tokens instead of always waiting for a 401 response to trigger a refresh.
Care should be taken to avoid token refresh race conditions. It is recommended to have unique constraints and when refreshing tokens, lock the associated row.
Example refresh steps:
- An access token needs to be refreshed. We know this because the
access_token_expirationis less than current time or an HTTP status of 401 is received from a Gust API request. - Lock the
gusto_auth_tokensrow for the associatedcompany_uuid. - Refresh the access token as instructed above.
- Update the
gusto_auth_tokensrow with the new access and refresh tokens. Theaccess_token_expirationshould also be updated to (expires_in- 60) seconds from the current time. - Unlock the row.
- Use the new access_token for Gusto API requests.
- All concurrent processes should use the latest
access_token.
Updated 2 days ago