How to Detect Employee Onboarding and Offboarding Events with
·
To detect new hires and leavers across HR systems with Unified.to's HR & Directory API, compare each employee's employment_status, hired_at and terminated_at between reads, and use employee webhooks where the integration sends them. This guide is for teams automating onboarding, offboarding and access changes. 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 report 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.to's HR & Directory API doesn't invent lifecycle events. It returns observable employee state (employment status, start and end dates, groups and locations) and, where the integration supplies it, an updated_at timestamp. Lifecycle events are derived by comparing state over time, using consistent semantics across HR systems.
This guide shows how to detect joiners, leavers and other employee changes with Unified.to's HR & Directory API, without vendor-specific logic or inferred history.
What does lifecycle detection cover here?
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 current 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.to provides the lifecycle signal. Your product decides how to act on it.
Does Unified.to send onboarding and offboarding events?
Not as such. There's no "lifecycle event" object; on supported integrations, employee created, updated and deleted webhooks tell you a record changed, and the lifecycle meaning comes from the employee's 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 steps 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 steps 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 steps
Step 4: Detect updates to active employees
Not all lifecycle-relevant changes are joiners or leavers.
Examples:
- Department changes
- Location changes
- Company reassignment
Where the integration returns updated_at, you can detect records that need re-evaluation; elsewhere, compare the fields you care about.
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: Re-read only changed employees where you can
Where an integration supports the updated_gte filter, such as SAP SuccessFactors, Personio, Okta and Microsoft Entra ID, you can re-read only changed employees. Elsewhere, list all employees and compare.
Typical pattern:
- Persist last processed
updated_at - Re-fetch employees with
updated_gte - Compare state against stored snapshot
- Derive joiners, leavers, and updates
Can webhooks replace polling?
On supported integrations, yes, for detection: employee events are native on HiBob, Personio, FactorialHR, Remote.com, Google Workspace Directory and Microsoft Entra ID (including deletes), and come from virtual webhooks on BambooHR, Workday, SAP SuccessFactors, UKG Pro HCM and Okta, which check at an interval you set, as often as every minute on paid plans (as of 20 October 2026). ADP Workforce Now and Deel send no employee events.
However:
- Webhooks are an optimisation, 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.
Can I provision accounts from the same data?
Yes. Use the lifecycle signal to create or remove accounts in your own product, or write to a directory: Okta, Microsoft Entra ID, Google Workspace Directory and JumpCloud create, update and remove employees through the same API, and Unified.to's SCIM API offers SCIM Users and Groups over its HR integrations. Device records (asset tag, model, operating system, assigned users) are readable on integrations such as Microsoft Entra ID and Google Workspace Directory (as of 19 October 2026).
To keep a current copy of employees in your own database, Database Sync (Grow, Pro and Scale) writes changes into MongoDB, MySQL, Postgres, MSSQL, MariaDB, Supabase or Snowflake for objects with native or virtual webhooks.
What doesn't Unified.to assume?
Unified.to 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 returns observable state changes and leaves lifecycle interpretation to your product.
How do I start?
Employee lifecycle syncing is about state awareness, not event orchestration.
Unified.to's HR & Directory API reads employee state from the source at request time (start dates, termination dates, groups, locations and change timestamps where supplied) across 679 HR & Directory integrations, so onboarding and offboarding steps follow the HR system.
With explicit state and incremental detection, lifecycle automation becomes reliable instead of reactive.