GuidesAPI ReferenceChangelog
Log In
Guides

Payrolls

Payrolls can contain an overwhelming amount of information, but the basics of updating information should be a pain-free process.

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.

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 parameter. It's recommended to use the optional query parameters start_date & end_date to narrow the response in order to avoid potential timeouts.

The example cURL below is filtering to show unprocessed payrolls 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&start_date=2021-02-01&end_date=2021-03-31' \
     --header 'accept: application/json' \
     --header 'authorization: Bearer <<COMPANY_API_TOKEN>>'

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"
    }
  },
  {
    "payroll_deadline": "2021-03-01T20:00:00Z",
    "check_date": "2021-03-05",
    "processed": false,
    "processed_date": null,
    "calculated_at": null,
    "payroll_uuid": "79598603-2975-40fc-9b18-a6cf835a4744",
    "company_uuid": "6bf7807c-a5a0-4f4d-b2e7-3fbb4b2299fb",
    "pay_period": {
      "start_date": "2021-02-15",
      "end_date": "2021-02-28",
      "pay_schedule_uuid": "00ebc4a4-ec88-4435-8f45-c505bb63e501"
    }
  }
]

2. Prepare the Payroll

Before updating a payroll, it needs to be prepared 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 the payroll.

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'

Here is a sample response from the prepare endpoint:

{
  "payroll_deadline": "2021-02-18T20:00:00Z",
  "check_date": "2021-02-22",
  "processed": false,
  "processed_date": null,
  "calculated_at": null,
  "off_cycle": false,
  "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": "2021-02-22",
      "initial_check_date": "2021-02-22",
      "expected_debit_time": "2021-02-18T23:00:00Z",
      "payroll_late": false,
      "initial_debit_cutoff_time": "2021-02-18T23:00:00Z"
  },
  "employee_compensations": [
    {
      "employee_uuid": "187412e1-3dbe-491a-bb2f-2f40323a7067",
      "version": "19289df18e6e20f797de4a585ea5a91535c7ddf7",
      "excluded": false,
      "gross_pay": "2791.25",
      "net_pay": "1953.31",
      "payment_method": "Direct Deposit",
      "fixed_compensations": [
        {
          "name": "Bonus",
          "amount": "100.00",
          "job_uuid": "94e0d15e-9ed2-4077-98f6-64554f242ba5"
        },
        {
          "name": "Reimbursement",
          "amount": "100.00",
          "job_uuid": "91bc3b43-ded0-4ee7-98fe-215499e909ba"
        }
      ],
      "hourly_compensations": [
        {
          "name": "Regular Hours",
          "hours": "10.000",
          "job_uuid": "bd378298-3e0c-4145-904a-baadf8a91fa3",
          "compensation_multiplier": 1
        },
        {
          "name": "Overtime",
          "hours": "0.000",
          "job_uuid": "9d3760f0-d1f9-4700-8817-0fe2dce5cf23",
          "compensation_multiplier": 1.5
        },
        {
          "name": "Double overtime",
          "hours": "0.000",
          "job_uuid": "b5eef9a9-4a87-4649-a80d-14878c05f44e",
          "compensation_multiplier": 2
        }
      ],
      "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"
    }
  ]
}

3. Update the Payroll

Next you can update the payroll with the new employee_compensation data using the PUT companies/{company_uuid}/payrolls/{payroll_uuid} endpoint, passing in the version and updated employee_compensations parameters from the prepare endpoint. To add a fixed compensation for an employee compensation, add a new object to the fixed_compensations array with a valid name from fixed_compensation_types and an amount. If the amount is 0.00 it will not be persisted and returned in the update response.

🚧

Avoid Overwriting Data

Unless you are certain that you want to overwrite the data returned via the API, you should only add to it.

In our example, the employee already has 100.00 dollars of Reimbursement and 100.00 dollars of Bonus. In order to add 50 dollars to Reimbursement, 150.00 dollars, must be passed in order to maintain the amount existing prior to your update. We've also added a new object to the fixed_compensations array, 20.00 dollars in Cash Tips.

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": [
    {
      "fixed_compensations": [
        {
          "name": "Bonus",
          "amount": "100.00",
          "job_uuid": "94e0d15e-9ed2-4077-98f6-64554f242ba5"
        },
        {
          "name": "Reimbursement",
          "amount": "150.00",
          "job_uuid": "91bc3b43-ded0-4ee7-98fe-215499e909ba"
        },
        {  
          "name": "Cash Tips",
          "amount": "20.00",
          "job_uuid": "91bc3b43-ded0-4ee7-98fe-215499e909ba"
        }
      ],
      "employee_uuid": "187412e1-3dbe-491a-bb2f-2f40323a7067",
      "version": "19289df18e6e20f797de4a585ea5a91535c7ddf7"
    }
  ]
}
'
const fetch = require('node-fetch');

const url = 'https://api.gusto-demo.com/v1/companies/{company_uuid}/payrolls/2021-02-01/2021-02-15';
const options = {
  method: 'PUT',
  headers: {
    accept: 'application/json',
    'content-type': 'application/json',
    authorization: 'Bearer <<COMPANY_API_TOKEN>>'
  },
  body: JSON.stringify({
  employee_compensations: [
    {
      fixed_compensations: [
        {
          name: 'Bonus',
          amount: '100.00',
          job_uuid: '94e0d15e-9ed2-4077-98f6-64554f242ba5'
        },
        {
          name: 'Reimbursement',
          amount: '150.00',
          job_uuid: '91bc3b43-ded0-4ee7-98fe-215499e909ba'
        },
        {  
          name: 'Cash Tips',
          amount: '20.00',
          job_uuid: '91bc3b43-ded0-4ee7-98fe-215499e909ba'
        }
      ],
      employee_uuid: '187412e1-3dbe-491a-bb2f-2f40323a7067',
      version: '19289df18e6e20f797de4a585ea5a91535c7ddf7'
    }
  ]
})
};

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 shape as prepare, with the data reflecting your changes.

Conflicts

If information has changed since you last prepared the payroll, the version will have changed and you will receive a 409 Conflict response code. This means that you will need to re-prepare the payroll data for that pay period and resubmit your updates.

Do not simply copy over the new version and resubmit, as you'll likely be overwriting information that the user, an internal Gusto process, or another 3rd party application has added or changed. This can lead to incorrect pay, miscalculated taxes, and upset users.

Common Questions

Can we process payroll through the API?

No, given the sensitive nature of payroll, this should be done in Gusto to allow the user to review and confirm before processing.

Do we have access to form data, such as the W2 info or 941s?

Specific forms and their fields are not available in the API. However, the payrolls endpoint provides everything Gusto uses in our form calculations and you can pull this data to then calculate the form information you may need – be sure to consider benefits and time periods that may impact total taxable wages.

How do I set up a child-support garnishment in my Gusto demo account?

At this time we do not support child support garnishments in the demo environment since they require a valid Agency and CSE Case Number to set up. You will receive the following error message when attempting to set this up in demo: “Oh no! Something went wrong.”

How do I GET gross wage totals for paid time off (PTO)?

Our payroll endpoint will return a breakdown of PTO hours (vacation or sick) by employee for each payroll but not the total gross wages for total PTO in a given time period. However, this can be calculated using the number of hours returned for each time off type and the employees hourly rate. Our payrolls endpoint returns the raw payroll data, you just may need to set up some custom calculations on your end to get the data in the exact format you need.

How do I retrieve off-cycle and/or bonus payrolls?

The request GET /v1/companies/{company_uuid}/payrolls?processing_statuses=processed,unprocessed&payroll_types=off_cycle returns off-cycle payrolls, including bonus payrolls.