Onboard a contractor-only company
Set up companies that exclusively employ contractors
Businesses that exclusively work with contractors (meaning they do not employ any W-2 employees) should use contractor-only companies. Contractor-only companies benefit from a streamlined onboarding process with fewer requirements than companies that manage W-2 employees, but they are subject to a payroll blocker that prevents W-2 payroll processing.
A contractor-only company can be upgraded to support contractor payments and W-2 payroll, and the company must then complete additional onboarding steps to enable W-2 payroll.
We have not explicitly blocked APIs for contractor-only companies, but some behaviors that should be avoided. For instance, users can technically create an employee for a contractor-only company through the API. However, they should refrain from doing so since the company is contractor-only.
Although we are not explicitly blocking API endpoints, fully onboarded contractor-only companies are unable to run payroll due to the contractor-only payroll blocker. This applies even when the company has onboarded contractors.
1. Create a contractor-only company
Specify "contractor_only": true
in the API request body of the POST v1/partner_managed_companies endpoint.
By default, unless explicitly defined, the "contractor_only"
attribute is set to false
, indicating the company supports at least one W-2 employee.
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,
"contractor_only": true
}
}'
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
{
"access_token": "COMPANY_ACCESS_TOKEN",
"refresh_token": "COMPANY_REFRESH_TOKEN",
"company_uuid": "COMPANY_UUID",
"expires_in": 7200
}
2. Get a companyβs contractor_only status
Make a call to the GET /v1/companies endpoint to check the "contractor_only"
value in the response.
If "contractor_only: true
the company is configured as contractor-only.
Sample response
{
"contractor_only": true
}
3. Get a companyβs onboarding requirements
Retrieve the companyβs onboarding requirements using the GET companies/{company_uuid}/onboarding_status endpoint, as onboarding steps for contractor-only companies are different than companies that support W-2 employees.
For contractor-only companies the onboarding steps include:
add_addresses
federal_tax_setup
select_industry
add_bank_info
add_contractors
sign_all_forms
verify_bank_info
The state_setup
, payroll_schedule
, and add_employees
steps are not included for contractor-only.
Sample request
curl --request GET \
--url https://api.gusto-demo.com/v1/companies/company_uuid/onboarding_status \
--header 'X-Gusto-API-Version: 2025-06-15' \
--header 'accept: application/json'
Sample response
{
"uuid": "8e75cd53-9427-40a1-9f7c-4542d56d7e6e",
"onboarding_completed": false,
"onboarding_steps": [
{
"title": "Add Your Companyβs Addresses",
"id": "add_addresses",
"required": true,
"completed": true,
"skippable": false,
"requirements": []
},
{
"title": "Enter Your Federal Tax Information",
"id": "federal_tax_setup",
"required": true,
"completed": true,
"skippable": false,
"requirements": []
},
{
"title": "Select Industry",
"id": "select_industry",
"required": true,
"completed": true,
"skippable": false,
"requirements": []
},
{
"title": "Add Your Bank Account",
"id": "add_bank_info",
"required": true,
"completed": true,
"skippable": false,
"requirements": []
},
{
"title": "Add Your Contractors",
"id": "add_contractors",
"required": false,
"completed": true,
"skippable": false,
"requirements": [
"add_addresses"
]
},
{
"title": "Sign Documents",
"id": "sign_all_forms",
"required": true,
"completed": true,
"skippable": false,
"requirements": [
"federal_tax_setup",
"add_bank_info"
]
},
{
"title": "Verify Your Bank Account",
"id": "verify_bank_info",
"required": true,
"completed": true,
"skippable": false,
"requirements": [
"add_bank_info"
]
}
]
}
4. Handle payroll blockers
Check payroll blockers through the GET /v1/companies/{company_uuid}/payrolls/blockers endpoint. If a company is contractor-only, it will have the following payroll blocker:
[
{
"key": "contractor_only_company",
"message": "Company is set to contractor_only and cannot run payroll. Update the company and complete additional onboarding steps to process payroll."
}
]
This payroll blocker does not apply to companies with W-2 employees.
5. Generate a contractor-only onboarding flow
After creating a contractor-only company using the POST /v1/partner_managed_companies endpoint, generate a company_onboarding
flow using our POST /v1/companies/{company_uuid}/flows endpoint.
curl --request POST
--url <https://api.gusto-demo.com/v1/companies/{{company_uuid}}/flows>
--header 'Authorization: Bearer {{access_token}}β'
--header 'Content-Type: application/json'
--data '
{
"flow_type": "company_onboarding"
}
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));
Contractor-only flow:

- Steps such as βAdd Your Employees,β βSelect a Pay Schedule,β and βEnter Your State Tax Informationβ are not included as steps in the contractor-only onboarding flow since these steps are not applicable.
- For contractor-only companies, the unique step βAdd Your Contractorsβ addresses their specific operational needs, nesting the
add_contractors
flow within the broader company onboarding flow.
Non-contractor-only flow:
As a comparison to the contractor-only company onboarding flow, here's what the company onboarding flow looks like for companies that support W-2 employees:

Update a company to support payroll for W-2 employees
If a contractor-only company wants to onboard and run payroll for W-2 employees, the company must first be updated using the PUT /v1/companies
endpoint and specifying βcontractor_onlyβ: false
in the body params:
curl --request PUT \
--url https://api.gusto-demo.com/v1/companies/company_id \
--header 'accept: application/json' \
--header 'content-type: application/json' \
--data '
{
"contractor_only": false
}
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));
Updating the "contractor_only" attribute
- The
contractor_only
attribute can only be updated fromtrue
tofalse
, and not vice versa. In other words,contractor_only
cannot be enabled for an existing company.- If you update
"contractor_only": false
you must also complete thestate_setup
,payroll_schedule
, andadd_employees
onboarding steps before running payroll.
Updated 6 days ago