Daily Pay & Earned Wage Access

In today’s fast-paced economy, workers often see their expenses outpace their pay schedule. As a way to attract more workers and increase satisfaction amongst staff, employers may want to offer options for employees to receive pay daily.

In this guide

  • Complications with the daily pay schedule.
  • Earned wage access.
  • Technical implementation.

Daily Pay

Placing workers on a daily pay schedule and running payroll every day comes with many administrative complications: ACH transfers are not generally fast enough to pay workers on demand; it may be difficult for employers to fund payroll every single day; the fast turn-around leaves less time for payroll admins to review timesheets. And so on…

In addition, a daily pay schedule can have undesired tax implications due to the way tax engines calculate withholdings. Tax engines must annualize wages and calculate withholdings based on the estimated annual salary. Annualizing wages on a daily pay schedule, instead of a more traditional weekly or biweekly schedule, can lead to less-accurate estimations of salary, and thus less-accurate withholdings. While this all will get resolved with end-of-year filings, it can still lead to employees that are dissatisfied by their wages being under or over-withheld. This is why Zeal recommends that our daily pay schedule only be used in unique circumstances.

Earned Wage Access

As an alternative to running payroll daily, many employers choose to offer earned wage access, or EWA. EWA has emerged as an industry standard, as it allows employees to access earned wages on demand, without the need to actually run payroll on a daily frequency.

The APA has great resources to learn more about EWA, but as an overview, the programs generally function as follows:

  1. The employer partners with an EWA provider that funds the wage access and runs the program.
  2. Employees can create an account with the EWA provider and set up a payment method (such as a pay card).
  3. As the employee completes their work, payroll data (timesheets, gross-to-net calculations, etc) is submitted to both the payroll provider and the EWA provider.
  4. The EWA provider grants the employee access to their net earnings (or a portion of earnings to reduce risk). The provider tracks the amount accessed for later steps.
  5. At the end of the reporting period, before payroll is run, the EWA provider gives a report of wages accessed per employee so that the employer can add a deduction with their payroll provider to reduce the net pay owed (accounting for the wages accessed).
  6. Finally, the EWA provider withdraws funds from the employer's bank account equaling the total amount of wages accessed by employees.

Technical Implementation

Zeal's APIs offer all the flexibility needed to integrate with an EWA provider.

Overview

As a one-time action:
Create a miscellaneous deduction template that defines the rules for deductions that will be used to reduce employees final net pay based on the earned wages they access.

💬

Note

Visit our Deductions Guide to learn more about setting up deduction templates.

For every payroll run:

  1. For each employee, collect time & attendance data and submit it as Shifts in an Employee Check.
  2. Use the Preview Payroll APIs to calculate the net pay the employee should have access to.
  3. Report the net pay to the EWA provider.
  4. When the EWA provider reports back wages that were accessed, use the deduction template to create a deduction for each Employee Check. The employee contribution should equal the total wages the employee accessed early.

Implementation

Create a Deduction Template

Set up a miscellaneous deduction template to be used for future payroll runs.

curl --request POST \
     --url https://api.zeal.com/deductionTemplate \
     --header 'Accept: application/json' \
     --header 'Authorization: Bearer {{testApiKey}}' \
     --header 'Content-Type: application/json' \
     --data '
{
    "companyID": "{{companyID}}",
    "deduction_type": "miscellaneous",
    "custom_name": "Earned Wage Access",
    "employee_contribution": {
        "contribution_type": "dollars",
        "override_type": "needs_input"
    }
}
'

Communicate payroll data

  1. Collect the hours the worker has completed for the day into a Shift Object.
  2. Get the reporting period for this check.
curl --request GET \
     --url 'https://api.zeal.com/reportingPeriod?companyID={{companyID}}&pay_schedule=weekly&searchStart=2022-01-01&searchEnd=2022-01-07' \
     --header 'Accept: application/json' \
     --header 'Authorization: Bearer {{testApiKey}}'
  1. Use the reportingPeriodID to check for any pending checks for this employee in this reporting period.
curl --request GET \
     --url 'https://api.zeal.com/employeeCheck?companyID={{companyID}}&employeeID={{employeeID}}&status=pending&reportingPeriodID={{reportingPeriodID}}' \
     --header 'Accept: application/json' \
     --header 'Authorization: Bearer {{testApiKey}}'
  1. If there is a pending check, use the returned employeeCheckID to add the shift to the pending check.
curl --request POST \
     --url https://api.zeal.com/shifts \
     --header 'Accept: application/json' \
     --header 'Authorization: Bearer {{testApiKey}}' \
     --header 'Content-Type: application/json' \
     --data '
{
    "companyID": "{{companyID}}",
    "employeeCheckID": "{{employeeCheckID}}",
    "shifts": [
        {
            "time": "2022-01-01T17:00:00Z",
            "hourly": {
                "hours": 8,
                "wage": 25
            }
        }
    ]
}'
  1. Else, compile the shift into a Employe Check Object and create a new check with the disbursement method marked as direct_deposit.
