The Deductions API lets a benefits administration platform keep a worker's recurring deductions in Everee in sync with its own records. You can start, change and end deductions without anyone working in Everee.
There are three endpoints to set up deductions, one for each kind. They work the same way and differ in which pay codes and amount options they accept. A fourth, Get deduction reconciliation, reads back what payroll actually deducted. See Reconciling deductions.
| Endpoint | Use it for |
|---|---|
| Apply benefit deduction | Benefit plans: medical, dental, vision, HSA, FSA, life, disability and similar |
| Apply other deduction | Other recurring deductions: dues, savings, loan repayments |
| Apply retirement deduction | Retirement plans: 401(k), 403(b), IRAs |
| Get deduction reconciliation | Reconciling the amounts deducted and contributed in a payroll |
One request to start, change or end
Each endpoint is a single POST that does the right thing based on which dates you send:
| You send | What happens |
|---|---|
effectiveDate | The deduction is created, or updated if it already exists |
effectiveDate and effectiveEndDate | The same, with an end date |
Only effectiveEndDate | The existing deduction is ended |
| Neither | The request is rejected |
A deduction is identified by the worker and the pay code, so you don't store any Everee deduction ID. For other deductions you also supply an externalId, because a worker can have more than one deduction of the same type.
Changing a deduction
- If the worker has no deduction for that pay code, or their last one ended before your
effectiveDate, a new one is created. - If the existing deduction hasn't been used in a finalized payroll yet, it's updated in place.
- Otherwise the existing deduction is ended the day before your
effectiveDate, and a new one starts on it. This keeps past payrolls unchanged.
The start date can't be earlier than the worker's earliest editable date. If it is, it's moved forward to that date. The response always contains the dates that were actually used.
Ending a deduction
To end a deduction, send the workerId and payCode (and externalId) with only an effectiveEndDate. The deduction must exist and still be active or upcoming, otherwise you get a 404. A deduction that was never used in a finalized payroll is removed entirely, and its response still returns the start date and the end date you sent. One that was used is ended on the date you gave, or the earliest date that's still editable.
The response
Each response echoes workerId and payCode (and externalId), along with:
status:ACTIVE, orENDEDif the end date is today or earlier in the company's time zoneeffectiveDateandeffectiveEndDate: the dates that now apply
Amounts
Send exactly one of deductionAmount or deductionPercentage. Which one a pay code allows is listed below. Sending both, neither, or one the pay code doesn't allow returns a 422.
Fixed amounts (deductionAmount) are amounts per period. Send the amount with the periodType it applies to (WEEKLY, BI_WEEKLY, SEMI_MONTHLY or MONTHLY). For companies that deduct a monthly amount, Everee converts it to a monthly total: the amount times the number of periods in a year, divided by 12. Companies configured to deduct on every payment have the amount applied as sent, per payment. Use employerAmount for any employer contribution. It defaults to zero.
Percentages (deductionPercentage) are decimal fractions, not whole percentages: send 0.05 for 5%. Use employerPercentage for any employer contribution. An optional limit caps the dollar amount deducted per payment, per month or per pay period.
lifetimeLimit caps the total deducted from the worker over the life of the deduction. It's available on the benefit and other deduction endpoints.
Retirement employer match
The retirement endpoint doesn't take an employer amount or percentage. Describe the employer's match with employerMatchTiers instead: an ordered list of tiers, each with a matchRate and the share of wages (percentOfWages) it covers. Both are decimal fractions. For example, a 100% match on the first 3% of wages and a 50% match on the next 2% is:
"employerMatchTiers": [
{ "matchRate": 1.0, "percentOfWages": 0.03 },
{ "matchRate": 0.5, "percentOfWages": 0.02 }
]Match tiers aren't accepted for state retirement plan Roth 401(k) or PAYROLL_DEDUCTION_IRA pay codes.
HSA limit
For HSA deductions, hsaLimitType sets whether the contribution limit is INDIVIDUAL or FAMILY. If you leave it out, the worker's existing limit type is kept. Sending it with any other pay code is rejected.
Pay codes
The payCode says what kind of deduction this is. Use one of the values below, or the apiKey of a custom pay code your company has set up for one of these deduction types. Each endpoint only accepts its own types. Anything else returns a 404.
Benefit deductions
All benefit deductions use deductionAmount.
| Pre-tax | ACCIDENT_INSURANCE, CANCER_INSURANCE, COMMUTER_PLAN, CRITICAL_ILLNESS_INSURANCE, DENTAL_INSURANCE, DRA, FSA, GROUP_LIFE_INSURANCE, VOLUNTARY_LIFE_INSURANCE, HOSPITAL_INDEMNITY_INSURANCE, HRA, HSA, MEDICAL_INSURANCE, MEDICAL_INSURANCE_SECONDARY, MEDICARE_SUPPLEMENT_PLAN, PRESCRIPTION_PLAN, VISION_INSURANCE, LONG_TERM_DISABILITY_INSURANCE, SHORT_TERM_DISABILITY_INSURANCE |
| Post-tax | LONG_TERM_DISABILITY_INSURANCE_POST_TAX, SHORT_TERM_DISABILITY_INSURANCE_POST_TAX, MEDICAL_INSURANCE_POST_TAX, DENTAL_INSURANCE_POST_TAX, VISION_INSURANCE_POST_TAX, ACCIDENT_INSURANCE_POST_TAX, VOLUNTARY_LIFE_INSURANCE_POST_TAX, GROUP_LIFE_INSURANCE_POST_TAX, CRITICAL_ILLNESS_INSURANCE_POST_TAX, HOSPITAL_INDEMNITY_INSURANCE_POST_TAX |
Other deductions
payCode | Amount |
|---|---|
DUES | deductionAmount or deductionPercentage |
EMERGENCY_SAVINGS | deductionAmount or deductionPercentage |
LOAN_REPAYMENT | deductionAmount |
LOAN_REPAYMENT_401K | deductionAmount |
OTHER_POST_TAX_DEDUCTION | deductionAmount |
NEW_YORK_FAMILY_LEAVE_INSURANCE | deductionPercentage |
Retirement deductions
All of these accept deductionAmount or deductionPercentage.
ERISA_401K, ROTH_401K, ERISA_403B, TRADITIONAL_IRA, SIMPLE_IRA, SIMPLE_IRA_POST_TAX, PAYROLL_DEDUCTION_IRA, and state retirement plan Roth 401(k)s.
State retirement plan Roth 401(k)s are sent with a two-letter state prefix, like CA_STATE_RETIREMENT_PLAN_ROTH_401K. The prefix must be one of the participating states: CA, CO, CT, DE, IL, ME, MD, MN, NJ, NV, NY, OR, RI, VA or VT. The unprefixed STATE_RETIREMENT_PLAN_ROTH_401K is rejected.
Errors
| Status | Cause |
|---|---|
400 | effectiveEndDate is before effectiveDate |
404 | The payCode isn't valid for the endpoint, or you tried to end a deduction that doesn't exist or has already ended |
422 | Neither date was sent; the amount options are wrong for the payCode; hsaLimitType was sent for a pay code other than HSA; the state prefix is invalid; or a required field is missing |
Reconciling deductions
The apply endpoints say what should be deducted. Get deduction reconciliation returns what payroll did deduct from workers, and what the employer contributed, so you can report on it or remit it.
GET https://api.everee.com/integration/v1/deductions/reconciliation?pay-period-start-date=2026-10-05&pay-period-end-date=2026-10-11You retrieve a whole pay period at a time. The two dates must match a pay period exactly, as the start and end dates the pay period has in Everee. Dates that don't match a pay period return no rows, and a missing date, or an end date before the start date, returns a 400.
Retrieve a pay period once its payroll has finished processing, and page through it in one pass. Only payments that were paid, and have wages, are included, so it's a record of what happened, not a preview. Payments that were paid and later pulled back are included too: see Pulled-back payments.
Workers in the same pay period can have different pay dates, so each row carries its own payDate.
{
"workerId": "94cae9c4-a52c-4731-969f-83540f45c2e2",
"externalWorkerId": "emp-1042",
"payPeriodStartDate": "2026-10-05",
"payPeriodEndDate": "2026-10-11",
"payDate": "2026-10-16",
"payCode": "ERISA_401K",
"type": "ERISA_401K",
"category": "RETIREMENT",
"externalId": null,
"amountDeducted": { "amount": "120.00", "currency": "USD" },
"employerAmountContributed": { "amount": "60.00", "currency": "USD" },
"amountDeductedYearToDate": { "amount": "1200.00", "currency": "USD" },
"employerAmountContributedYearToDate": { "amount": "600.00", "currency": "USD" },
"totalTaxableWages": { "amount": "3000.00", "currency": "USD" },
"totalNonTaxablePay": { "amount": "50.00", "currency": "USD" },
"totalHoursWorked": "PT75H30M",
"remittedByEveree": false,
"paymentId": "28230311",
"status": "PAID"
}One row per payment and pay code
Each row totals the deductions of one pay code in one payment, which is one worker's payment for one pay period. paymentId is the same ID as in the Payment Data API, so you can tie a row back to its payment.
amountDeductedis withheld from the worker.employerAmountContributedis what the employer contributed.amountDeductedYearToDateandemployerAmountContributedYearToDateare the year-to-date totals for the pay code as of that payment, the same running totals shown on the worker's pay stub. When a row combines more than one deduction of the pay code, such as a deduction and a one-time reversal, it reports the highest of their year-to-date amounts.remittedByEvereeistrueif Everee funds and remits these amounts, so you know not to fund them a second time.categoryisBENEFIT,OTHERorRETIREMENT, as for the apply endpoints.
Wages and hours
Retirement plans usually need the worker's pay as well as the contribution, so each row also carries the wages and hours of the payment it comes from:
totalTaxableWagesis the payment's taxable wages, andtotalNonTaxablePayis its non-taxable pay, such as reimbursements. They mean the same as in the Payment Data API.totalHoursWorkedis the time worked in the payment, as an ISO 8601 duration likePT75H30M.
These describe the whole payment, not the pay code, so every row of a payment repeats the same values. Take them from any one of its rows. Don't add them up across a payment's rows.
Pay codes and types
payCode is the same value you send to the apply endpoints, so you can match rows to the deductions you set up:
- The
apiKeyof a custom pay code, if the deduction was set up under one. - For state retirement plan Roth 401(k)s, the state-prefixed value, like
CA_STATE_RETIREMENT_PLAN_ROTH_401K. - Otherwise the name of the built-in deduction type.
type is always the built-in type, so a row under a custom pay code still tells you what it is.
The endpoint also reports deduction types you can't set up through the apply endpoints, such as CAL_SAVERS. They're reported under their built-in type name, and put in the nearest category. Garnishments, Workers' Comp and Everee's own fees aren't included. Garnishments and Workers' Comp are in the Payment Data API.
Custom pay codes on other deductionsFor other deductions, the custom pay code you set up a deduction under isn't kept with it yet. These rows are reported under the built-in type instead of the custom pay code. The
externalIdyou sent is returned, so you can still match them.
Clients must tolerate new payCode and type values.
Pulled-back payments
A payment can be pulled back after it was paid. When it is, it stops being a paid payment, but it doesn't disappear from this endpoint: its rows stay, with status set to PULLED_BACK instead of PAID. Their amounts are what the payment applied before it was pulled back, so you can see what you may already have acted on. Payments that were deleted without being funded, such as ones left out of a payroll run, aren't included. This matches the Payroll Cost API, which also includes pulled-back payments.
If payroll is then run again for the same worker and pay period, the worker has two payments in it, the pulled-back one and the new one, each with its own rows. Count only the PAID rows for what stands, and use the PULLED_BACK rows to reverse anything you already funded or credited. Year-to-date amounts on a pulled-back payment aren't kept up to date after the pullback, so don't use them as current totals. The Payment Data API only lists payments that are currently paid, so the paymentId of a PULLED_BACK row isn't there. Clients must tolerate new status values.
Reversals
A deduction that was reversed shows up as a negative amountDeducted, in the pay period and pay date of the payment that carried the reversal, not the original deduction's, so a pay period request returns what was applied in that period's payments, not a restated net for the period. A row's amounts are the net of everything in it, and a row that nets to zero isn't returned. Add up rows to get what a worker has had deducted overall.
Filtering and paging
Use category or pay-code to narrow the rows, for example category=RETIREMENT for a retirement plan administrator. Paging works as it does in the Payment Data API: limit defaults to 200 and can be up to 1000, and you pass each response's nextCursor back as after until hasNextPage is false. Pass the cursor back exactly as you received it. There's no total count.
A missing or invalid pay period date, category, limit or after returns a 400.