Accrual Policies

Learn how to set up and manage a PTO or Sick Time Policy for your workers

Intro

Offering a a PTO or sick time policy is a good way to attract a great workforce and can be critical for employer compliance. Managing these policies, however, involves proper accrual rates, PTO usages, capping PTO balances, rollovers, etc.

In Zeal, Accrual Policies represent policies that can be accrued by and assigned to workers. These Accrual Policies, when attached to a worker, contain an accrual balance that is automatically tracked and updated by Zeal based on the worker's shifts as well as their specific Accrual Policy specifications.

In this guide

  • What an accrual policy is
  • How to set up a standard policy
  • How to add employees to a policy
  • How to track usages that affect the balance (e.g. PTO usage)
  • How to handle more complex rules

What is an accrual policy?

An accrual policy is simply a set of rules that define how employees accrue hours for various perks such as PTO or sick leave. The basic rules generally state the rate of accrual and the number of hours that must be worked before that rate is accrued (e.g. an employee earns 5 hours for every 80 hours worked). The policy may also include more complicated rules such as annual caps, wait periods, and rollover rules.


Managing a standard PTO policy

Letโ€™s start with a basic accrual policy. Weโ€™ll define a PTO policy where employees accrue 5 hours off for every 80 hours worked.

Step 1: Create the policy

To create an Accrual Policy, utilize the Create Accrual Policy or POST /accrualPolicy endpoint. The endpoint requires the following body parameters:

  • companyID: Zeal Company ID
  • policy_code: Custom code you must assign for the policy. This is the unique identifier for the policy
  • policy_type: Type of the accrual policy (accepts: pto, sick_leave, or custom).
    Note: The accrual policy type has no effects on other parameters other than classification of the accrual policy. Therefore, a pto policy type does not differ from a sick_leave type other than in classification.

Other parameters:

As mentioned in the Accrual Policy object reference, the POST endpoint accepts other body parameters to further specify the Accrual Policy being created:

attributetypedescription
policy_namestringCustom name that can be assigned for the policy
policy_effective_dateYYYY-MM-DDThe effective start date of the policy
accrual_rate_hoursfloatThe rate at which employees will accrue hours
accrual_period_hoursfloatThe number of hours employees need to work to accrue accrual_rate_hours
immediate_balancefloatThe immediate hour balance the employee would receive
include_doubletimebooleanInclude if double-time work is eligible for hour accrual
include_overtimebooleanInclude if overtime work is eligible for hour accrual
accrual_waiting_periodfloatThe number of hours the employees need to work before they are eligible to begin accruing time for policy
accrual_capfloatMax hours an employee can accrue in one year until the rollover date
rollover_capfloatMax hours an employee can rollover from one year to the next year, on a specified rollover date
rollover_datefloatRequired if the user passes a value for rollover_cap or accrual_cap

Letโ€™s create a PTO policy with an accrual rate of 5 hours for every 80 hours worked. We will setaccrual_rate_hours at 5 and accrual_period_hours to 80.

Create accrual policy

curl --request POST \
     --url https://api.zeal.com/accrualPolicy \
     --header 'Authorization: Bearer {{TEST_API_KEY}}' \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '
{
  "companyID": "{{companyID}}",
  "policy_code": "PTO-01",
  "policy_type": "pto",
  "accrual_rate_hours": "5",
  "accrual_period_hours": "80",
	"include_doubletime": false,
  "include_overtime": false,
}
'

This will return an Accrual Policy object:

{
  "companyID": "e9a3c22ea5276a1ea82dba27ca6e1a2ea",
  "policy_code": "PTO-01",
  "policy_type": "pto",
  "policy_name": null,
  "policy_effective_date": "2023-03-01",
  "accrual_rate_hours": 5,
  "accrual_period_hours": 80,
  "immediate_balance": 0,
  "include_doubletime": false,
  "include_overtime": false,
  "accrual_waiting_period": 0,
  "accrual_cap": 0,
  "rollover_cap": 0,
  "rollover_date": null,
  "policy_status": "live"
}

Step 2: Add employees

With the policy created, next we add our employees to the policy.

Add/remove employees to accrual policy

curl --request POST \
     --url https://api.zeal.com/accrualPolicyEmployees \
     --header 'Authorization: Bearer {{TEST_API_KEY}}' \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '
{
  "add_employees": [
    "{{firstEmployeeID}}",
    "{{secondEmployeeID}",
    "{{thirdEmployeeID}"
  ],
  "companyID": "{{companyID}}",
  "policy_code": "PTO-01"
}
'

All the employees added will now automatically begin accruing hours based on the payroll hours submitted.

Step 3: Get accrual balance

We can get the balance of an employee at any time.

Get accrual balance

curl --request GET \
     --url 'https://api.zeal.com/accrualBalance?companyID={{companyID}}&employeeID={{employeeID}}' \
     --header 'Authorization: Bearer {{TEST_API_KEY}}' \
     --header 'accept: application/json'

This will give us a response detailing the policy and the hours the employee has under that policy.

{
  "success": true,
  "data": {
    "companyID": "{{companyID}}",
    "accrualPolicies": [
      {
        "policy_code": "PTO-01",
        "employeeID": "{{employeeID}}",
        "policy_type": "pto",
        "accrual_balance": 20,
        "accrual_rate_unit": "hours",
        "policy_status": "live"
      }
    ]
  }
}

