Skip to main content 首页 创作者 comeonoliver skillshub bamboohr-reference-architecture
bamboohr-reference-architecture Implement BambooHR reference architecture for production HR data pipelines.
Use when designing new BambooHR integrations, building employee sync systems,
or establishing architecture standards for BambooHR-powered applications.
Trigger with phrases like "bamboohr architecture", "bamboohr design",
"bamboohr project structure", "bamboohr system design", "bamboohr pipeline".
跳到安装 Skills Marketplace 发现并探索由社区构建的 Agent Skills
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/ComeOnOliver/skillshub --skill bamboohr-reference-architecture命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
下载 Zip 下载中... 同仓库更多 Skills Review product and feature risk before an AI coding agent starts implementation.
Use Xquik for X data and confirmation-gated X actions: tweet search, user lookup, follower export, media download, monitors, webhooks, MCP, and SDK workflows.
Canton Network open-source ecosystem guide covering DAML SDK, Canton runtime, and Splice applications. Use when working with Canton Network, DAML smart contracts, or building decentralized applications.
name bamboohr-reference-architecture description Implement BambooHR reference architecture for production HR data pipelines.
Use when designing new BambooHR integrations, building employee sync systems,
or establishing architecture standards for BambooHR-powered applications.
Trigger with phrases like "bamboohr architecture", "bamboohr design",
"bamboohr project structure", "bamboohr system design", "bamboohr pipeline".
allowed-tools Read, Grep version 1.0.0 license MIT author Jeremy Longshore <jeremy@intentsolutions.io> tags ["saas","hr","bamboohr","architecture"] compatible-with claude-code
BambooHR Reference Architecture
Overview
Production-ready architecture for BambooHR integrations covering the three most common patterns: real-time employee sync, HR data pipeline, and employee lifecycle automation.
Prerequisites
Understanding of layered architecture and event-driven design
BambooHR API knowledge from earlier skills in this pack
TypeScript project setup with Node.js 18+
Instructions
Architecture Overview
┌──────────────────────────────────────────────────────────┐
│ Your Application │
├──────────────┬───────────────┬────────────────────────────┤
│ API Layer │ Sync Engine │ Webhook Handler │
│ /api/* │ (Cron/Queue) │ /webhooks/bamboohr │
├──────────────┴───────────────┴────────────────────────────┤
│ Service Layer │
│ EmployeeService │ TimeOffService │ ReportService │
├───────────────────┴──────────────────┴────────────────────┤
│ BambooHR Client Layer │
│ BambooHRClient │ Cache │ RetryHandler │ Metrics │
├───────────────────┴─────────┴────────────────┴────────────┤
│ Data Layer │
│ PostgreSQL (employees) │ Redis (cache) │ S3 (files) │
└───────────────────────────────────────────────────────────┘
│
▼
┌────────────────────────┐
│ BambooHR REST API │
│ api.bamboohr.com/api/ │
│ gateway.php/{co}/v1 │
└────────────────────────┘
Project Structure
bamboohr-integration/
├── src/
│ ├── bamboohr/
│ │ ├── client.ts # HTTP client (from sdk-patterns)
│ │ ├── types.ts # BambooHR API response types
│ │ ├── retry.ts # Retry with Retry-After support
│ │ ├── cache.ts # LRU + Redis cache layer
│ │ └── metrics.ts # Request counting and latency
│ ├── services/
│ │ ├── employee-sync.ts # Incremental directory sync
│ │ ├── time-off.ts # PTO balance and request management
│ │ ├── reports.ts # Custom report generation
│ │ └── lifecycle.ts # Onboarding/offboarding automation
│ ├── handlers/
│ │ ├── webhook.ts # Webhook signature verification + routing
│ │ └── events.ts # Employee change event processors
│ ├── api/
│ │ ├── health.ts # Health check endpoint
│ │ ├── employees.ts # REST API for local employee data
│ │ └── reports.ts # Report generation endpoints
│ ├── jobs/
│ │ ├── full-sync.ts # Scheduled full directory sync
│ │ ├── incremental-sync.ts # Frequent delta sync
│ │ └── report-export.ts # Scheduled report export
│ └── db/
│ ├── schema.sql # PostgreSQL schema
│ └── queries.ts # Database queries
├── tests/
│ ├── unit/
│ │ ├── client.test.ts
│ │ ├── employee-sync.test.ts
│ │ └── webhook.test.ts
│ ├── integration/
│ │ └── bamboohr-live.test.ts
│ └── mocks/
│ └── bamboohr-handlers.ts # MSW handlers
├── config/
│ ├── default.json
│ ├── production.json
│ └── test.json
└── docker-compose.yml # PostgreSQL + Redis for local dev
Step 1: Data Model
CREATE TABLE bamboohr_employees (
id INTEGER PRIMARY KEY ,
first_name TEXT NOT NULL ,
last_name TEXT NOT NULL ,
display_name TEXT,
work_email TEXT,
job_title TEXT,
department TEXT,
division TEXT,
location TEXT,
supervisor_id INTEGER REFERENCES bamboohr_employees(id),
status TEXT DEFAULT 'Active' ,
hire_date DATE ,
termination_date DATE ,
employee_number TEXT,
raw_data JSONB,
synced_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX idx_employees_status ON bamboohr_employees(status);
CREATE INDEX idx_employees_department ON bamboohr_employees(department);
CREATE INDEX idx_employees_synced ON bamboohr_employees(synced_at);
CREATE TABLE bamboohr_sync_log (
id SERIAL PRIMARY KEY ,
sync_type TEXT NOT NULL ,
started_at TIMESTAMPTZ NOT NULL ,
completed_at TIMESTAMPTZ,
employees_created INTEGER DEFAULT 0 ,
employees_updated INTEGER DEFAULT 0 ,
employees_deleted INTEGER DEFAULT 0 ,
errors JSONB DEFAULT '[]' ,
status TEXT DEFAULT 'running'
);
Step 2: Employee Sync Service
import { BambooHRClient } from '../bamboohr/client' ;
import { db } from '../db/queries' ;
const SYNC_FIELDS = [
'firstName' , 'lastName' , 'displayName' , 'workEmail' ,
'jobTitle' , 'department' , 'division' , 'location' ,
'supervisor' , 'status' , 'hireDate' , 'terminationDate' ,
'employeeNumber' ,
];
export class EmployeeSyncService {
constructor (private client : BambooHRClient ) {}
async fullSync (): Promise <SyncResult > {
const log = await db.createSyncLog ('full' );
try {
const report = await this .client .customReport (SYNC_FIELDS );
const result = { created : 0 , updated : 0 , deleted : 0 , errors : [] as string [] };
for (const emp of report.employees ) {
try {
const existing = await db.getEmployee (parseInt (emp.id ));
if (existing) {
await db.updateEmployee (parseInt (emp.id ), emp);
result.updated ++;
} else {
await db.createEmployee (parseInt (emp.id ), emp);
result.created ++;
}
} catch (err) {
result.errors .push (`Employee ${emp.id} : ${(err as Error ).message} ` );
}
}
const activeIds = new Set (report.employees .map (e => parseInt (e.id )));
const localEmployees = await db.getActiveEmployeeIds ();
for (const localId of localEmployees) {
if (!activeIds.has (localId)) {
await db.deactivateEmployee (localId);
result.deleted ++;
}
}
await db.completeSyncLog (log.id , result);
return result;
} catch (err) {
await db.failSyncLog (log.id , (err as Error ).message );
throw err;
}
}
async incrementalSync (): Promise <SyncResult > {
const lastSync = await db.getLastSyncTimestamp ();
const changed = await this .client .request <any >(
'GET' , `/employees/changed/?since=${lastSync} ` ,
);
const changedIds = Object .keys (changed.employees || {});
if (changedIds.length === 0 ) return { created : 0 , updated : 0 , deleted : 0 , errors : [] };
const result = { created : 0 , updated : 0 , deleted : 0 , errors : [] as string [] };
for (const id of changedIds) {
const emp = await this .client .getEmployee (id, SYNC_FIELDS );
}
return result;
}
async handleWebhookEvent (employeeId : string , action : string , fields : Record <string , string > ) {
switch (action) {
case 'Created' :
await db.createEmployee (parseInt (employeeId), fields);
break ;
case 'Updated' :
await db.updateEmployee (parseInt (employeeId), fields);
break ;
case 'Deleted' :
await db.deactivateEmployee (parseInt (employeeId));
break ;
}
}
}
Step 3: Employee Lifecycle Automation
export class EmployeeLifecycleService {
constructor (
private bamboohr : BambooHRClient ,
private slackClient : any ,
private googleAdmin : any ,
) {}
async onNewEmployee (employeeId : string , fields : Record <string , string > ) {
const { firstName, lastName, workEmail, department, jobTitle, supervisor } = fields;
await this .googleAdmin .createUser ({
primaryEmail : workEmail,
name : { givenName : firstName, familyName : lastName },
orgUnitPath : `/departments/${department} ` ,
});
await this .slackClient .inviteUser (workEmail);
await this .slackClient .addToChannel (workEmail, `#${department.toLowerCase()} ` );
await this .slackClient .sendDM (supervisor, {
text : `Your new report ${firstName} ${lastName} (${jobTitle} ) starts soon. ` +
`BambooHR profile: https://${process.env.BAMBOOHR_COMPANY_DOMAIN} .bamboohr.com/employees/employee.php?id=${employeeId} ` ,
});
console .log (`Onboarding complete for ${firstName} ${lastName} ` );
}
async onEmployeeTerminated (employeeId : string , fields : Record <string , string > ) {
const { workEmail, firstName, lastName } = fields;
await this .googleAdmin .suspendUser (workEmail);
await this .slackClient .deactivateUser (workEmail);
console .log (`Offboarding complete for ${firstName} ${lastName} ` );
}
async onDepartmentChanged (employeeId : string , fields : Record <string , string > ) {
const { workEmail, department } = fields;
await this .googleAdmin .moveUser (workEmail, `/departments/${department} ` );
await this .slackClient .addToChannel (workEmail, `#${department.toLowerCase()} ` );
}
}
Step 4: Sync Scheduling
import cron from 'node-cron' ;
cron.schedule ('0 2 * * *' , async () => {
console .log ('Starting full BambooHR sync...' );
const result = await syncService.fullSync ();
console .log (`Full sync: ${result.created} created, ${result.updated} updated, ${result.deleted} deleted` );
});
cron.schedule ('*/15 * * * *' , async () => {
const result = await syncService.incrementalSync ();
if (result.created + result.updated + result.deleted > 0 ) {
console .log (`Incremental sync: ${JSON .stringify(result)} ` );
}
});
Step 5: Configuration Management
export interface BambooHRIntegrationConfig {
api : {
companyDomain : string ;
apiKey : string ;
timeoutMs : number ;
maxRetries : number ;
};
sync : {
fullSyncCron : string ;
incrementalSyncCron : string ;
batchSize : number ;
};
cache : {
directoryTtlMs : number ;
employeeTtlMs : number ;
redisUrl ?: string ;
};
webhook : {
secret : string ;
path : string ;
replayWindowMs : number ;
};
}
export function loadConfig ( ): BambooHRIntegrationConfig {
return {
api : {
companyDomain : process.env .BAMBOOHR_COMPANY_DOMAIN !,
apiKey : process.env .BAMBOOHR_API_KEY !,
timeoutMs : 30_000 ,
maxRetries : 3 ,
},
sync : {
fullSyncCron : '0 2 * * *' ,
incrementalSyncCron : '*/15 * * * *' ,
batchSize : 100 ,
},
cache : {
directoryTtlMs : 5 * 60 * 1000 ,
employeeTtlMs : 60 * 1000 ,
redisUrl : process.env .REDIS_URL ,
},
webhook : {
secret : process.env .BAMBOOHR_WEBHOOK_SECRET !,
path : '/webhooks/bamboohr' ,
replayWindowMs : 300_000 ,
},
};
}
Output
Layered architecture separating API, service, client, and data concerns
Employee sync with full, incremental, and webhook-driven modes
PostgreSQL schema for local employee data with audit trail
Lifecycle automation (onboarding, offboarding, department changes)
Scheduled sync jobs with cron
Environment-specific configuration
Error Handling Issue Cause Solution Sync data gaps Missed webhooks + long incremental interval Full sync as daily safety net Duplicate processing Webhook retry + no idempotency Idempotency keys in sync log Stale local data Cache TTL too long Webhook-based cache invalidation Circular dependencies Poor layer separation Strict dependency direction (API > Service > Client > DB)
Enterprise Considerations
Multi-company : Deploy separate instances per BambooHR company domain, or use tenant-aware client factory
Data residency : Store employee data in the same region as your BambooHR instance
Compliance : Implement data retention policies; BambooHR data includes PII
High availability : Run sync workers as separate pods/containers from API servers
Monitoring : Alert on sync failures, webhook delivery gaps, and API error spikes
Resources
Flagship Skills For the complete BambooHR skill pack, start with bamboohr-install-auth.