docs
/
AI skills

Benefits enrollment

Set up benefit plans in Business Made › HR › Benefits, each with its coverage levels and costs and who can join. Enroll people and start their coverage, which takes their share from pay through a Payroll deduction. Add dependents and beneficiaries, waive cover, end it or remove an enrollment. Includes what is and isn't checked or deducted.

Benefits live in the Business Made app, on HR › Benefits (/hr/benefits). The screen has two tabs: Plans and Enrollments. All of it uses business-made/benefits/… (appengine business-made/services/benefits.service.ts, controller benefits.controller.ts). Call those routes with call_appengine.

Business Made records the plans and who is covered. It never talks to the insurer or the 401(k) provider, so enrolling someone here doesn't sign them up with the carrier. Nothing in benefits sends an email. Starting coverage only takes the employee's share from pay, through Payroll.

The Business Made docs cover the same screen for people: Benefits, compensation, performance and learning. Payroll deductions are explained in People, periods and schedules. For the API, see the Business Made module reference.

Ask first

  • The plan: its name, the kind of plan, the provider (name, plan number, group number), and the plan year.
  • Coverage levels and cost: which levels are offered (employee only, employee + spouse, employee + children, family). For each level, ask what the employee pays and what the employer pays, and whether that is per pay, per month or per year. Never guess a premium.
  • Who can join: full-time, part-time or contract staff. Only this is checked (see What it can't do yet).
  • For each enrollment: the person, the plan, the coverage level, and when cover starts. Is this a new hire, open enrollment, a life event or a reinstatement?
  • Dependents and beneficiaries: their names, relationship and date of birth. For a beneficiary, ask the percentage and whether they are primary or contingent.

Steps

1. HR › Benefits: the plan

POST business-made/benefits/plans takes the plan's fields at the top level. On screen, click New plan.

FieldOn screenValues
titleNameRequired (PLAN_TITLE_REQUIRED).
typeKind of planRequired (PLAN_TYPE_REQUIRED): health, dental, vision, life, disability-short-term, disability-long-term, retirement-401k, hsa, fsa, commuter, wellness, employee-assistance, tuition-reimbursement, other.
category(automatic)Set from the type: medical, insurance, retirement, financial or lifestyle.
providerProvider{ name, planId, groupNumber, contactPhone, contactEmail, website }.
coverage.tiers[]Coverage levels and cost{ tier, employeeCost, employerCost, frequency }. See the notes after this table.
eligibilityWho can join{ employmentTypes: ["full-time","part-time","contract"], waitingPeriodDays, minHoursPerWeek }.
planYear, startDate, endDate, descriptionPlan year, Dates, What it coversOptional. endDate must not come before startDate (PLAN_DATES_INVALID).

Notes on coverage.tiers[]:

  • tier is one of employee-only, employee-spouse, employee-children, family.
  • frequency is per-pay-period, monthly (the default) or annually.
  • Each tier can appear only once (PLAN_TIER_DUPLICATE), and costs can't be negative.

A new plan is always a draft. To edit one, call POST business-made/benefits/plans/update with { sk, data: { … } }. What you send is merged into the plan, and the whole plan is checked again.

Hands on: the plan's sk. Check: the plan shows under Benefit plans as Draft, with its Coverage levels and cost.

2. HR › Benefits: switch the plan on

POST business-made/benefits/plans/<sk>/activate. On screen, click Activate.

A plan with no coverage level can't be switched on (PLAN_TIERS_REQUIRED, tested). People can only be enrolled in an active plan (PLAN_NOT_ACTIVE).

Deactivate (…/deactivate) stops new enrollments. People already enrolled stay covered, and their deductions go on.

DELETE business-made/benefits/plans/<sk> works only while nobody has enrolled. Otherwise it gives PLAN_IN_USE, and you should deactivate the plan instead.

Set enrollment window (POST …/plans/<sk>/open-enrollment with { startDate, endDate }) saves the open-enrollment dates on the plan. Nothing checks them (see below).

Hands on: the plan, active. Check: the plan reads Active and appears under The plans you can enroll in.

3. HR › Benefits: make sure Payroll can take the share

Before you start anyone's coverage, check that there is a deduction type for the plan. Use GET business-made/payroll/deduction-types. Starting coverage looks for an active deduction type in the plan's category:

Plan typeDeduction category it needsSeeded type
health, dental, visionhealth, dental, visionHealth Premium, Dental Premium, Vision Premium
hsahsaHSA
retirement-401kretirement401(k): a percentage of pay, 5% by default
fsafsanone
any other typebenefitnone

POST business-made/payroll/deduction-types/seed adds the seeded set. You can also add a type on Payroll › Deduction types (/payroll/setup/deductions).

If no type matches, coverage still starts, but nothing is taken from pay. The enrollment reads "Not taken from pay — no benefit deduction set up in Payroll" (tested on a life plan).

  • Monthly and yearly shares are taken every pay. A $100-a-month share on a bi-weekly schedule took $100 from each pay, which is about $216 a month (tested on two previews). The deduction is saved with frequency: monthly, but the payroll engine reads only its amount. Until that is fixed, tell the person. If the share is per pay, set the level's frequency to per-pay-period.
  • A 401(k) plan takes the deduction type's percentage, not the plan's dollar share. With the seeded 401(k) type, that is 5% of pay (read from code). Confirm the person's contribution rate on the deduction in Payroll › People & pay.

Hands on: the deduction type that will be used, or "none". Check: the type is listed on Payroll › Deduction types, and it is active.

4. HR › Benefits: enroll the person

POST business-made/benefits/enrollments with:

{ "employeeId": "<bm_employee sk or EMP-… code>",
  "benefitPlanId": "<plan sk>",
  "coverageTier": "employee-only",
  "coverageStartDate": "2026-11-01",
  "enrollmentType": "new-hire" }

enrollmentType is new-hire (the default), open-enrollment, qualifying-life-event or reinstatement. On screen, click Enroll someone, then Enroll, or Enroll and start coverage to do steps 4 and 5 together.

The enrollment is always created pending. It copies the level's costs: employeeContribution, employerContribution, totalCost and contributionFrequency.

The enrollment is refused in these cases (all tested except NOT_ELIGIBLE and EMPLOYEE_INACTIVE):

CodeCause
TIER_NOT_OFFEREDThe plan has no such level.
ALREADY_ENROLLEDThe person already has a pending or active enrollment in this plan.
NOT_ELIGIBLETheir employment type isn't on the plan.
EMPLOYEE_INACTIVEThe person no longer works here.

Search the person's enrollments first: GET business-made/benefits/enrollments/employee/<employeeId>.

Hands on: the enrollment's sk. Check: the Enrollments tab lists them as Pending.

5. HR › Benefits: start coverage

POST business-made/benefits/enrollments/<sk>/activate. On screen, click Start coverage. This works on a pending enrollment only (NOT_PENDING).

It sets the enrollment to active, and sets the start date to today if none was given. If the person has an employee share, it creates a bm_employee_deduction for that amount, which is taken from every pay from the start date (see the warning in step 3). The result is on payrollDeduction, as one of these:

  • active, with the deduction, for example "$100.00 monthly taken from pay as Health Premium";
  • not-linked;
  • none (no employee share).

Stop if the person didn't ask for coverage to start. Starting it changes their next paycheck. Show the plan, the level, the start date and the amount taken, and wait for a yes.

Hands on: the payrollDeduction state. Check: the enrollment reads Active, or Waiting to start · when cover starts later. Its Payroll line shows what is taken from pay.

6. HR › Benefits: dependents and beneficiaries

AddRouteNeeds
DependentPOST business-made/benefits/enrollments/<sk>/dependentsfirstName, lastName, relationship (spouse, domestic-partner, child, other), dateOfBirth YYYY-MM-DD (DEPENDENT_DOB_REQUIRED, tested)
BeneficiaryPOST business-made/benefits/enrollments/<sk>/beneficiariesfirstName, lastName, relationship, percentage 1–100, type primary or contingent. The primaries can't add up to more than 100%, and neither can the contingents (BENEFICIARY_OVER_100, tested).

On screen, use Add dependent and Add beneficiary. Remove one with DELETE …/dependents/<id> or …/beneficiaries/<id>.

A dependent can be added to an employee-only level (tested). Check that the level covers them. If it doesn't, the person needs a different level: end this enrollment and enroll them at the right level.

Hands on: the dependents and beneficiaries saved. Check: the enrollment's Dependents and Beneficiaries lists show them.

7. HR › Benefits: waive, end or remove

NeedRouteWorks on
The person declines coverPOST …/enrollments/<sk>/waive with { reason }. On screen: Waive → Waive cover.pending
Coverage stops (they left, or changed plan)POST …/enrollments/<sk>/terminate with { reason }. On screen: End coverage, or Cancel coverage before it has started.active (NOT_ACTIVE otherwise)
Take back an enrollment made by mistakeDELETE business-made/benefits/enrollments/<sk>. On screen: Remove.pending, waived or declined. Other statuses give KEEP_HISTORY (tested).

Ending coverage sets the end date to today and cancels the payroll deduction (tested). If cover hadn't started yet, the end date is the start date, and the enrollment reads "Cancelled before anything was taken from pay" (tested).

Stop before ending someone's coverage. Show who, which plan and the end date, and wait for a yes. Tell the person to let the insurer know, because Business Made doesn't.

Hands on: the enrollment's new status. Check: the enrollment reads Ended or Waived, and its Payroll line no longer shows a deduction.

When it's done

Tell the person what was saved:

  • each plan, with its levels and costs;
  • who is enrolled, at which level and from when;
  • what will come out of each person's pay, and the frequency warning from step 3.

Open /hr/benefits.

GET business-made/benefits/metrics and the screen's tiles (Active plans, People covered, Employer cost) answer "how many are covered" and "what do benefits cost us". GET business-made/benefits/view/enrollments?… lists the enrollments with their labels.

What it can't do yet

  • The deduction frequency is ignored. Monthly and yearly shares are taken every pay (step 3).
  • A 401(k) enrollment's dollar share isn't used. The deduction type's percentage is.
  • The enrollment window is information only. Enrollments are accepted outside it.
  • waitingPeriodDays, minHoursPerWeek, eligibleDepartments and eligibleLocations aren't checked. Only employmentTypes is.
  • The coverage level doesn't limit dependents. You can add any dependent to any level.
  • No carrier connection. Nothing is sent to an insurer or 401(k) provider.
  • No self-enrollment. People can't enroll or waive from their staff portal; HR does it for them.
  • No benefit emails. Nothing tells the person when coverage starts or ends.
  • Changing a level's cost doesn't change existing enrollments. The costs were copied onto each enrollment when it was made.

Don'ts

  • Don't start or end coverage without a yes. It changes the person's pay.
  • Don't guess premiums, employer shares or contribution rates.
  • Don't tell the person a monthly share will be taken once a month. It won't be, until the frequency bug is fixed.
  • Don't delete a plan or an enrollment that people have used. Deactivate the plan or end the coverage, so the history stays.
  • Don't say the person is enrolled with the insurer. Business Made only records it.