Step 4: Apply accrual usage

When an employee requests off and completes it, we can apply usage, which affects the employee's balance. Let's say our employee takes 16 hours off (from their previous balance of 20hrs).

Apply accrual usage

curl --request PATCH \
     --url https://api.zeal.com/accrualPolicy/{{policyCode}}/usage \
     --header 'Authorization: Bearer {{TEST_API_KEY}}' \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '
{
  "employees": [
    {
      "employeeID": "66c7738bbabb2213d7628c02",
      "start_date": "2024-12-10",
      "end_date": "2024-12-12",
      "amount": 16
    }
  ],
  "companyID": "{{companyID}}"
}
'

Now the employee's balance is updated to 4 hours of PTO. They continue to accrue hours automatically as they work. The next time the employee completes a PTO request, we simply repeat step 4.

Here are a few important notes:

  1. The accrual policy that you are referencing as a path parameter (using policyCode) in this request must have a valid policy_effective_date.
  2. The employee must already be added to the accrual policy in order for you to assign usage for this employee and under this accrual policy.
  3. Zeal finds an employee check for this employee with the reporting period that encapsulates the start_date of the usage object.
    1. For example, if an employee check was created for Jim with reporting period January 6th - January 13th and an accrual usage was set with start_date January 8th and end_date January 15th, (Jan 8th-Jan 15th), then Zeal will attach the usage to this check because the start_date falls within the reporting period of that check.
    2. If there is no existing check for this employee with a reporting period that encapsulates the start_date, then you will get an error (No check for given date range)
  4. Usage will also show on the paystub of an existing employee check with a reporting period that encompasses the start_date of the usage object.
  5. It is possible for the accrual balance to be negative for an employee, if using usage.

Corrections to Usage

In case you misapplied usage, you can make a similar call to adjust the usage and balance.

Let's say instead of using 16 hours, this worker actually only used 14 hours. You can apply a correction of 2 hours, reducing the employee's usage within the same date range used above:

curl --request PATCH \
     --url https://api.zeal.com/accrualPolicy/{{policyCode}}/usage \
     --header 'Authorization: Bearer {{TEST_API_KEY}}' \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '
{
  "employees": [
    {
      "employeeID": "66c7738bbabb2213d7628c02",
      "start_date": "2024-12-10",
      "end_date": "2024-12-12",  
      "correction": true,  
      "amount": 2
    }
  ],
  "companyID": "{{companyID}}"
}
'

After this request is applied, the total usage for the employee within the specified date range would be calculated to 14 (instead of 16 previously).

Handling more complex cases

Many accrual policies have additional rules such as annual caps, waiting periods, and rollovers. Thankfully, Zeal's system manages these complexities with ease.

Setting an annual cap

It's common to set a cap on the number of hours that can be accrued in one year. If you have such a policy in place, all you have to do is tell Zeal the cap, and the system will stop adding to an employee's balance once they've hit the annual limit. Let's update our policy with an accrual_cap set to 100 hours.

Update accrual policy

curl --request PATCH \
     --url https://api.zeal.com/accrualPolicy \
     --header 'Authorization: Bearer {{TEST_API_KEY}}' \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '
{
  "companyID": "{{companyID}}",
  "policy_code": "PTO-01",
  "accrual_cap": 100
}
'

Now our employee's are only able to accrue up to 100 hours of PTO within a calendar year. At midnight on the first day of the year, the cap resets and employees resume accruing hours.

Setting a waiting period

Many policies define a waiting period, or cliff, that an employee must meet before they can begin accruing hours. This is generally used to prevent new hires from immediately taking time off. Let's update our policy with a accrual_waiting_period of 160 hours.

Update accrual policy

curl --request PATCH \
     --url https://api.zeal.com/accrualPolicy \
     --header 'Authorization: Bearer {{TEST_API_KEY}}' \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '
{
  "companyID": "{{companyID}}",
  "policy_code": "PTO-01",
  "accrual_waiting_period": 160
}
'

Now our employees must work 160 hours before they are able to begin accruing PTO.

Setting rollover rules

Rollover rules define how many hours an employee can keep, or rollover, into the next year. These rules generally set a cap on hours and a date that the rollover happens. On the given date, any hours an employee has accrued above the cap are forfeited. This encourages employees to use their time off for rest and recuperation. Let's update our policy with a rollover_cap of 60 hours and the rollover_date of 01-01 (Jan. 1st).

Update accrual policy

curl --request PATCH \
     --url https://api.zeal.com/accrualPolicy \
     --header 'Authorization: Bearer {{TEST_API_KEY}}' \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '
{
  "companyID": "{{companyID}}",
  "policy_code": "PTO-01",
  "rollover_cap": 60,
  "rollover_date": "01-01"
}
'

Now with our rollover rules in place, employees can only carry up to 60 hours of PTO into the next calendar year. Note: many policies set the rollover date to the first day of the year, but you can set the date to whatever works for your policy.

Recap

  • An accrual policy is simply a set of rules that define how employees accrue hours for various perks such as PTO or sick leave
  • Managing accruals with Zeal generally involves 4 steps: create an accrual policy, add employees to the policy, query for accrual balances, apply usage when employees take time off
  • Zeal's system accounts for complex rules such as annual caps, waiting periods, and rollovers