Complete a Regular Payroll
Your embedded payroll product allows the Company to pay the Employees the right amount at the right cadence, while accounting for tax implications.
We automatically pre-generate scheduled regular payrolls based on the companyโs pay schedule and corresponding pay periods. Pay periods are the foundation of payroll. Compensation, time & attendance, taxes, and expense reports all rely on when they happened.
Before using this guide you need a fully onboarded Company and Employee.
1. Retrieve Upcoming Payroll
Upcoming regular payrolls can be retrieved using the GET companies/{company_uuid}/payrolls?processing_statuses=unprocessed
endpoint. The next upcoming payroll will be the earliest unprocessed payroll. By default, the payrolls#index endpoint will return only processed payrolls so make sure to add the processing_statuses=unprocessed
query param. You can use the optional query parameters start_date
& end_date
to narrow or expand the response.
The example cURL below is filtering to show unprocessed payrolls, including off cycle, the dates for payroll is between 2021-02-01
and 2021-03-01
. To see all query values review our API Reference.
curl --request GET \
--url 'https://api.gusto-demo.com/v1/companies/company_id/payrolls?processing_statuses=unprocessed&payroll_types=regular,off_cycle&start_date=2021-02-01&end_date=2021-03-31' \
--header 'accept: application/json' \
--header 'authorization: Bearer <<COMPANY_API_TOKEN>>'
const fetch = require('node-fetch');
const url = 'https://api.gusto-demo.com/v1/companies/company_id/payrolls?processed=false&include_off_cycle=true&include=&include=deductions&start_date=2021-02-01&end_date=2021-03-31';
const options = {
method: 'GET',
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));
This query will return an JSON array of payroll objects:
[
{
"payroll_deadline": "2021-02-18T20:00:00Z",
"check_date": "2021-02-22",
"processed": false,
"processed_date": null,
"calculated_at": null,
"payroll_uuid": "b50e611d-8f3d-4f24-b001-46675f7b5777",
"company_uuid": "6bf7807c-a5a0-4f4d-b2e7-3fbb4b2299fb",
"pay_period": {
"start_date": "2021-02-01",
"end_date": "2021-02-15",
"pay_schedule_uuid": "00ebc4a4-ec88-4435-8f45-c505bb63e501"
}
}
]
2. Prepare & Update Payroll (Optional)
If there is information about the payroll that needs to be updated, start by using the PUT companies/{company_uuid}/payrolls/{payroll_uuid}/prepare
endpoint. This endpoint will return the version
and the employee_compensations data you need to update a payroll.
You can update Regular Hours, Overtime, and Double overtime for Salaried Nonexempt employees, but only Regular Hours can be updated for Exempt employees since they are not eligible for overtime.
New in v2024-03-01
- The
version
field in the payroll moved from the top level payroll to eachemployee_compensations
object. Theversion
for each employee compensation should now be included in the payroll update request. - All applicable fixed compensations are no longer included in the
employee_compensations
response from preparing a payroll. To add a fixed compensation for an employee, when updating a payroll include a new object in thefixed_compensations
array with a validname
andamount
. All applicable fixed compensation names are included in thefixed_compensation_types
array in the prepare response.
curl --request PUT \
--url https://api.gusto-demo.com/v1/companies/{company_uuid}/payrolls/{payroll_uuid}/prepare \
--header 'accept: application/json' \
--header 'authorization: Bearer <<COMPANY_API_TOKEN>>' \
--header 'content-type: application/json'
const fetch = require('node-fetch');
const url = 'https://api.gusto-demo.com/v1/companies/{company_uuid}/payrolls/prepare';
const options = {
method: 'PUT',
headers: {
accept: 'application/json',
'content-type': '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));
Here is a sample response from the prepare endpoint:
{
"payroll_deadline": "2022-02-18T22:00:00Z",
"check_date": "2021-02-22",
"processed": false,
"processed_date": null,
"calculated_at": null,
"payroll_uuid": "b50e611d-8f3d-4f24-b001-46675f7b5777",
"company_uuid": "6bf7807c-a5a0-4f4d-b2e7-3fbb4b2299fb",
"pay_period": {
"start_date": "2021-02-01",
"end_date": "2021-02-15",
"pay_schedule_uuid": "00ebc4a4-ec88-4435-8f45-c505bb63e501"
},
"payroll_status_meta": {
"cancellable": false,
"expected_check_date": "2022-02-22",
"initial_check_date": "2022-02-22",
"expected_debit_time": "2022-02-18T22:00:00Z",
"payroll_late": false,
"initial_debit_cutoff_time": "2022-02-18T22:00:00Z"
},
"employee_compensations": [
{
"employee_uuid": "187412e1-3dbe-491a-bb2f-2f40323a7067",
"version": "19289df18e6e20f797de4a585ea5a91535c7ddf7",
"excluded": false,
"payment_method": "Direct Deposit",
"fixed_compensations": [],
"hourly_compensations": [
{
"name": "Regular Hours",
"hours": "40.000",
"job_uuid": "bd378298-3e0c-4145-904a-baadf8a91fa3",
"compensation_multiplier": 1,
"flsa_status": "Nonexempt"
},
{
"name": "Overtime",
"hours": "15.000",
"job_uuid": "9d3760f0-d1f9-4700-8817-0fe2dce5cf23",
"compensation_multiplier": 1.5,
"flsa_status": "Nonexempt"
},
{
"name": "Double overtime",
"hours": "0.000",
"job_uuid": "b5eef9a9-4a87-4649-a80d-14878c05f44e",
"compensation_multiplier": 2,
"flsa_status": "Nonexempt"
},
{
"name": "Regular Hours",
"hours": "40.000",
"job_uuid": "332bd171-9efc-432b-abbb-a75c9dba706a",
"compensation_multiplier": 1,
"flsa_status": "Nonexempt"
},
{
"name": "Overtime",
"hours": "5.000",
"job_uuid": "ca9b3dc1-57ac-4736-901a-9b1c9634b9d5",
"compensation_multiplier": 1.5,
"flsa_status": "Nonexempt"
},
{
"name": "Double overtime",
"hours": "0.000",
"job_uuid": "1bad01e2-140c-49ed-9542-2388ce4a19b3",
"compensation_multiplier": 2,
"flsa_status": "Nonexempt"
}
],
"paid_time_off": [
{
"name": "Vacation Hours",
"hours": "20.000"
},
{
"name": "Sick Hours",
"hours": "0.000"
},
{
"name": "Holiday Hours",
"hours": "0.000"
}
]
}
],
"fixed_compensation_types": [
{
"name": "Bonus"
},
{
"name": "Commission"
},
{
"name": "Correction Payment"
},
{
"name": "Cash Tips"
},
{
"name": "Paycheck Tips"
},
{
"name": "Reimbursement"
}
]
}
Next you can update the payroll with the new employee_compensation data with the PUT companies/{company_uuid}/payrolls/{payroll_uuid}
endpoint, passing in the updated employee_compensations
params from the prepare endpoint.
curl --request PUT \
--url https://api.gusto-demo.com/v1/companies/{company_uuid}/payrolls/{payroll_uuid} \
--header 'accept: application/json' \
--header 'authorization: Bearer <<COMPANY_API_TOKEN>>' \
--header 'content-type: application/json' \
--data '
{
"employee_compensations": [
{
"employee_uuid": "187412e1-3dbe-491a-bb2f-2f40323a7067",
"version": "19289df18e6e20f797de4a585ea5a91535c7ddf7",
"excluded": false,
"payment_method": "Direct Deposit",
"fixed_compensations": [
{
"name": "Bonus",
"amount": "200.00",
}
],
"hourly_compensations": [
{
"name": "Regular Hours",
"hours": "30.000",
"job_uuid": "91bc3b43-ded0-4ee7-98fe-215499e909ba"
},
{
"name": "Double overtime",
"hours": "20.000",
"job_uuid": "bd378298-3e0c-4145-904a-baadf8a91fa3"
},
{
"name": "Overtime",
"hours": "10.000",
"job_uuid": "9d3760f0-d1f9-4700-8817-0fe2dce5cf23"
}
],
"paid_time_off": [
{
"name": "Vacation Hours",
"hours": "25.000"
},
{
"name": "Sick Hours",
"hours": "10.000"
},
{
"name": "Holiday Hours",
"hours": "8.000"
}
]
}
]
}
'
const fetch = require('node-fetch');
const url = 'https://api.gusto-demo.com/v1/companies/{company_uuid}/payrolls/{payroll_uuid}';
const options = {
method: 'PUT',
headers: {
accept: 'application/json',
'content-type': 'application/json',
authorization: 'Bearer <<COMPANY_API_TOKEN>>'
},
body: JSON.stringify({
employee_compensations: [
{
employee_uuid: '187412e1-3dbe-491a-bb2f-2f40323a7067',
version: '19289df18e6e20f797de4a585ea5a91535c7ddf7',
excluded: false,
payment_method: 'Direct Deposit',
fixed_compensations: [
{
name: 'Bonus',
amount: '200.00'
}
],
hourly_compensations: [
{
name: 'Regular Hours',
hours: '30.000',
job_uuid: '91bc3b43-ded0-4ee7-98fe-215499e909ba'
},
{
name: 'Double overtime',
hours: '20.000',
job_uuid: 'bd378298-3e0c-4145-904a-baadf8a91fa3'
},
{
name: 'Overtime',
hours: '10.000',
job_uuid: '9d3760f0-d1f9-4700-8817-0fe2dce5cf23'
}
],
paid_time_off: [
{name: 'Vacation Hours', hours: '25.000'},
{name: 'Sick Hours', hours: '10.000'},
{name: 'Holiday Hours', hours: '8.000'}
]
}
]
})
};
fetch(url, options)
.then(res => res.json())
.then(json => console.log(json))
.catch(err => console.error('error:' + err));
The update endpoint will return the same response data as prepare, with the data reflecting your changes.
3. Calculate the Payroll
Once a payroll is updated, use the PUT companies/{company_id}/payrolls/{payroll_id}/calculate
endpoint to calculate the taxes, benefits, and deductions for the unprocessed payroll. The calculated payroll details provide a preview of the actual values that will be used when the payroll is run. Any benefits or deductions - mandatory or voluntary - that are set up for the employee at the time payroll is calculated will automatically be factored in.
This calculation is asynchronous and a successful request responds with a 202 HTTP status. To view the details of the calculated payroll, poll the GET /v1/companies/{company_uuid}/payrolls/{payroll_uuid}
endpoint with theinclude=taxes,benefits,deductions
param, until the payroll returns with the calculated_at
field populated with a timestamp. The payroll will include any submission_blockers
and will also return a totals
attribute once it is calculated.
curl --request PUT \
--url https://api.gusto-demo.com/v1/companies/{company_uuid}/payrolls/{payroll_uuid}/calculate \
--header 'authorization: Bearer <<COMPANY_API_TOKEN>>'
const fetch = require('node-fetch');
const url = 'https://api.gusto-demo.com/v1/companies/{company_uuid}/payrolls/{payroll_uuid}/calculate';
const options = {method: 'PUT', headers: {authorization: 'Bearer <<COMPANY_API_TOKEN>>'}};
fetch(url, options)
.then(res => res.json())
.then(json => console.log(json))
.catch(err => console.error('error:' + err));
If you need to make further updates to the payroll after calculating, use the PUT companies/{company_uuid}/payrolls/{payroll_uuid}/prepare
endpoint again, which will cancel out the calculations and return the payroll version
used for updates.
4. Submit Payroll
Preview UI
We recommend building a UI where the user can review their payroll before submitting. The displayed information can be customized to fit your unique business needs, but we highly recommend a preview step to provide the user with the payroll details before they finalize it. Typically this includes a breakdown of total payroll, taxes, and debits.
If everything looks accurate, a payroll can be processed using the PUT companies/{company_uuid}/payrolls/{payroll_uuid}/submit
endpoint. Upon success, this request transitions the payroll to the processed
state and initiates the transfer of funds. This is a critical step to process payroll. A payroll is not finalized without calling this endpoint.
This submission is asynchronous and a successful request responds with a 202 HTTP status. Upon success, the payroll status transitions to the processed
state. You should poll to ensure that payroll is processed successfully, as async errors only occur after async processing is complete.
curl --request PUT \
--url https://api.gusto-demo.com/v1/companies/{company_uuid}/payrolls/{payroll_uuid}/submit \
--header 'authorization: Bearer <<COMPANY_API_TOKEN>>'
const fetch = require('node-fetch');
const url = 'https://api.gusto-demo.com/v1/companies/{company_uuid}/payrolls/{payroll_uuid}/submit';
const options = {method: 'PUT', headers: {authorization: 'Bearer <<COMPANY_API_TOKEN>>'}};
fetch(url, options)
.then(res => res.json())
.then(json => console.log(json))
.catch(err => console.error('error:' + err));
Cancel a Payroll
You can revert a payroll to the
unprocessed
state using thePUT /companies/{company_uuid}/payrolls/{payroll_uuid}/cancel
endpoint. A payroll cannot be canceled after 3:30pm PST on thepayroll_deadline
.
5. Receive Payroll Receipts and Paystubs
Once a payroll is submitted, we recommend including a summary of the payroll for the end user to view the debit date, check date, and payroll details. The payroll receipt should also be available on this final step. See Payroll Receipts for more information.
You can retrieve Payroll Receipt using the GET payrolls/{payroll_uuid}/receipt
endpoint.
You can retrieve a W2 Employee's Paystub using the GET payrolls/{payroll_id}/employees/{employee_id}/pay_stub
endpoint.
You can also use the pre-built UI Flow for a payroll receipt.
Architecture Diagram
Updated about 2 months ago