Claude-code-plugins-plus-skills bamboohr-core-workflow-a
install
source · Clone the upstream repo
git clone https://github.com/jeremylongshore/claude-code-plugins-plus-skills
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/jeremylongshore/claude-code-plugins-plus-skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/plugins/saas-packs/bamboohr-pack/skills/bamboohr-core-workflow-a" ~/.claude/skills/jeremylongshore-claude-code-plugins-plus-skills-bamboohr-core-workflow-a && rm -rf "$T"
manifest:
plugins/saas-packs/bamboohr-pack/skills/bamboohr-core-workflow-a/SKILL.mdsource content
BambooHR Core Workflow A — Employee Management & Reports
Overview
Primary BambooHR workflows: CRUD operations on employees, directory sync to external systems, custom reports, and table data (job history, compensation, emergency contacts).
Prerequisites
- Completed
setupbamboohr-install-auth
fromBambooHRClientbamboohr-sdk-patterns- API key with appropriate permissions (read or read+write)
Instructions
Step 1: Add a New Employee
// POST /employees/ — minimum: firstName + lastName const newEmpRes = await fetch(`${BASE}/employees/`, { method: 'POST', headers: { Authorization: AUTH, 'Content-Type': 'application/json' }, body: JSON.stringify({ firstName: 'Sarah', lastName: 'Chen', department: 'Engineering', jobTitle: 'Backend Engineer', workEmail: 'sarah.chen@acmecorp.com', hireDate: '2026-04-01', location: 'San Francisco', status: 'Active', }), }); // New employee ID is in the Location header const locationHeader = newEmpRes.headers.get('Location'); // e.g., "https://api.bamboohr.com/.../v1/employees/456" const newId = locationHeader?.split('/').pop(); console.log(`Created employee ID: ${newId}`);
Step 2: Update Employee Fields
// POST /employees/{id}/ — only send fields you want to change await fetch(`${BASE}/employees/${newId}/`, { method: 'POST', headers: { Authorization: AUTH, 'Content-Type': 'application/json' }, body: JSON.stringify({ jobTitle: 'Senior Backend Engineer', department: 'Platform Engineering', }), });
Fields that trigger position history changes:
jobTitle, department, division, location, reportsTo. Updating these creates a new row in the employee's position history table.
Step 3: Directory Sync to External System
interface SyncResult { created: number; updated: number; deactivated: number; errors: string[]; } async function syncBambooHRDirectory( onSync: (emp: BambooEmployee, action: string) => Promise<void>, ): Promise<SyncResult> { const result: SyncResult = { created: 0, updated: 0, deactivated: 0, errors: [] }; // Fetch full directory const { employees } = await client.getDirectory(); // Use the "changed since" endpoint for incremental sync // GET /employees/changed/?since=2026-03-20T00:00:00Z const changedRes = await client.request<Record<string, { lastChanged: string }>>( 'GET', `/employees/changed/?since=${lastSyncTimestamp}`, ); for (const [empId, meta] of Object.entries(changedRes.employees || {})) { try { const emp = await client.getEmployee(empId, [ 'firstName', 'lastName', 'workEmail', 'department', 'jobTitle', 'status', 'hireDate', 'terminationDate', ]); const action = emp.terminationDate ? 'deactivated' : emp.status === 'Active' ? 'updated' : 'created'; await onSync(emp as any, action); result[action as keyof SyncResult]++; } catch (err) { result.errors.push(`Employee ${empId}: ${(err as Error).message}`); } } return result; }
Step 4: Custom Reports
// POST /reports/custom?format=JSON — pull arbitrary field combinations const headcountReport = await client.customReport( ['department', 'division', 'jobTitle', 'hireDate', 'status', 'location'], { lastChanged: { includeNull: 'no', value: '2025-01-01T00:00:00Z' } }, ); // Aggregate by department const deptCounts = new Map<string, number>(); for (const emp of headcountReport.employees) { const dept = emp.department || 'Unassigned'; deptCounts.set(dept, (deptCounts.get(dept) || 0) + 1); } console.log('Headcount by Department:'); for (const [dept, count] of [...deptCounts.entries()].sort((a, b) => b[1] - a[1])) { console.log(` ${dept}: ${count}`); }
Step 5: Saved Reports
// GET /reports/{reportId}?format=JSON — run a saved report from BambooHR const savedReport = await client.request<{ title: string; employees: Record<string, string>[]; }>('GET', '/reports/42?format=JSON'); console.log(`Report: ${savedReport.title}`); for (const row of savedReport.employees) { console.log(row); }
Step 6: Employee Table Data
BambooHR stores structured data in "tables" — each employee has rows in tables like
jobInfo, employmentStatus, compensation, emergencyContacts.
// GET /employees/{id}/tables/{tableName} — read table rows const jobHistory = await client.getTableRows(123, 'jobInfo'); // Returns array: [{ date, jobTitle, department, division, location, reportsTo }, ...] const compensation = await client.getTableRows(123, 'compensation'); // Returns: [{ startDate, rate, type, reason, comment }, ...] const emergencyContacts = await client.getTableRows(123, 'emergencyContacts'); // Returns: [{ name, relationship, phone, email }, ...] // POST /employees/{id}/tables/{tableName} — add a new row await client.addTableRow(123, 'emergencyContacts', { name: 'John Smith', relationship: 'Spouse', phone: '555-0100', email: 'john@example.com', });
Available table names:
| Table | Description |
|---|---|
| Job title, department, division, location changes |
| Hire date, termination date, status changes |
| Pay rate, pay type, pay schedule changes |
| Emergency contact records |
| Employee dependents |
| Custom tables created in BambooHR admin |
Output
- New employees created with auto-assigned IDs
- Employee fields updated with position history tracking
- Directory sync with incremental change detection
- Custom and saved reports with aggregation
- Table data CRUD for job history, compensation, contacts
Error Handling
| Error | Cause | Solution |
|---|---|---|
| 400 on employee create | Missing or | Both are required |
| 403 on compensation tables | API key lacks access | Need admin-level API key |
| 409 on duplicate | Same exists | Use unique employee numbers |
Empty response | No changes since timestamp | Normal — nothing to sync |
Resources
Next Steps
For time off and benefits workflows, see
bamboohr-core-workflow-b.