Migrate an existing company

Learn how to migrate a Gusto.com company to your Embedded Payroll system

For existing Gusto.com customers, you can migrate their company to your Embedded Payroll product, using OAuth2 for authentication, instead of creating a new company for them. Find libraries supporting OAuth on the OAuth2 homepage.

Only primary or full-access admins can authorize new apps. Some users manage payroll for multiple companies and must select which one to connect to during authorization, so your integration should be ready to handle this.

1. OAuth connect

Securely connect an existing Gusto company to your Embedded Payroll integration using the OAuth authentication flow. This ensures only authorized administrators can grant access and maintain control over their company data.

Below is an overview of the OAuth flow:

Retrieve an authorization code

To begin the migration, the company’s primary or full-access administrator must approve your application accessing their information on Gusto.

They’ll be directed to Gusto’s login and authorization screen, where they authenticate and grant your application permission.

Authorization URL structure

https://api.gusto.com/oauth/authorize?client_id=YOUR_CLIENT_ID&redirect_uri=YOUR_REDIRECT_URI&response_type=code

Parameters

  • client_id: Your application’s unique identifier, generated for you when you create an app in the Gusto Developer Portal.
  • redirect_uri: Sometimes called a β€œcallback URI,” this is the URL to which the user will be redirected after authorization. OAuth does not support wildcard URIs or URIs with fragments (e.g #).
  • response_type: Always set to code.

After successful authentication, Gusto redirects the user to your redirect_uri, appending an authorization code as a query parameter:

https://example.com/callback?code=AUTHORIZATION_CODE

πŸ“˜

The authorization code is valid for 10 minutes. It must be exchanged for an access token before it expires.

Exchange the authorization code for an access token

Once you have the authorization code, exchange it for an access token by making a POST /oauth/token request.

Sample request

curl --request POST \
  --url https://api.gusto.com/oauth/token \
  --header 'Content-Type: application/json' \
  --data '{
    "client_id": "YOUR_CLIENT_ID",
    "client_secret": "YOUR_CLIENT_SECRET",
    "redirect_uri": "https://example.com/callback",
    "code": "AUTHORIZATION_CODE",
    "grant_type": "authorization_code"
  }'

Sample response

{
  "access_token": "de6780bc506a0446309bd9362820ba8aed28aa506c71eedbe1c5c4f9dd350e54",
  "token_type": "bearer",
  "expires_in": 7200,
  "refresh_token": "8257e65c97202ed1726cf9571600918f3bffb2544b26e00a61df9897668c33a1"
}

You’ll use the access token in the Authorization header when calling the API. Tokens are tied to one company. For guidance on refreshing and storing tokens, see Authentication and authorization.

2. Retrieve information from the token

After obtaining an access token, use the GET /v1/token_info endpoint to retrieve the company's unique identifier.

Sample request

curl --request GET \
  --url https://api.gusto-demo.com/v1/token_info \
  --header 'accept: application/json' \
  --header 'authorization: Bearer COMPANY_ACCESS_TOKEN'

Sample response

{
  "resource_type": "Company",
  "resource_uuid": "123e4567-e89b-12d3-a456-426614174000"
}

3. Accept terms of service (TOS)

Using the uuid for the company you want to migrate, accept Gusto’s Terms of Service using the POST /v1/partner_managed_companies/{company_uuid}/accept_terms_of_service endpoint. Each company added must accept the Terms of Service.

Sample request

curl --request POST \
  --url https://api.gusto-demo.com/v1/partner_managed_companies/123e4567-e89b-12d3-a456-426614174000/accept_terms_of_service \
  --header 'accept: application/json' \
  --header 'authorization: Bearer COMPANY_ACCESS_TOKEN' \
  --header 'content-type: application/json' \
  --data '{
    "email": "[email protected]",
    "external_user_id": "USER_12345",
    "ip_address": "192.168.1.1"
  }'

Sample response

{
  "status": "accepted",
  "company_uuid": "123e4567-e89b-12d3-a456-426614174000",
  "timestamp": "2025-01-29T12:34:56Z"
}

4. Migrate the company

Once the Terms of Service have been accepted, finalize the migration to Embedded Payroll by using the PUT /v1/partner_managed_companies/{company_uuid}/migrate endpoint.

Sample request

curl --request PUT \
  --url https://api.gusto-demo.com/v1/partner_managed_companies/123e4567-e89b-12d3-a456-426614174000/migrate \
  --header 'accept: application/json' \
  --header 'authorization: Bearer COMPANY_ACCESS_TOKEN' \
  --header 'content-type: application/json' \
  --data '{
    "email": "[email protected]",
    "ip_address": "192.168.1.1",
    "external_user_id": "USER_12345"
  }'

Sample response

{
  "status": "migrated",
  "company_uuid": "123e4567-e89b-12d3-a456-426614174000",
  "timestamp": "2025-01-29T13:45:00Z"
}

5. (Recommended) Add admin users

The user who authenticated in step is now the primary payroll administrator of the migrated company. You can add administrators or change the administrator, use the POST /v1/companies/{company_id}/admins endpoint.

Sample request

curl --request POST \
  --url https://api.gusto-demo.com/v1/companies/123e4567-e89b-12d3-a456-426614174000/admins \
  --header 'accept: application/json' \
  --header 'authorization: Bearer COMPANY_ACCESS_TOKEN' \
  --header 'content-type: application/json' \
  --data '{
    "first_name": "Harold",
    "last_name": "Hill",
    "email": "[email protected]"
  }'
const fetch = require('node-fetch');

const url = 'https://api.gusto-demo.com/v1/companies/company_id/admins';
const options = {
  method: 'POST',
  headers: {
    accept: 'application/json',
    'content-type': 'application/json',
    authorization: 'Bearer <<COMPANY_ACCESS_TOKEN>>'
  },
  body: JSON.stringify({first_name: 'Harold', last_name: 'Hill', email: '[email protected]'})
};

fetch(url, options)
  .then(res => res.json())
  .then(json => console.log(json))
  .catch(err => console.error('error:' + err));

Sample response

{
  "id": "987654321",
  "first_name": "Harold",
  "last_name": "Hill",
  "email": "[email protected]",
  "role": "payroll_admin",
  "company_id": "123e4567-e89b-12d3-a456-426614174000"
}