Unified.to
All articles

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 = ACTIVE and a hired_at date
  • Offboarding → employment_status transitions or terminated_at is 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:

  • id
  • employment_status
  • hired_at
  • terminated_at
  • updated_at
  • groups[]
  • locations[]
  • company_id

Important constraints:

  • Lifecycle signals are represented as state, not events
  • updated_at reflects changes to the employee record
  • Not all HRISs update all fields simultaneously

Groups (HrisGroup)

Groups provide organizational context.

Relevant fields:

  • id
  • name
  • parent_id
  • type
  • company_id

Groups are useful for assigning onboarding or offboarding workflows by department or team.

Locations (HrisLocation)

Locations provide geographic context.

Relevant fields:

  • id
  • name
  • address.region
  • address.country
  • company_id

Locations are often used to trigger jurisdiction-specific onboarding or exit steps.

Companies (HrisCompany)

Companies define scope.

Relevant fields:

  • id
  • name

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_status of ACTIVE
  • A populated hired_at date
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_status transitions to INACTIVE
  • terminated_at becomes 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:

  1. Persist last processed updated_at
  2. Re-fetch employees with updated_gte
  3. Compare state against stored snapshot
  4. 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_at remains 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.

Start your 30-day free trial

Book a demo

All articles