curl --request POST \
     --url https://api.zeal.com/employeeCheck \
     --header 'Accept: application/json' \
     --header 'Authorization: Bearer {{testApiKey}}' \
     --header 'Content-Type: application/json' \
     --data '
{
    "companyID": "{{companyID}}",
     "employeeID": "{{employeeID}}",
     "reportingPeriodID": "{{reportingPeriodID}}",
     "check_date": "2022-01-14"
     "approval_required": false,
     "disbursement": {
          "method": "direct_deposit"
     },
     "shifts": [
        {
            "time": "2022-01-01T17:00:00Z",
            "hourly": {
                "hours": 8,
                "wage": 25
            }
        }
    ],
}
'
  1. Take the Employee Check Object you get as a response (either to Add a Shift or Creating a Check) and use it in a request to Preview Check Data.
curl --request POST \
     --url https://api.zeal.com/preview/checkData \
     --header 'Authorization: Bearer {{testApiKey}}' \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '
{
     "companyID": "{{companyID}}",
     "employeeID": "{{employeeID}}",
     "reportingPeriodID": "{{reportingPeriodID}}",
     "check_date": "2022-01-14",
     "shifts": [
          {
          	"time": "2022-11-05T17:00:00Z",
            "hourly: {
               "hours": 8,
               "wage": 25
            }
          }
     ],
}
'

🪄

Tip

Alternatively, you may use the employeeCheckID alone in a call to Preview Payroll by Check IDs and handle the job request asynchronously. See Preview Payroll Guide for more information.

  1. This will return a preview of the withholdings from the check as well as the net pay.
{
    "success": true,
    "data": {
        "success": true,
        "result": {
            "checks": [
                {
                    "gross_pay": "200.00",
                    "net_pay": "183.58",
                    "employer_taxes": "26.10",
                    "employee_taxes": "16.42",
                    "employee_deductions": "0.00",
                    "employer_deductions": "0.00",
                    "taxes": [
                        {
                            "name": "Federal Income Tax",
                            "codename": "FIT",
                            "amount": "0.00"
                        },
                        {
                            "name": "Social Security",
                            "codename": "FICA_SocialSecurity_EE",
                            "amount": "12.40"
                        },
                        {
                            "name": "Social Security",
                            "codename": "FICA_SocialSecurity_ER",
                            "amount": "12.40"
                        },
                        {
                            "name": "Medicare",
                            "codename": "FICA_Medicare_EE",
                            "amount": "2.90"
                        },
                        {
                            "name": "Medicare",
                            "codename": "FICA_Medicare_ER",
                            "amount": "2.90"
                        },
                        {
                            "name": "Medicare Additional",
                            "codename": "FICA_MedicareAdditional_EE",
                            "amount": "0.00"
                        },
                        {
                            "name": "Federal Unemployment Tax",
                            "codename": "FUTA",
                            "amount": "0.00"
                        },
                        {
                            "name": "State Unemployment Tax",
                            "codename": "SUTA_AK",
                            "amount": "10.80"
                        },
                        {
                            "name": "State Unemployment Tax",
                            "codename": "SUI_AK",
                            "amount": "1.12"
                        }
                    ]
                }
            ],
            "total_employer_taxes": "26.10",
            "total_employee_taxes": "16.42",
            "total_employee_deductions": "0.00",
            "total_employer_deductions": "0.00"
        }
    }
}
  1. Communicate this net pay, or a portion (e.g. 50%, 80%) based on your risk tolerance, to your EWA provider.

Add deduction to the check

  1. Using the deductionTemplateID from the first step, the employeeCheckID, and the wages accessed by the employee to create a deduction for this check.
curl --request POST \
     --url https://api.zeal.com/deductions \
     --header 'Authorization: Bearer {{testApiKey}}' \
     --header 'accept: application/json' \
     --header 'content-type: application/json'
     --data '
{
    "companyID": "{{companyID}}",
    "deductionTemplateID": "{{deductionTemplateID}}",
    "employeeCheckID": "{{employeeCheckID}}",
    "deduction": {
        "employee_contribution": {
            "value": 146.86
        }
    }
}
'     
  1. Now that the deduction has been added, Zeal will know to deduct this amount from the total net pay we disburse to the employee's bank account through direct deposit.
  2. The funds will remain in the employer's account to be debited by the EWA provider.

Recap

Earned wage access is a rather advanced use case that brings a lot of moving pieces together. However, when executed correctly, it provides a competitive advantage for employers and a better experience for workers.