Update classified hours for entire pay period

This endpoint lets you specify the classified hours, per worker, for a pay period. You can include as many or as few workers as you want in a single call (subject to the size limit, below), and we only change the hours of the workers you include.

How to use this endpoint

The purpose of this endpoint is to synchronize a timesheet of hours, for many workers, at the same time. To do this accurately, follow the rules below for adding, editing, and removing hours.

📘

This is a "synchronize" operation, not an "add" operation

Each call replaces the hours we have on file; it never adds to them. For every worker you include, send the complete set of hours for the pay period each time, whether or not anything changed since your last sync.

Replacement is scoped to the worker, the pay period, and the work location. When you send hours for a work location (or for no work location, which means the worker's default location), we remove everything we already have for that worker, in that pay period, at that location, and replace it with the hours you sent. Hours the worker has at work locations you did not include are left untouched.

Let's say you send us 40 hours at Location A for Jane Appleseed for the January 3 - January 9 pay period. Later, you send us 8 hours for Jane at Location A for the same pay period. We will remove the 40 hours and keep only the 8. We do not combine the previous hours with the new hours, so if you split a worker's hours for one location across several calls, only the last call's hours are kept. If the second call were for Location B instead, Jane would have 40 hours at Location A and 8 hours at Location B.

Finally, if Jane was already paid for that pay period and you've authorized us to process corrections, we'll determine the difference between the old hours and the new hours, then handle the consequences automatically.

⚠️

Different earningDate values do not prevent a collision

Replacement ignores the individual date. If you send Jane's Monday shift with earningDate Monday, then her Tuesday shift with earningDate Tuesday, both at Location A in the same pay period, we keep only the Tuesday hours and the Monday hours are lost. The call still returns 200, so nothing warns you that hours were replaced. To avoid this, build one classifiedHours list per worker covering every shift in the period, and send it in one call.

Rules for each call

  • List each worker once per call. A call that includes the same worker more than once is rejected with a 400 error. Put all of a worker's hours, across all classifications, pay rates, and work locations, in that worker's single classifiedHours list.
  • Send all of a worker's hours for a work location together. If your system holds hours as separate timesheets (for example, one per shift or per client) for the same worker and work location in the same pay period, combine them before sending. This includes shifts on different days. Combine them into one list before sending, even when your system tracks each day separately.
  • Set earningDate to the last date of the pay period. earningDate tells us which pay period the hours belong to, and we recommend always sending the period's final day (for a Sunday–Saturday period, the Saturday) so the same value identifies the period on every call. Any date inside the period is currently accepted and resolves to the same pay period, but it does not scope the hours to that day. Do not send one call per shift date. A worker's hours are replaced by pay period and work location, so two calls with different earningDate values in the same period still replace each other. Send the worker's complete hours for the whole period in a single call. Hours sent with an earningDate in a pay period that has already been paid are rejected unless you authorize corrections (see below).
  • Workers you leave out are not changed. If you do not include a worker, we leave that worker's existing hours in place.

Adding and editing hours

To add or change a worker's hours, send that worker with the complete, correct set of hours for each work location that changed. We replace the worker's existing hours for those locations in the pay period with what you sent.

Removing hours

If you do not include a worker in the call, we make no changes to that worker's hours, because you haven't told us to remove anything.

To remove all of a worker's hours for the pay period, include the worker with every ...HoursWorked field set to "0.00". That explicitly instructs us to remove the hours we have on file.

But what if payroll has already been run?

This endpoint supports our automated Timesheet Corrections system. We can accept changes to hours for pay periods that have already been paid-out and automatically process the resulting additional payout or future reduction of wages. You just need to authorize the change using the correction-authorized=true parameter.

👍

You should consider authorizing corrections!

If you authorize us to process corrections to paid-out periods, it creates a seamless and automated workflow for payroll admins, and eliminates the need for manual double-entry in your system and ours. This is a nice experience!



How to structure the data

Typically, you'll need to send us some combination of regular, overtime, and double-time hours. You specify these in the appropriate field: regularHoursWorked, for instance.

But notice how each entry in a worker's classifiedHours list also has a payRate field. When using this endpoint, you're expected to provide a pay rate and exactly one of the ...HoursWorked fields for each entry. This allows you to provide the exact pay rate for each set of hours at each classification.

This is important because employers are required to pay overtime and double time at premium rates, and we won't calculate that premium rate automatically on your behalf, since we don't have enough information to do that.

Here are some examples of good and bad inputs:

// 👍 This is good! 👍
{
  "payRate": { "amount": "20.00", "currency": "USD" },
  "regularHoursWorked": "18.00"
}
// => 200 OK



// 👍 This is good! 👍
{
  "payRate": { "amount": "65.00", "currency": "USD" },
  "overtimeHoursWorked": "4.00"
}
// => 200 OK



// ❌ This is ambiguous and confusing. This will produce an error. ❌
{
  "payRate": { "amount": "20.00", "currency": "USD" },  
  "regularHoursWorked": "12.00",
  "overtimeHoursWorked": "2.25"
}
// => 400 Bad Request: "More than one type of hours is not allowed."

In summary: split regular, overtime, and double time hours into separate entries in the worker's classifiedHours list, to make sure you're sending us exactly the right pay rate + hours combination for each classification. A worker appears once in the request; their entries go inside that one worker object.



Example: one worker, two work locations, one call

This is the correct way to send a worker who worked at two locations in the same pay period. The worker appears once, with one entry per classification and location:

{
  "earningDate": "2026-01-09",
  "classifiedHoursPerWorker": [
    {
      "workerId": "0ee89b64-e8e4-4d80-baf2-a7dece28528a",
      "classifiedHours": [
        { "workLocationId": "1001", "payRate": { "amount": "20.00", "currency": "USD" }, "regularHoursWorked": "32.00" },
        { "workLocationId": "1001", "payRate": { "amount": "30.00", "currency": "USD" }, "overtimeHoursWorked": "4.00" },
        { "workLocationId": "1002", "payRate": { "amount": "20.00", "currency": "USD" }, "regularHoursWorked": "8.00" }
      ]
    }
  ]
}

Sending this worker again later with only the Location 1001 entries would replace the hours at 1001 and leave the hours at 1002 as they are.



Data size limitations

This endpoint is limited to a maximum of 200 entries in the classifiedHoursPerWorker list per call. If you need to provide hours for more than 200 employees, you will need to call this endpoint multiple times until you have provided hours for all employees with hours in the period. Split the workers across calls, never one worker's hours: each worker's complete hours for a work location must go in a single call, because a later call for the same worker and location replaces the earlier one.


Query Params
boolean
Defaults to false

Whether Everee should process a timesheet correction for a date that's already been paid-out. If false, creating a shift for a paid-out date will fail with an error.

Body Params
date
required

Any date within the pay period (inclusive of first and last day) to set hours for.

classifiedHoursPerWorker
array of objects
required

The classified hours for the given period. Only ONE of the fields "regularHoursWorked", "flsaQualifiedOvertimeHoursWorked", "nonFlsaQualifiedOvertimeHoursWorked", or "doubleTimeHoursWorked" may be populated (see above).

classifiedHoursPerWorker*
string
enum
Defaults to NEXT_PAYROLL_PAYMENT

If the given hours would correct timesheets for a pay period that's already been paid, specify the timeframe for paying out any underpaid wages.

Allowed:
Response

Language
Credentials
Header
LoadingLoading…