Guide to the Deductions API

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.

EndpointUse it for
Apply benefit deductionBenefit plans: medical, dental, vision, HSA, FSA, life, disability and similar
Apply other deductionOther recurring deductions: dues, savings, loan repayments
Apply retirement deductionRetirement plans: 401(k), 403(b), IRAs
Get deduction reconciliationReconciling 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 sendWhat happens
effectiveDateThe deduction is created, or updated if it already exists
effectiveDate and effectiveEndDateThe same, with an end date
Only effectiveEndDateThe existing deduction is ended
NeitherThe 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, or ENDED if the end date is today or earlier in the company's time zone
  • effectiveDate and effectiveEndDate: 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-taxACCIDENT_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-taxLONG_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

payCodeAmount
DUESdeductionAmount or deductionPercentage
EMERGENCY_SAVINGSdeductionAmount or deductionPercentage
LOAN_REPAYMENTdeductionAmount
LOAN_REPAYMENT_401KdeductionAmount
OTHER_POST_TAX_DEDUCTIONdeductionAmount
NEW_YORK_FAMILY_LEAVE_INSURANCEdeductionPercentage

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

StatusCause
400effectiveEndDate is before effectiveDate
404The payCode isn't valid for the endpoint, or you tried to end a deduction that doesn't exist or has already ended
422Neither 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-11

You 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.

  • amountDeducted is withheld from the worker. employerAmountContributed is what the employer contributed.
  • amountDeductedYearToDate and employerAmountContributedYearToDate are 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.
  • remittedByEveree is true if Everee funds and remits these amounts, so you know not to fund them a second time.
  • category is BENEFIT, OTHER or RETIREMENT, 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:

  • totalTaxableWages is the payment's taxable wages, and totalNonTaxablePay is its non-taxable pay, such as reimbursements. They mean the same as in the Payment Data API.
  • totalHoursWorked is the time worked in the payment, as an ISO 8601 duration like PT75H30M.

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 apiKey of 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 deductions

For 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 externalId you 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.