Onboard a company
Streamline company setup, ensure regulatory compliance, and prepare for payroll activation
Prerequisites: Before using this guide you must have a developer account and created an application. To learn more about these steps, review the Quickstart guide.
Step 1: Setting up a company
1. Create a partner managed company
Create a company using the POST partner_managed_companies endpoint.
Sample request
curl --request POST \
--url https://api.gusto-demo.com/v1/partner_managed_companies \
--header 'accept: application/json' \
--header 'content-type: application/json'\
--header 'Authorization: Bearer {{system_access_token}}'\
--data '{
"user": {
"last_name": "Mushnik",
"first_name": "Mister",
"email": "[email protected]"
},
"company": {
"name": "Mushnik`s Flower Shop"
"ein": 910532465
}
}'
const fetch = require('node-fetch');
const url = 'https://api.gusto-demo.com/v1/partner_managed_companies';
const options = {
method: 'POST',
headers: {
accept: 'application/json',
'content-type': 'application/json',
authorization: 'Bearer <<API_TOKEN>>'
}
},
body: JSON.stringify({
user: {
first_name: 'Mister',
last_name: 'Mushnik',
email: '[email protected]'
},
company: {
name: "Mushnik\'s Flower Shop",
ein: "910532465"
}
})
};
fetch(url, options)
.then(res => res.json())
.then(json => console.log(json))
.catch(err => console.error('error:' + err));
Sample response
{
"company_uuid": "{{company_uuid}}",
"access_token": "{{access_token}}",
"refresh_token": "{{refresh_token}}",
"expires_in": 7200
}
Payroll administrators
The user created in this step is the primary payroll administrator of the new company. Add more payroll administrators using the POST /v1/companies/{company_id}/admins endpoint.
2. View and accept terms of service (TOS)
Each user must accept the Gusto Embedded Terms of Service. The user must exist in Gusto before you can retrieve and accept the Terms of Service for the user. If the user doesn't exist, create the admin, signatory, employee, or contractor record before surfacing the Terms of Service step in your application.
Partners may either embed a link to the terms of service in a short disclaimer such as "By continuing to the next step, I agree to the Embedded Payroll Terms of Service," or include the terms in an iframe for a user to scroll through.
In both cases, the user has to explicitly accept the TOS via a checkbox or other method.
Sample request
curl --request POST \
--url https://api.gusto-demo.com/v1/partner_managed_companies/{company_uuid}/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": "2005648946132",
"ip_address": "192.168.1.2"
}
'
const fetch = require('node-fetch');
const url = 'https://api.gusto-demo.com/v1/partner_managed_companies/{company_uuid}/accept_terms_of_service';
const options = {
method: 'POST',
headers: {
accept: 'application/json',
'content-type': 'application/json',
authorization: 'Bearer <<API_TOKEN>>'
},
body: JSON.stringify({
email: '[email protected]',
external_user_id: '2005648946132',
ip_address: '192.168.1.2'
})
};
fetch(url, options)
.then(res => res.json())
.then(json => console.log(json))
.catch(err => console.error('error:' + err));
Sample response
{
"latest_terms_accepted": true
}
3. Create a company location
All companies must provide mailing and filing addresses, as well as all addresses where the company has employees working in the United Statesβboth remotely and at home.
Use the POST /v1/company/{company_id}/locations endpoint to set each address.
Sample request
curl --request POST \
--url https://api.gusto-demo.com/v1/companies/{company_uuid}/locations \
--header 'accept: application/json' \
--header 'authorization: Bearer {{company_access_token}}' \
--header 'content-type: application/json' \
--data '
{
"phone_number": "8009360383",
"street_1": "425 2nd Street",
"street_2": "Suite 602",
"city": "San Francisco",
"state": "CA",
"zip": "94107",
"country": "USA",
"filing_address": true,
"mailing_address": true
}
'
const fetch = require('node-fetch');
const url = 'https://api.gusto-demo.com/v1/companies/{company_uuid}/locations';
const options = {
method: 'POST',
headers: {
accept: 'application/json',
'content-type': 'application/json',
authorization: 'Bearer <<COMPANY_API_TOKEN>>'
},
body: JSON.stringify({
phone_number: '8009360383',
street_1: '425 2nd Street',
street_2: 'Suite 602',
city: 'San Francisco',
state: 'CA',
zip: '94107',
country: 'USA'
})
};
fetch(url, options)
.then(res => res.json())
.then(json => console.log(json))
.catch(err => console.error('error:' + err));
Sample response
{
"company_uuid": "{{company_uuid}}",
"version": "{{version}}",
"phone_number": "8009360383",
"uuid": "{{uuid}}",
"street_1": "425 2nd Street",
"street_2": "Suite 602",
"city": "San Francisco",
"state": "CA",
"zip": "94107",
"country": "USA",
"active": true,
"filing_address": true,
"mailing_address": true,
"created_at": "2023-09-12T16:42:25.000-07:00",
"updated_at": "2023-09-12T16:42:25.000-07:00"
}
4. Update federal tax details
In ensure accurate filing, companies must provide federal tax information. Refer to the company's IRS Form CP-575 for this information.
- Retrieve the
version
of the tax details with the GET /v1/companies/{company_id}/federal_tax_details endpoint. - Update the tax details by calling the PUT /v1/companies/{company_id}/federal_tax_details endpoint
Sample request
curl --request PUT \
--url https://api.gusto-demo.com/v1/companies/{company_uuid}/federal_tax_details \
--header 'accept: application/json' \
--header 'authorization: Bearer {{company_access_token}}' \
--header 'content-type: application/json' \
--data '
{
"version": "6cb95e00540706ca48d4577b3c839fbe",
"tax_payer_type": "LLP",
"taxable_as_scorp": false,
"filing_form": "944",
"has_ein": true,
"ein_verified": false,
"legal_name": "Mushnik\'s Flower Shop Inc"
}'
const fetch = require('node-fetch');
const url = 'https://api.gusto-demo.com/v1/companies/{company_uuid}/federal_tax_details';
const options = {
method: 'PUT',
headers: {
accept: 'application/json',
'content-type': 'application/json',
authorization: 'Bearer <<COMPANY_API_TOKEN>>'
},
body: JSON.stringify({
version: '6cb95e00540706ca48d4577b3c839fbe',
tax_payer_type: 'LLP',
taxable_as_scorp: false,
filing_form: '944',
has_ein: true,
ein_verified: false,
legal_name: 'Mushnik\'s Flower Shop Inc'
})
};
fetch(url, options)
.then(res => res.json())
.then(json => console.log(json))
.catch(err => console.error('error:' + err));
Sample response
{
"version": "6cb95e00540706ca48d4577b3c839fbe",
"tax_payer_type": "LLP",
"taxable_as_scorp": false,
"filing_form": "941",
"has_ein": true,
"ein_verified": false,
"ein_verification": {
"status": "pending"
},
"legal_name": "Mushnik\'s Flower Shop Inc",
"effective_date": "2023-09-12",
"deposit_schedule": "Semiweekly"
}
5. Update the company industry
Update the company's industry selection using naics_code
andsic_codes
with the PUT /v1/companies/{company_uuid}/industry_selection endpoint.
NAICS and SIC codes
Gusto requires this information to stay in compliance with finance regulations:
- NAICS (North American Industry Classification System): A six-digit code based on the primary type of work the business performs
- SIC (Standard Industrial Classification): A four-digit code that categorizes the industries that companies belong to based on their activities.
You can look up a companyβs NAICS and SIC codes here.
Sample request
curl --request PUT \
--url https://api.gusto-demo.com/v1/companies/{company_uuid}/industry_selection \
--header 'accept: application/json' \
--header 'authorization: Bearer {{company_access_token}}' \
--header 'content-type: application/json' \
--data '
{
"title": "Computer Training",
"naics_code": "611420",
"sic_codes": [
"8243"
]
}
'
const fetch = require('node-fetch');
const url = 'https://api.gusto-demo.com/v1/companies/{company_uuid}/industry_selection';
const options = {
method: 'PUT',
headers: {
accept: 'application/json',
'content-type': 'application/json',
authorization: 'Bearer <<COMPANY_API_TOKEN>>'
},
body: JSON.stringify({title: 'Computer Training', naics_code: '611420', sic_codes: ['8243']})
};
fetch(url, options)
.then(res => res.json())
.then(json => console.log(json))
.catch(err => console.error('error:' + err));
Sample response
{
"company_uuid": "{{company_uuid}}",
"naics_code": "611420",
"sic_codes": [
"8243"
],
"title": "Computer Training"
}
Step 2: Configuring payrolls and employees
This phase involves integrating payroll and employee data to ensure compliance and readiness for processing payroll.
1. Add and verify a company bank account
Create and connect a new bank account for a company using the POST /v1/companies/{company_id}/bank_accounts endpoint. If a default bank account exists, the new bank account will replace it as the company's default funding method.
You can also connect a bank account from Plaid using the POST plaid/processor_token
endpoint.
When testing in Demo: Use the sample routing number 102001017
. The API checks that the routing number is a valid US routing number, and therefore will reject false inputs.
Sample request
curl --request POST \
--url https://api.gusto-demo.com/v1/companies/{company_uuid}/bank_accounts \
--header 'accept: application/json' \
--header 'authorization: Bearer {{company_access_token}}' \
--header 'content-type: application/json' \
--data '
{
"routing_number": "102001017",
"account_type": "Checking",
"account_number": "9775014007"
}
'
const fetch = require('node-fetch');
const url = 'https://api.gusto-demo.com/v1/companies/{company_uuid}/bank_accounts';
const options = {
method: 'POST',
headers: {
accept: 'application/json',
'content-type': 'application/json',
authorization: 'Bearer <<COMPANY_API_TOKEN>>'
},
body: JSON.stringify({
routing_number: '115092013',
account_type: 'Checking',
account_number: '9775014007'
})
};
fetch(url, options)
.then(res => res.json())
.then(json => console.log(json))
.catch(err => console.error('error:' + err));
Sample response
{
"uuid": "{{uuid}}",
"company_uuid": "{{company_uuid}}",
"account_type": "Checking",
"routing_number": "102001017",
"hidden_account_number": "XXXX014007",
"verification_status": "awaiting_deposits",
"verification_type": "bank_deposits",
"name": "Employer Funding Account"
}
Two verification deposits are automatically sent to the new bank account in 1-2 business days. During this stage, the bank account's verification_status
is awaiting_deposits
.
When the deposits are successfully transferred, the verification_status
changes to ready_for_verification
.
Verify account
At this point, call the PUT /v1/companies/{company_id}/bank_accounts/{bank_account_uuid}/verify to verify the bank account. After a successful verification, the bank account's verification_status
is returned as verified
.
Sample request
curl --request PUT \
--url https://api.gusto-demo.com/v1/companies/{company_uuid}/bank_accounts/{bank_account_uuid}/verify \
--header 'accept: application/json' \
--header 'authorization: Bearer {{company_access_token}}' \
--header 'content-type: application/json' \
--data '
{
"deposit_1": 0.02,
"deposit_2": 0.42
}
'
const fetch = require('node-fetch');
const url = 'https://api.gusto-demo.com/v1/companies/{company_uuid}/bank_accounts/{bank_account_uuid}/verify';
const options = {
method: 'PUT',
headers: {
accept: 'application/json',
'content-type': 'application/json',
authorization: 'Bearer <<COMPANY_API_TOKEN>>'
},
body: JSON.stringify({deposit_1: 0.02, deposit_2: 0.42})
};
fetch(url, options)
.then(res => res.json())
.then(json => console.log(json))
.catch(err => console.error('error:' + err));
Sample response
{
"uuid": "{{uuid}}",
"company_uuid": "{{company_uuid}}",
"account_type": "Checking",
"routing_number": "102001017",
"hidden_account_number": "XXXX014007",
"verification_status": "verified",
"verification_type": "bank_deposits",
"name": "Employer Funding Account"
}
Validation in Demo
For testing in Demo, use the POST companies/{company_id_or_uuid}/bank_accounts/{bank_account_uuid}/send_test_deposits endpoint simulate micro-deposit transfers.
2. Create an employee
Employees are essential for payroll. You can onboard employees either through employer-entered data or self-onboarding. For a more comprehensive walkthrough, see the Onboard a W2 Employee guide.
Create an employee with the POST /v1/companies/{company_id}/employees endpoint.
Sample request
The example below shows an employee "self-onboarding" since the "self_onboarding": true
. If false
, the payroll admin is required to enter all of the employee's onboarding information.
curl --request POST \
--url https://api.gusto-demo.com/v1/companies/{company_uuid}/employees \
--header 'accept: application/json' \
--header 'authorization: Bearer {{company_access_token}}' \
--header 'content-type: application/json' \
--data '
{
"first_name": "Alexander",
"middle_initial": "A",
"last_name": "Hamilton",
"date_of_birth": "1979-06-01",
"email": "[email protected]",
"ssn": "123451776",
"self_onboarding": true
}
'
const fetch = require('node-fetch');
const url = 'https://api.gusto-demo.com/v1/companies/{company_uuid}/employees';
const options = {
method: 'POST',
headers: {
accept: 'application/json',
'content-type': 'application/json',
authorization: 'Bearer <<COMPANY_API_TOKEN>>'
},
body: JSON.stringify({
first_name: 'Alexander',
middle_initial: 'A',
last_name: 'Hamilton',
date_of_birth: '1979-06-01',
email: '[email protected]',
ssn: '123451776',
self_onboarding: true
})
};
fetch(url, options)
.then(res => res.json())
.then(json => console.log(json))
.catch(err => console.error('error:' + err));
Sample response
{
"uuid": "{{uuid}}",
"first_name": "Alexander",
"middle_initial": "A",
"last_name": "Hamilton",
"email": "[email protected]",
"company_uuid": "9aacba60-69b8-4a16-9086-69196d9f0aa3",
"manager_uuid": null,
"version": "5ac6c6f7b695f5c947bbe150b3ed7dfd",
"current_employment_status": null,
"onboarding_status": "self_onboarding_pending_invite",
"preferred_first_name": null,
"department_uuid": null,
"employee_code": "5c01a2",
"payment_method": "Check",
"department": null,
"terminated": false,
"two_percent_shareholder": null,
"onboarded": false,
"historical": false,
"has_ssn": true,
"onboarding_documents_config": {
"uuid": null,
"i9_document": false
},
"jobs": [],
"eligible_paid_time_off": [],
"terminations": [],
"garnishments": [],
"date_of_birth": "1979-06-01",
"ssn": "",
"phone": null,
"work_email": null
}
3. Create an employee work address
Call POST /v1/employees/{employee_id}/work_addresses to create a work address for an employee. This is required for updating the company's state tax details later on.
Sample request
curl --request POST \
--url https://api.gusto-demo.com/v1/employees/employee_id/work_addresses \
--header 'X-Gusto-API-Version: 2024-04-01' \
--header 'accept: application/json' \
--header 'content-type: application/json'
Sample response
{
"uuid": "64ee5fd7-3eb2-4083-883c-95e93e181cc8",
"employee_uuid": "d773461f-848a-40a1-8f09-b2ee4249d5c7",
"location_uuid": "733ab2af-9510-408f-8d20-09196967174f",
"effective_date": "2020-01-31",
"active": true,
"version": "3879823d440f3a3215d129ac73c58966",
"street_1": "977 Marks Viaduct",
"street_2": "Apt. 958",
"city": "Pink Hill",
"state": "NC",
"zip": "28572",
"country": "USA"
}
4. Create a pay schedule
A pay schedule determines the frequency and timing of payroll for a company. Create a new pay schedule for a company by calling the POST /v1/companies/{company_id}/pay_schedules endpoint. To learn more about Pay Schedules review the Create a Pay Schedule guide.
Sample request
curl --request POST \
--url https://api.gusto-demo.com/v1/companies/{company_uuid}/pay_schedules \
--header 'accept: application/json' \
--header 'authorization: Bearer {{company_access_token}} \
--header 'content-type: application/json' \
--data '{
"anchor_pay_date": "2025-09-15",
"anchor_end_of_pay_period": "2025-09-08"
"frequency": "Every week"
}'
Sample response
{
"uuid": "{{uuid}}",
"version": "5898e9667b9ea6935493b9e146991c34",
"day_1": null,
"day_2": null,
"frequency": "Every week",
"anchor_pay_date": "2025-09-15",
"name": null,
"custom_name": "every Monday",
"auto_pilot": false,
"anchor_end_of_pay_period": "2025-09-08",
"active": true
}
Key context: Anchor pay dates
- Payroll of any kind (regular, off-cycle, etc.) cannot be run in a quarter prior to the quarter that the anchor pay date falls in.
- If payroll (regular or off-cycle) is not run by the set anchor pay date, the field will be invalidated and the pay schedule will need to be set again.
- If the anchor pay date is changed prior to running the first payroll, form 8655 may need to be resigned by the company signatory:
- If the new anchor pay date is in the same quarter as the initially chosen anchor pay date, forms are not required to be resigned.
- If the new anchor pay date is in a different quarter, forms are required to be resigned.
Context: the anchor pay date is reported on the Federal 8655 form (authorization for Gusto to pay & file taxes on behalf of the company). Because of this, our authorization starts in the quarter associated with the anchor pay date.
5. Update company state tax details
State tax setup is based on employee work addresses and determines tax compliance for each state.
A company location and employee work address must be created before completing this step, as Gusto determines a company's state tax requirements from the employee work address(es).
Step 3: Finalizing and submitting onboarding
This third and final phase ensures all requirements are completed before the company is approved to process payroll.
1. (Optional) Add previous payrolls
Historical payrolls are essential for companies transitioning from another payroll provider mid-year. This ensures accurate year-to-date tax filings and a single W-2 for employees.
Follow the Create a historical payroll guide to add previous payrolls.
2. Add a signatory
The signatory should be an officer, owner, general partner or LLC member manager, plan administrator, fiduciary, or an authorized representative who is designated to sign agreements on the company's behalf. An officer is someone like the president, vice president, treasurer, or chief accounting officer.
There can only be a single primary signatory in a company so you must delete a signatory before creating a new one. Retrieve the current primary signatory using the GET /v1/companies/{company_uuid}/signatories endpoint.
You can either create a new signatory or invite a signatory to create a signatory with minimal information and subsequently populate the remaining information using the update a signatory endpoint.
Sample request
This example shows a request to create a new signatory using POST companies/{company_uuid}/signatories.
curl --request POST \
--url https://api.gusto-demo.com/v1/companies/{company_uuid}/signatories \
--header 'accept: application/json' \
--header 'authorization: Bearer {{company_access_token}}' \
--header 'content-type: application/json' \
--data '
{
"home_address": {
"street_1": "35 Fantine Street",
"street_2": "Suite 17",
"city": "Paris",
"state": "TX",
"zip": "75460"
},
"ssn": "254324601",
"first_name": "Jean",
"last_name": "Valjean",
"email": "[email protected]\"",
"title": "Business Man",
"phone": "8002331000",
"birthday": "1983-12-01"
}
'
const fetch = require('node-fetch');
const url = 'https://api.gusto-demo.com/v1/companies/{company_uuid}/signatories';
const options = {
method: 'POST',
headers: {
accept: 'application/json',
'content-type': 'application/json',
authorization: 'Bearer <<COMPANY_API_TOKEN>>'
},
body: JSON.stringify({
home_address: {
street_1: '35 Fantine Street',
street_2: 'Suite 17',
city: 'Paris',
state: 'TX',
zip: '75460'
},
ssn: '254324601',
first_name: 'Jean',
last_name: 'Valjean',
email: '[email protected]"',
title: 'Business Man',
phone: '8002331000',
birthday: '1983-12-01'
})
};
fetch(url, options)
.then(res => res.json())
.then(json => console.log(json))
.catch(err => console.error('error:' + err));
Sample response
{
"uuid": "{{uuid}}",
"first_name": "Jean",
"last_name": "Valjean",
"title": "Business Man",
"phone": "8002331000",
"birthday": "1983-12-01",
"email": "[email protected]",
"is_admin": false,
"has_ssn": true,
"version": "801fee0712d0123ac3266017b2095b59",
"home_address": {
"street_1": "35 Fantine Street",
"street_2": "Suite 17",
"city": "Paris",
"state": "TX",
"zip": "75460",
"country": "USA"
},
"identity_verification_status": "Pass"
}
3. Sign documents
Prerequisite
All onboarding steps, including tax details, locations, and bank accounts, must be completed before signing documents.
-
To see what forms need to be signed, use the GET /v1/companies/{company_id}/forms endpoint.
Sample requestcurl --request GET \ --url https://api.gusto-demo.com/v1/companies/{company_id}/forms \ --header 'accept: application/json' \ --header 'authorization: Bearer {{company_access_token}}'
Sample response
The response will return an array of document objects:[ { "uuid": "48cdd5ec-a4dd-4840-a424-ad79f38d8408", "name": "company_direct_deposit", "title": "Direct Deposit Authorization", "description": "We need you to sign paperwork to authorize us to debit and credit your bank account and file and pay your taxes.", "requires_signing": true } ]
-
To optionally preview the PDF of each document, use the GET /v1/forms/{form_uuid}/pdf endpoint.
-
Identify which forms require signingβthey will have
"requires_signing": true
βand use theuuid
of each form to make a request to sign a company form using the PUT /v1/forms/{form_id}/sign endpoint.
Sample requestcurl --request PUT \ --url https://api.gusto-demo.com/v1/forms/48cdd5ec-a4dd-4840-a424-ad79f38d8408/sign \ --header 'accept: application/json' \ --header 'authorization: Bearer {{company_access_token}}' \ --header 'content-type: application/json' \ --data ' { "signature_text": "Jean Valjean", "agree": true, "signed_by_ip_address": "192.168.0.1" } '
const fetch = require('node-fetch'); const url = 'https://api.gusto-demo.com/v1/forms/48cdd5ec-a4dd-4840-a424-ad79f38d8408/sign'; const options = { method: 'PUT', headers: { accept: 'application/json', 'content-type': 'application/json', authorization: 'Bearer <<COMPANY_API_TOKEN>>' }, body: JSON.stringify({ signature_text: 'Jean Valjean', agree: true, signed_by_ip_address: '192.168.0.1' }) }; fetch(url, options) .then(res => res.json()) .then(json => console.log(json)) .catch(err => console.error('error:' + err));
Sample response
{ "uuid": "48cdd5ec-a4dd-4840-a424-ad79f38d8408", "name": "company_direct_deposit", "title": "Direct Deposit Authorization", "description": "We need you to sign paperwork to authorize us to debit and credit your bank account and file and pay your taxes.", "draft": false, "quarter": null, "year": null, "document_content_type": "application/pdf", "requires_signing": true }
-
If a form requires action you can subscribe to webhooks and listen for
form.updated
. Check the value ofform.signed_at
βif it changes from a present timestamp to blank or nil, the form has gone from signed to unsigned.
Form 8655 regenerates in these scenarios and will require re-signature:
- The signatory's information changes.
- The anchor pay date is updated to an earlier month.
- Company data (e.g., EIN, name, filing address) is modified.
4. Confirm all steps are complete and submit
-
Before finalizing onboarding, ensure all steps are marked as "completed" by calling the GET /v1/companies/{company_uuid}/onboarding_status endpoint.
Sample request
In this example response,payroll_schedule
,sign_all_forms
,andverify_bank_info
have not been completed, as shown by"completed": false
:{ "uuid": "94a4d25c-c3a6-4bea-92a8-356ac915c8aa", "onboarding_completed": false, "onboarding_steps": [ { "title": "Add Your Companyβs Addresses", "id": "add_addresses", "required": true, "completed": true, "requirements": [] }, { "title": "Enter Your Federal Tax Information", "id": "federal_tax_setup", "required": true, "completed": true, "requirements": [] }, { "title": "Select Industry", "id": "select_industry", "required": true, "completed": true, "requirements": [] }, { "title": "Add Your Bank Account", "id": "add_bank_info", "required": true, "completed": true, "requirements": [] }, { "title": "Add Your Employees", "id": "add_employees", "required": true, "completed": true, "requirements": [ "add_addresses" ] }, { "title": "Enter Your State Tax Information", "id": "state_setup", "required": true, "completed": true, "requirements": [ "add_addresses", "add_employees" ] }, { "title": "Select a Pay Schedule", "id": "payroll_schedule", "required": true, "completed": false, "requirements": [] }, { "title": "Sign Documents", "id": "sign_all_forms", "required": true, "completed": false, "requirements": [ "add_employees", "federal_tax_setup", "state_setup", "add_bank_info", "payroll_schedule" ] }, { "title": "Verify Your Bank Account", "id": "verify_bank_info", "required": true, "completed": false, "requirements": [ "add_bank_info" ] } ] }
-
Ensure all steps have been completed by checking for
"completed": true
on each item returned getting the onboarding status. -
After all steps are completed, use the PUT companies/{company_uuid}/finish_onboarding endpoint to complete company onboarding.
Sample requestcurl --request PUT \ --url https://api.gusto-demo.com/v1/companies/{company_uuid}/finish_onboarding \ --header 'accept: application/json' \ --header 'authorization: Bearer {{company_access_token}}'
const fetch = require('node-fetch'); const url = 'https://api.gusto-demo.com/v1/companies/{company_uuid}/finish_onboarding'; const options = { method: 'PUT', headers: {accept: 'application/json', authorization: 'Bearer <<COMPANY_API_TOKEN>>'} }; fetch(url, options) .then(res => res.json()) .then(json => console.log(json)) .catch(err => console.error('error:' + err));
Sample response
{ "uuid": "94a4d25c-c3a6-4bea-92a8-356ac915c8aa", "onboarding_completed": true, "onboarding_steps": [ { "title": "Add Your Company's Addresses", "id": "add_addresses", "required": true, "completed": true, "requirements": [] }, { "title": "Enter Your Federal Tax Information", "id": "federal_tax_setup", "required": true, "completed": true, "requirements": [] }, { "title": "Select Industry", "id": "select_industry", "required": true, "completed": true, "requirements": [] }, { "title": "Add Your Bank Account", "id": "add_bank_info", "required": true, "completed": true, "requirements": [] }, { "title": "Add Your Employees", "id": "add_employees", "required": true, "completed": true, "requirements": [ "add_addresses" ] }, { "title": "Enter Your State Tax Information", "id": "state_setup", "required": true, "completed": true, "requirements": [ "add_addresses", "add_employees" ] }, { "title": "Select a Pay Schedule", "id": "payroll_schedule", "required": true, "completed": false, "requirements": [] }, { "title": "Sign Documents", "id": "sign_all_forms", "required": true, "completed": false, "requirements": [ "add_employees", "federal_tax_setup", "state_setup", "add_bank_info", "payroll_schedule" ] }, { "title": "Verify Your Bank Account", "id": "verify_bank_info", "required": true, "completed": false, "requirements": [ "add_bank_info" ] } ] }
-
After a company completes onboarding, Gusto's Risk team will automatically review the company and either approve the company to run payroll or request additional information to verify the company.
Demo
For testing purposes in the demo environment, you can use the
PUT /v1/companies/{company_uuid}/approve
endpoint. This simulates the approval process, enabling you to validate integration workflows without waiting for standard approval.
5. Monitor webhook for approval
When you finish company onboarding, Gustoβs internal review process automatically begins. The review can take up to two business days.
Using webhooks, you can monitor when the company is approved via the company.approved
event.
Update information post-onboarding
- If you need to make any changes to company or employee info post onboarding, you can use the Company and Employee endpoints to do so.
- If using Flows, you can revisit the Flows to make necessary adjustments. State tax information cannot be edited through Flows so you must contact Support.
FAQ
How do I onboard contractor-only companies?
Contractor-only companies are configured to work exclusively with contractors, bypassing the requirements associated with managing W-2 employees.
Gusto provides a simplified onboarding process for contractor-only companies, focusing on essential steps such as adding company addresses, setting up federal tax information, and verifying banking details.
Architecture diagram

Updated 5 days ago