Skip to content

BambooHR Sensor

What it ingests

Org chart and role context from BambooHR — the employee directory, not time-off or compensation:

BambooHR objectOntology entitySignal
EmployeePerson (identity + role properties)employee
Department / divisionOrganizationemployee

An employee is identity — they resolve to Person via work email and a stable BambooHR employee id, the same contract as a HubSpot contact. Job title, department, and location land as properties on that Person. The employee's department (and division, when present) is an Organization with a MEMBER_OF edge; a department is PART_OF its division. The supervisor, when the directory exposes it, is RELATED_TO by name.

This is BambooHR alone. Workday is a different HRIS with a different API and has its own Workday sensor.

Read-only and poll-based against https://{companyDomain}.bamboohr.com/api/v1. BambooHR webhooks exist but are configured in the BambooHR UI, never via API, so they cannot be provisioned at install time.

Credential

References a bamboohr_api_key credential by id. The secret is a BambooHR API key. BambooHR authenticates with HTTP Basic: the key as the username and the literal x as the password.

The company subdomain is not part of the secret. It is a required config field (see below) interpolated into https://{companyDomain}.bamboohr.com.

bash
curl -sS -X POST https://your-corveil-host/api/credentials \
  -H "Authorization: Bearer <admin>" -H "Content-Type: application/json" \
  -d '{"type":"bamboohr_api_key","name":"acme-bamboohr","secret":"<api-key>"}'

OAuth (BambooHR's developer-portal marketplace app) is out of scope in v1.

Config fields

KeyRequiredNotes
company_domainyesThe subdomain in your BambooHR URL. If you log in at https://acme.bamboohr.com, this is acme. A full URL is accepted and stripped to the slug. Do not include a path.

There is no default_entity_type. This source emits Person and Organization, so a single override would silently mistype the rest.

Provider-side setup

  1. In BambooHR, click your profile photo → API Keys.
  2. Create a key. Copy it immediately — you will not see it again.
  3. Store only the key value, not key:x or Basic ….
  4. Note your company subdomain (acme in acme.bamboohr.com).
  5. Confirm Company Directory (or at least Company Org Chart) is shared with the access level that owns the API key. If both are off, the directory endpoint returns 403 Directory disabled for this account and Test connection fails.

Wire-up

POST /api/sensors

json
{
  "sensor_type": "bamboohr",
  "name": "Acme BambooHR",
  "config": {
    "company_domain": "acme"
  },
  "credentials": { "api_key": "<bamboohr_api_key credential id>" }
}

Verify

Run Test connection. It authenticates the key against GET /api/v1/employees/directory, so a 401/403 fails at save/test rather than on the first poll. A "Directory disabled" error means the Company Directory / Org Chart sharing settings, not a bad key.

Once polling, employees_collected appears in the per-poll summary log.

How incremental sync works

Worth knowing, because it explains a few behaviours you may notice.

  • Each poll re-reads the whole directory. BambooHR returns every published employee in one response and does not paginate. Typical HRIS sizes fit in a single request.
  • A title or manager change re-ingests. Event ids include a fingerprint of the role-context fields (bamboohr:employee:<id>:<fingerprint>), so sensor_events treats the change as a new event. The Person itself upserts on the stable bamboohr:employee:<id>.
  • Deletes are invisible. Someone vanishing from the directory is not treated as a deletion.
  • The fieldset is company-configured. A tenant that shares only the org chart omits supervisor, department, division, location, and work email. Names and job titles still land.

Not included

  • Workday. A different HRIS; do not configure this source against Workday.
  • OAuth / marketplace apps. Only needed for multi-customer marketplace distribution.
  • Webhooks. BambooHR supports them, but subscriptions are created in the BambooHR UI, never via API — so they cannot be provisioned at install time. Polling is the supported path.
  • Time-off, compensation, custom reports, files. Deferred.