Onboard a W2 Employee
Employees are a critical part of payroll. Companies themselves are, naturally, a collection of one to hundreds of employees that must be paid on a regular cadence for work done.
Employees may be added during a companyโs onboarding for payroll, or at any time after the initial onboarding is complete. An employee can be setup in one of two ways:
- By Employer
- By Employee (โSelf-onboardingโ)
Both can be done using Gustoโs pre-built Flows or using the Employee APIs to build custom UI/UX.
To learn more about the difference between Employee Onboarding by Employer vs Employee Self-Onboarding review the Onboarding Method Comparison Guide.
The steps for both of these processes is the same
1. Create a W2 Employee
You can create an employee using the POST companies/{company_id}/employees
endpoint.
The example below shows an employee "self-onboarding".
curl --request POST \
--url https://api.gusto-demo.com/v1/companies/{company_uuid}/employees \
--header 'accept: application/json' \
--header 'authorization: Bearer <<COMPANY_API_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));
2. Create an Employee's Job and Compensation
To create a W2 Employee's job and compensation follow the Create a Job and Compensation guide.
3. Update Employee's Information
If completing via Employee Self-Onboarding, you can use the employee_self_management Flow to collect this information or you can use the following steps.
a. Update An Employee's Home Address
To update an employee's home address, you will first need to get the version
of the address using the GET employees/{employee_id}/home_addresses
endpoint. Once you have the version
you can update the home address using the PUT /employees/{employee_id}/home_addresses
endpoint.
curl --request PUT \
--url https://api.gusto-demo.com/v1/employees/employee_id/home_addresses \
--header 'accept: application/json' \
--header 'authorization: Bearer <<COMPANY_API_TOKEN>>' \
--header 'content-type: application/json' \
--data '
[
{
"uuid": "56260b3d-c375-415c-b77a-75d99f717193",
"employee_uuid": "7087a288-8349-4632-b92e-bc94fb79f29e",
"street_1": "644 Fay Vista",
"street_2": "Suite 842",
"city": "Richmond",
"state": "VA",
"zip": "23218",
"country": "USA",
"active": false,
"effective_date": "2021-01-01",
"courtesy_withholding": true
},
{
"uuid": "d9f74049-8769-4fba-8e0f-eceef2da4e6b",
"employee_uuid": "7087a288-8349-4632-b92e-bc94fb79f29e",
"street_1": "100 5th Ave",
"street_2": "Suite 555",
"city": "New York",
"state": "NY",
"zip": "10001",
"country": "USA",
"active": true,
"effective_date": "2022-03-03",
"courtesy_withholding": true
}
]
'
const fetch = require('node-fetch');
const url = 'https://api.gusto-demo.com/v1/employees/employee_id/home_address';
const options = {
method: 'PUT',
headers: {
accept: 'application/json',
'content-type': 'application/json',
authorization: 'Bearer <<COMPANY_API_TOKEN>>'
},
body: JSON.stringify({
version: 'fe75bd065ff48b91c35fe8ff842f986c',
street_1: '39057 Broderick Light',
street_2: 'Apt. 612',
city: 'San Francisco',
state: 'CA',
zip: '94107'
})
};
fetch(url, options)
.then(res => res.json())
.then(json => console.log(json))
.catch(err => console.error('error:' + err));
b. Update an Employee's Federal Taxes
In order to file and pay taxes correctly, a employee needs to provide federal tax information. To update the Federal Tax Details, you will first need to get the version
of the tax details using GET employees/{employee_uuid}/federal_taxes
. Once you have the version
you can update the federal tax details using PUT employees/{employee_uuid}/federal_taxes
.
curl --request PUT \
--url https://api.gusto-demo.com/v1/employees/{employee_uuid}/federal_taxes \
--header 'accept: application/json' \
--header 'authorization: Bearer <<COMPANY_API_TOKEN>>' \
--header 'content-type: application/json' \
--data '
{
"version": "56a489ce86ed6c1b0f0cecc4050a0b01",
"filing_status": "Single",
"extra_withholding": "0.0",
"two_jobs": true,
"dependents_amount": "0.0",
"other_income": "0.0",
"deductions": "0.0",
"w4_data_type": "rev_2020_w4"
}
'
const fetch = require('node-fetch');
const url = 'https://api.gusto-demo.com/v1/employees/{employee_uuid}/federal_taxes';
const options = {
method: 'PUT',
headers: {
accept: 'application/json',
'content-type': 'application/json',
authorization: 'Bearer <<COMPANY_API_TOKEN>>'
},
body: JSON.stringify({
version: '56a489ce86ed6c1b0f0cecc4050a0b01',
filing_status: 'Single',
extra_withholding: '0.0',
two_jobs: true,
dependents_amount: '0.0',
other_income: '0.0',
deductions: '0.0',
w4_data_type: 'rev_2020_w4'
})
};
fetch(url, options)
.then(res => res.json())
.then(json => console.log(json))
.catch(err => console.error('error:' + err));
c. Update an Employee's State Taxes
The data required to correctly calculate an employee's state taxes varies by both home and work location.
To know which information is needed for an Employee's State Taxes, first use the GET employees/{employee_uuid}/state_taxes
endpoint. This will return an array of questions that must be answered, and possible answers for each, and what we currently have marked as that answer. Below is an example for the state of CA with the following answers:
filing_status = S
, withholding_allowance = 1
, additional_withholding = 0.0
, file_new_hire_report = false
{
"employee_uuid": "92fa4d30-e284-43d0-a26e-605619c04beb",
"file_new_hire_report": false,
"is_work_state": true,
"state": "CA",
"questions": [
{
"label": "Filing Status",
"description": "The Head of Household status applies to unmarried individuals who have a relative living with them in their home. If unsure, read the <a target='_blank' data-bypass rel='noopener noreferrer' tabindex='99' href='https://www.ftb.ca.gov/file/personal/filing-status/index.html'>CA Filing Status explanation</a>.\n",
"key": "filing_status",
"input_question_format": {
"type": "Select",
"options": [
{
"value": "S",
"label": "Single"
},
{
"value": "M",
"label": "Married one income"
},
{
"value": "MD",
"label": "Married dual income"
},
{
"value": "H",
"label": "Head of household"
},
{
"value": "E",
"label": "Do Not Withhold"
}
]
},
"answers": [
{
"value": "S",
"valid_from": "2010-01-01",
"valid_up_to": null
}
]
},
{
"label": "Withholding Allowance",
"description": "This value is needed to calculate the employee's CA income tax withholding. If unsure, use the <a target='_blank' data-bypass rel='noopener noreferrer' tabindex='99' href='http://www.edd.ca.gov/pdf_pub_ctr/de4.pdf'>CA DE-4 form</a> to calculate the value manually.\n",
"key": "withholding_allowance",
"input_question_format": {
"type": "Number"
},
"answers": [
{
"value": 1,
"valid_from": "2010-01-01",
"valid_up_to": null
}
]
},
{
"label": "Additional Withholding",
"description": "You can withhold an additional amount of California income taxes here.",
"key": "additional_withholding",
"input_question_format": {
"type": "Currency"
},
"answers": [
{
"value": "0.0",
"valid_from": "2010-01-01",
"valid_up_to": null
}
]
},
{
"label": "File a New Hire Report?",
"description": "State law requires you to file a new hire report within 20 days of hiring or re-hiring an employee.",
"key": "file_new_hire_report",
"input_question_format": {
"type": "Select"
},
"answers": [
{
"value": false,
"valid_from": "2010-01-01",
"valid_up_to": null
}
]
}
]
}
Once you know which information needs to be added/updated, you can use the PUT employees/{employee_uuid}/state_taxes
endpoint.
curl --request PUT \
--url https://api.gusto-demo.com/v1/employees/{employee_uuid}/state_taxes \
--header 'accept: application/json' \
--header 'authorization: Bearer <<COMPANY_API_TOKEN>>' \
--header 'content-type: application/json' \
--data '
{
"employee_id": "87156178-62f8-46d4-a026-ed9de3e8f836",
"states": [
{
"state": "CA",
"questions": [
{
"key": "filing_status",
"answers": [
{
"value": "M",
"valid_from": "2010-01-01",
"valid_up_to": null
}
]
},
{
"key": "withholding_allowance",
"answers": [
{
"value": 2,
"valid_from": "2010-01-01",
"valid_up_to": null
}
]
},
{
"key": "additional_withholding",
"answers": [
{
"value": "25.0",
"valid_from": "2010-01-01",
"valid_up_to": null
}
]
},
{
"key": "file_new_hire_report",
"answers": [
{
"value": true,
"valid_from": "2010-01-01",
"valid_up_to": null
}
]
}
]
}
]
}
'
const fetch = require('node-fetch');
const url = 'https://api.gusto-demo.com/v1/employees/{employee_uuid}/state_taxes';
const options = {
method: 'PUT',
headers: {
accept: 'application/json',
'content-type': 'application/json',
authorization: 'Bearer <<COMPANY_API_TOKEN>>'
},
body: JSON.stringify({
employee_id: '87156178-62f8-46d4-a026-ed9de3e8f836',
states: [
{
state: 'CA',
questions: [
{
key: 'filing_status',
answers: [{value: 'M', valid_from: '2010-01-01', valid_up_to: null}]
},
{
key: 'withholding_allowance',
answers: [{value: 2, valid_from: '2010-01-01', valid_up_to: null}]
},
{
key: 'additional_withholding',
answers: [{value: '25.0', valid_from: '2010-01-01', valid_up_to: null}]
},
{
key: 'file_new_hire_report',
answers: [{value: true, valid_from: '2010-01-01', valid_up_to: null}]
}
]
}
]
})
};
fetch(url, options)
.then(res => res.json())
.then(json => console.log(json))
.catch(err => console.error('error:' + err));
d. Create an Employee Bank Account
Creating an employee bank account will automatically update an employeeโs payment method from Check
to Direct Deposit
. If you want to change the payment method you can use the PUT employees/{employee_uuid}/payment_method
endpoint. To create a bank account for an Employee use the POST employees/{employee_uuid}/bank_account
endpoint.
curl --request POST \
--url https://api.gusto-demo.com/v1/employees/{employee_uuid}/bank_accounts \
--header 'accept: application/json' \
--header 'authorization: Bearer <<COMPANY_API_TOKEN>>' \
--header 'content-type: application/json' \
--data '
{
"name": "BoA Checking Account",
"routing_number": "266905059",
"account_number": "5809431207",
"account_type": "Checking"
}
'
const fetch = require('node-fetch');
const url = 'https://api.gusto-demo.com/v1/employees/{employee_uuid}/bank_accounts';
const options = {
method: 'POST',
headers: {
accept: 'application/json',
'content-type': 'application/json',
authorization: 'Bearer <<COMPANY_API_TOKEN>>'
},
body: JSON.stringify({
name: 'BoA Checking Account',
routing_number: '266905059',
account_number: '5809431207',
account_type: 'Checking'
})
};
fetch(url, options)
.then(res => res.json())
.then(json => console.log(json))
.catch(err => console.error('error:' + err));
4. (Optional) Enroll the employee in a Time Off policy (sick, vacation, etc)
If you company already has a Time Off Policy, you can enroll your employee after they are onboarded. To add an employee to a time off policy, use the PUT time_off_policies/{time_off_policy_uuid}/add_employees
endpoint.
curl --request PUT \
--url https://api.gusto-demo.com/v1/time_off_policies/time_off_policy_uuid/add_employees \
--header 'accept: application/json' \
--header 'authorization: Bearer <<COMPANY_API_TOKEN>>' \
--header 'content-type: application/json' \
--data '
{
"employee": [
{
"uuid": "56c672b4-3918-45cd-a3bb-a62ae0ff1307",
"balance": "40.0"
},
{
"uuid": "28e7a45d-32dd-4925-a82a-9a3ccc6d302c",
"balance": "40.0"
},
{
"uuid": "f60650da-ba18-417a-b2ab-3c9b6f0fe4f2",
"balance": "20.0"
}
]
}
'
const fetch = require('node-fetch');
const url = 'https://api.gusto-demo.com/v1/time_off_policies/time_off_policy_uuid/add_employees';
const options = {
method: 'PUT',
headers: {
accept: 'application/json',
'content-type': 'application/json',
authorization: 'Bearer <<COMPANY_API_TOKEN>>'
},
body: JSON.stringify({
employee: [
{uuid: '56c672b4-3918-45cd-a3bb-a62ae0ff1307', balance: '40.0'},
{uuid: '28e7a45d-32dd-4925-a82a-9a3ccc6d302c', balance: '40.0'},
{uuid: 'f60650da-ba18-417a-b2ab-3c9b6f0fe4f2', balance: '20.0'}
]
})
};
fetch(url, options)
.then(res => res.json())
.then(json => console.log(json))
.catch(err => console.error('error:' + err));
5. (Optional) Add employee benefits and deductions
You can add benefits and deductions to your employee's compensation following the Create Company Benefits guide.
6. Mark Employee as Onboarded
With the basic details, address, payment method, and tax information complete, the final step is to mark the employer as onboarding_completed
. This is done using the PUT employees/{employee_uuid}/onboarding_status
endpoint. You will want to change the status to onboarding_completed
in the body.
curl --request PUT \
--url https://api.gusto-demo.com/v1/employees/employee_id/onboarding_status \
--header 'accept: application/json' \
--header 'authorization: Bearer <<COMPANY_API_TOKEN>>' \
--header 'content-type: application/json' \
--data '
{
"onboarding_status": "onboarding_completed"
}
'
const fetch = require('node-fetch');
const url = 'https://api.gusto-demo.com/v1/employees/employee_id/onboarding_status';
const options = {
method: 'PUT',
headers: {
accept: 'application/json',
'content-type': 'application/json',
authorization: 'Bearer <<COMPANY_API_TOKEN>>'
},
body: JSON.stringify({onboarding_status: 'onboarding_completed'})
};
fetch(url, options)
.then(res => res.json())
.then(json => console.log(json))
.catch(err => console.error('error:' + err));
Updated over 1 year ago