How to Sync Employee Lifecycle Events (Onboarding & Offboarding) with Unified's HR & Directory API
February 2, 2026
Employee lifecycle automation breaks when products treat onboarding and offboarding as one-time events instead of state transitions.
Across HR systems, employee lifecycle data is fragmented. Start dates, termination dates, employment status, and organizational attributes are updated independently and often asynchronously. Some systems emit explicit events. Others only expose current state. Many require teams to reconstruct lifecycle changes by comparing snapshots or relying on vendor-specific semantics.
For product teams, this creates real operational risk:
- New hires aren't provisioned on time
- Departed employees retain access longer than intended
- Role or team changes fail to trigger downstream updates
- 'Joiners' and 'leavers' are detected inconsistently across HRISs
Many tools attempt to solve this by inventing lifecycle event objects or relying on undocumented vendor behavior. That approach is brittle and hard to audit.
Unified's HR & Directory API takes a more explicit stance. It does not invent lifecycle events. Instead, it exposes observable employee state—employment status, start and end dates, organizational attributes—and a reliable updated_at signal. Lifecycle events are derived by comparing state over time, using consistent semantics across HR systems.
This guide shows how to sync onboarding and offboarding flows using Unified's HR & Directory API—detecting joiners, leavers, and meaningful employee changes without vendor-specific logic or inferred history.
What lifecycle syncing means in this article
This article focuses on detecting and reacting to employee lifecycle changes, not performing provisioning directly.
We will:
- Identify new employees (onboarding)
- Identify exited employees (offboarding)
- Detect changes to active employees that require updates
- Keep downstream systems in sync incrementally
We will not:
- Model role history or promotions
- Infer lifecycle events from payroll or benefits
- Require webhooks to function correctly
- Define provisioning logic for downstream systems
Unified provides the lifecycle signal. Your product decides how to act on it.
The mental model: lifecycle events are derived, not emitted
Unified does not expose a dedicated 'lifecycle event' object.
Instead, lifecycle events are derived from changes in employee state:
- Onboarding → employee appears with
employment_status = ACTIVEand ahired_atdate - Offboarding →
employment_statustransitions orterminated_atis set - Updates → any meaningful change reflected in
updated_at
This model is intentional. It avoids vendor-specific event semantics and keeps lifecycle detection consistent across HRISs.
Objects you'll use
Employees (HrisEmployee)
Employees are the source of truth for lifecycle state.
Relevant fields:
idemployment_statushired_atterminated_atupdated_atgroups[]locations[]company_id
Important constraints:
- Lifecycle signals are represented as state, not events
updated_atreflects changes to the employee record- Not all HRISs update all fields simultaneously
Groups (HrisGroup)
Groups provide organizational context.
Relevant fields:
idnameparent_idtypecompany_id
Groups are useful for assigning onboarding or offboarding workflows by department or team.
Locations (HrisLocation)
Locations provide geographic context.
Relevant fields:
idnameaddress.regionaddress.countrycompany_id
Locations are often used to trigger jurisdiction-specific onboarding or exit steps.
Companies (HrisCompany)
Companies define scope.
Relevant fields:
idname
This allows lifecycle syncing in multi-entity organizations without assuming a single global org.
Step 1: Perform an initial employee ingest
Start by ingesting the current employee population.
import { UnifiedTo } from '@unified-api/typescript-sdk';
const sdk = new UnifiedTo({
security: { jwt: process.env.UNIFIED_API_KEY! },
});
async function fetchEmployees(connectionId: string) {
const employees = [];
let offset = 0;
const limit = 100;
while (true) {
const page = await sdk.hris.listHrisEmployees({
connectionId,
limit,
offset,
sort: 'updated_at',
order: 'asc',
fields: [
'id',
'employment_status',
'hired_at',
'terminated_at',
'updated_at',
'groups',
'locations',
'company_id',
].join(','),
});
if (!page || page.length === 0) break;
employees.push(...page);
offset += limit;
}
return employees;
}
This establishes a baseline state.
Step 2: Detect onboarding (joiners)
A new employee is typically identified by:
- A previously unseen
id - An
employment_statusofACTIVE - A populated
hired_atdate
function detectJoiners(
previous: Map<string, any>,
current: any[]
) {
return current.filter(
(e) =>
!previous.has(e.id) &&
e.employment_status === 'ACTIVE'
);
}
These employees can trigger onboarding workflows such as:
- Account creation
- Training assignment
- Welcome communications
Step 3: Detect offboarding (leavers)
Offboarding is detected through state change.
Common signals:
employment_statustransitions toINACTIVEterminated_atbecomes populated
function detectLeavers(
previous: Map<string, any>,
current: any[]
) {
return current.filter((e) => {
const prev = previous.get(e.id);
if (!prev) return false;
return (
prev.employment_status === 'ACTIVE' &&
e.employment_status !== 'ACTIVE'
);
});
}
These records can drive:
- Access revocation
- Device or account cleanup
- Exit workflows
Step 4: Detect updates to active employees
Not all lifecycle-relevant changes are joiners or leavers.
Examples:
- Department changes
- Location changes
- Company reassignment
Because Unified exposes updated_at, you can detect records that require re-evaluation.
function detectUpdates(
previous: Map<string, any>,
current: any[]
) {
return current.filter((e) => {
const prev = previous.get(e.id);
if (!prev) return false;
return e.updated_at !== prev.updated_at;
});
}
These updates often require partial downstream changes rather than full onboarding or offboarding.
Step 5: Sync incrementally using updated_at
Unified supports incremental lifecycle syncing without full resyncs.
Typical pattern:
- Persist last processed
updated_at - Re-fetch employees with
updated_gte - Compare state against stored snapshot
- Derive joiners, leavers, and updates
This works consistently across HRISs and does not rely on vendor-specific events.
Webhooks (optional)
If your integration supports webhooks, lifecycle syncing can become near-real-time.
However:
- Webhooks are an optimization, not a requirement
- Polling with
updated_atremains the baseline approach - Lifecycle logic should not depend on webhook guarantees
This ensures correctness even when webhooks are unavailable or delayed.
What Unified does not assume
Unified does not:
- Emit explicit onboarding or offboarding events
- Infer lifecycle changes from payroll or benefits
- Model role or title history
- Guarantee synchronous field updates across HRISs
It exposes observable state changes and leaves lifecycle interpretation to your product.
Closing thoughts
Employee lifecycle syncing is about state awareness, not event orchestration.
Unified's HR & Directory API gives you a consistent, real-time view of employee state—start dates, termination signals, organizational context, and change timestamps—so onboarding and offboarding workflows stay accurate as organizations evolve.
With explicit state and incremental detection, lifecycle automation becomes reliable instead of reactive.