Enrollment Lifecycle
How enrollments move through statuses and which webhook events fire at each transition.
An enrollment represents an employee’s participation in a benefit plan. Each enrollment moves through a defined set of statuses as the employee selects, confirms, or declines coverage. Vitable fires webhook events at every transition, giving your system a real-time view of where each enrollment stands.
Enrollment statuses apply across all benefit categories: Medical, Dental, Vision, and Hospital.
Quick Reference
Section titled “Quick Reference”This table maps every enrollment status transition to the webhook event that triggers it.
| Current Status | Event Fired | New Status | What Happened |
|---|---|---|---|
| (none) | enrollment.started | pending | An enrollment window opened for the employee |
pending | enrollment.granted | pending | The system or an admin created the enrollment opportunity — the employee still needs to make an election |
pending | enrollment.elected + enrollment.accepted | enrolled | The employee selected a plan and confirmed — both events fire together from the same action |
pending | enrollment.waived | waived | The employee declined the benefit |
enrolled | enrollment.terminated | inactive | Coverage has ended |
Mapping Statuses
Section titled “Mapping Statuses”| Status | Meaning | Events | Transitions To |
|---|---|---|---|
pending | Enrollment window opened, employee has not acted | enrollment.started, enrollment.granted | enrolled, waived |
enrolled | Employee selected a plan and confirmed | enrollment.elected + enrollment.accepted (both fire together) | inactive |
waived | Employee declined the benefit | enrollment.waived | — |
inactive | Coverage has ended | enrollment.terminated | — |
The high-level flow is:
pending -> enrolled (elected + accepted fire together)pending -> waivedenrolled -> inactive (via terminated)Understanding the Events
Section titled “Understanding the Events”Vitable fires six enrollment webhook events. Each event follows the standard webhook payload format with event_id, event_name, resource_type, resource_id, and created_at fields. After receiving any enrollment event, fetch the current state by calling GET /v1/enrollments/{id} with the resource_id from the payload.
Starting an Enrollment
Section titled “Starting an Enrollment”When an employee becomes eligible for benefits and an enrollment window opens, Vitable fires enrollment.started. The enrollment is created with a status of pending. This event fires during both open enrollment periods and qualifying life event (QLE) windows.
At this point, the employee can view available plans and make a selection.
Granting an Enrollment Opportunity
Section titled “Granting an Enrollment Opportunity”The enrollment.granted event fires when the system or an admin creates an enrollment opportunity for the employee. The enrollment remains in pending status — the employee still needs to make an election. This is distinct from enrollment.started, which signals the enrollment window opened.
Electing and Confirming Coverage
Section titled “Electing and Confirming Coverage”When the employee selects a plan, signs, and confirms in the enrollment widget, Vitable fires both enrollment.elected and enrollment.accepted together. The enrollment moves from pending to enrolled in a single step — there is no intermediate state between selecting a plan and confirming coverage. Once enrolled, the employee has active coverage and the enrollment’s coverage_start field reflects when coverage began.
Waiving Coverage
Section titled “Waiving Coverage”If the employee declines a benefit, Vitable fires enrollment.waived and the enrollment moves to the waived status. The answered_at field on the enrollment records when the employee made this decision.
Terminating Coverage
Section titled “Terminating Coverage”When active coverage ends, Vitable fires enrollment.terminated and the enrollment transitions to inactive. The enrollment’s terminated_at and coverage_end fields reflect when coverage was terminated and when it officially ends.
Coverage can end for several reasons: the employee leaves the company, the employer terminates the plan, or an administrative change removes the employee’s eligibility. Regardless of the cause, the resulting status is always inactive.
Enrolling Through Open Enrollment
Section titled “Enrolling Through Open Enrollment”During an open enrollment period, all eligible employees receive enrollment windows for each available benefit category. The typical flow looks like this:
sequenceDiagram
participant V as Vitable API
participant P as Partner
V--)P: enrollment.started (status: pending)
Note over P: Employee views plans
V--)P: enrollment.elected + enrollment.accepted (status: enrolled)
Note over V: Deductions generated on monthly schedule
Diagram summary:
- Vitable fires
enrollment.startedwhen the enrollment window opens. The enrollment ispending. - The employee selects a plan. Vitable fires both
enrollment.electedandenrollment.acceptedtogether. The enrollment moves toenrolled. - Payroll deductions are generated later on a monthly schedule —
employee.deduction_createdfires on the 1st of each month, not immediately after enrollment.
An employee may also choose to waive coverage, in which case step 2 would be replaced by an enrollment.waived event and the enrollment would move to waived.
Enrolling Through a Qualifying Life Event
Section titled “Enrolling Through a Qualifying Life Event”A qualifying life event (QLE) — such as marriage, the birth of a child, or loss of other coverage — opens a special enrollment window outside the regular open enrollment period. The webhook event flow is the same:
sequenceDiagram
participant V as Vitable API
participant P as Partner
Note over V,P: Qualifying life event occurs
V--)P: enrollment.started (status: pending)
V--)P: enrollment.elected + enrollment.accepted (status: enrolled)
Note over V: Deductions generated on monthly schedule
Diagram summary:
- A qualifying life event triggers a new enrollment window. Vitable fires
enrollment.started. - The employee selects a plan. Vitable fires both
enrollment.electedandenrollment.acceptedtogether. The enrollment moves toenrolled. - Payroll deductions are generated later on a monthly schedule — not immediately after enrollment.
The QLE flow produces the same sequence of events as open enrollment. The difference is the trigger — a qualifying life event rather than a scheduled enrollment period.
Terminating an Enrollment
Section titled “Terminating an Enrollment”When an enrolled employee’s coverage ends, the enrollment transitions from enrolled to inactive:
| From | To | Event | Notes |
|---|---|---|---|
enrolled | inactive | enrollment.terminated | There is no terminated status — the enrollment moves to inactive |
- The enrollment’s status field reads
inactive, notterminated.
Troubleshooting
Section titled “Troubleshooting”Receiving events out of order. Webhook events are delivered at least once and may arrive out of order. Always fetch the current enrollment state with GET /v1/enrollments/{id} after receiving an event rather than relying on event order to track status. If you receive enrollment.accepted before enrollment.elected, the enrollment’s status field from the API reflects the true current state.
Duplicate events. Your endpoint may receive the same event more than once. Use the event_id field for idempotency — if you have already processed an event, skip it.
Missing events. If your endpoint was unreachable, use GET /v1/webhook-events to query for events you may have missed. You can filter by resource_type and time range to find enrollment events. For delivery details on a specific event, call GET /v1/webhook-events/{event_id}/deliveries.
Enrollment stuck in pending. An enrollment remains pending until the employee makes a selection and it is processed, or the enrollment window closes. If an enrollment has been pending longer than expected, the employee may not have completed their enrollment yet.
Related Webhooks
Section titled “Related Webhooks”| Event | Description |
|---|---|
enrollment.started | An enrollment window has opened for an employee. Learn more |
enrollment.elected | An employee has selected a benefit plan. Learn more |
enrollment.accepted | An enrollment has been confirmed and coverage is active. Learn more |
enrollment.granted | An enrollment has been granted through auto-enrollment or admin action. Learn more |
enrollment.waived | An employee has declined a benefit. Learn more |
enrollment.terminated | Coverage has ended and the enrollment is now inactive. Learn more |
employee.deduction_created | Payroll deductions generated on monthly schedule for employees with active enrollments. Learn more |
Related API Endpoints
Section titled “Related API Endpoints”GET /v1/employees/{id}/enrollments— List all enrollments for an employeeGET /v1/enrollments/{id}— Retrieve a single enrollment by IDGET /v1/webhook-events— Query webhook events to recover missed deliveriesGET /v1/webhook-events/{event_id}/deliveries— Inspect delivery attempts for a specific event