Skip to content

Connect BambooHR

Connect BambooHR so joiners, leavers, job and team changes, and pay changes reach Flowstate without anyone typing them in again. The forecast and budgets then work from the people you employ today.

You need access to integrations. Ask your Flowstate admin. First decide whether BambooHR is where people changes are made: see Get your people data into Flowstate.

How it connects

Flowstate reads your people from BambooHR's API. We recommend a scheduled sync for BambooHR: it needs only an API key, and BambooHR can list the people who changed since the last run, so each run fetches only what's new.

RouteHow it worksChoose it when
Scheduled sync (recommended)A custom integration in Flowstate pulls from BambooHR's API on a schedule, from every 15 minutes to daily.You want the sync to run inside Flowstate, with nothing of your own to host.
Event-drivenYour middleware, such as Workato, Boomi, MuleSoft, Make or n8n, receives BambooHR's webhooks and updates Flowstate through the REST API.You already run middleware and want each change to arrive as it happens.

What you need from BambooHR

  • A BambooHR user for the sync. Its access level must let it see everything under What syncs, including pay. The API key carries that user's permissions, and BambooHR leaves out any field the user can't see without raising an error.
  • An API key created by that user.
  • Access to hiring for that user, if you want open jobs brought in as vacancies.
  • For the event-driven route: an admin, or a custom access level with webhook permission, to set up webhooks.

Set it up

In BambooHR

  1. Sign in as the user the sync will use.
  2. Open the user menu and select API Keys.
  3. Create a key and copy it.

In Flowstate

  1. Ask your Flowstate contact to switch on custom integrations for your organisation. They provide the hook for BambooHR and help your technical team configure it.
  2. Go to Settings → Integrations → Custom Integrations: select Browse catalog and open Custom Integrations.
  3. Select Create Integration. Enter a Name, such as BambooHR, and a Source System Key, such as bamboohr. Select Create. You can't change the key later.
  4. Under Credentials, select Add Credential and store the API key, using the key name and format your Flowstate contact gives you.
  5. Under Hooks, select Create Hook. Choose Pull as the Hook Type and Employee as the Entity Type, then select Create. Add the hook's code and select Save Code. Add hooks for contractors and vacancies the same way if you bring them in.
  6. On the hook's Settings tab, turn on Run on schedule and choose an Interval. For Daily, choose a Preferred hour. Select Save Code.
  7. Select Test (Dry Run) and open Preview. Check that nobody already in Flowstate is about to be created a second time.
  8. Turn the hook on with the switch at the top of the editor, and confirm Enable Hook.

Each step in more detail: Manage a custom integration in Settings.

People already in Flowstate

If you loaded people by spreadsheet before connecting BambooHR, your technical team links each one to their BambooHR ID before the first run. See Adopt people who are already in Flowstate.

Event-driven instead

  1. In Flowstate, go to Settings → Users & Access → API Keys and create a key that can view, create and update employees, contractors and vacancies.
  2. In BambooHR, go to Account Settings → Webhooks and add a webhook that sends to your middleware.
  3. Your technical team has the middleware update Flowstate. See Sync people from an HR system with the REST API.

What syncs

BambooHRFlowstate
Employee IDExternal ID, which is how the sync recognises the person on every run
First name, last name, work emailName and Email address
Job titleRole. A job title Flowstate hasn't seen before adds a job role.
DepartmentCurrent team
SupervisorLine manager. A scheduled sync can't set it: set it in Flowstate, or send it from middleware.
Employee or contractorBambooHR has no standard contractor flag. Check how your account marks contractors, such as an employment status or pay type, and tell your Flowstate contact so contractors come in as contractors.
Standard hours per weekFTE on their team. BambooHR has no FTE field, so agree your full-time hours with your Flowstate contact.
Hire date and termination dateEmployment dates
Compensation: pay rate, currency, how often it's paid, and the date it startsSalary changes, each from its effective date and in its own currency, on the Compensation tab
Job openings in hiringVacancies, with their role, team and status. BambooHR doesn't keep a salary on a job opening, so add it in Flowstate.
LocationLocation. A scheduled sync can't set it: set it in Flowstate, or send it from middleware.
Not in BambooHRWork type (Employment type on the person's record), which sets their overhead. Set it in Flowstate, or send it from middleware.

To set location, work type or line manager in Flowstate, go to Resourcing → People and teams → People, open the person and change them under Employee details. Nothing goes back to BambooHR.

How changes arrive

  • When. On the schedule you chose, from Every 15 minutes to Daily. With the event-driven route, as BambooHR sends each change.
  • Edits made in Flowstate. Anything the sync sends, such as role, team, dates and pay, is set back to BambooHR's value on the next run. Make those changes in BambooHR. Location, work type and line manager stay as you set them. More in Edits made in Flowstate.
  • Leavers. A termination date in BambooHR becomes the person's end date in Flowstate. They stay in past months of the forecast and effort. The sync never deletes anyone.
  • Rehires. A returning employee keeps their old end date in Flowstate, because a sync can't clear one. Your technical team clears it through the REST API. See Undo a leaver.
  • Future-dated pay. A pay change with a future effective date comes across on the next run and shows as Scheduled on the Compensation tab until that date.

Check it's working

  1. Open the hook and select Execution History.
  2. Find the latest run with Scheduled under Triggered By. It shows Completed, with a count under Records.
  3. If some records failed, the run's log has a line for each one, with the reason.
  4. Go to Resourcing → People and teams → People and compare a few people with BambooHR: a recent joiner, a recent leaver (Filter → Status → Include off-boarded) and someone with a recent pay change. Check Role, Current team, Employment dates and the Compensation tab.

If something's not right

Runs fail with an authentication error. The API key was deleted, or its user lost access. BambooHR also locks a key out for a while after repeated invalid attempts. Create a new key, then update the credential.

Pay, department or other details are blank. The sync user can't see those fields, and BambooHR leaves them out without an error. Give the user's access level those fields.

Runs fail with a 503 or 429 error. BambooHR is limiting how fast the sync can call it. From 16 September 2026, BambooHR answers with 429 instead of 503. Choose a less frequent Interval, or ask your Flowstate contact to look at the hook.

Contractors show up as employees. The hook doesn't know how your account marks contractors. Tell your Flowstate contact which employment status or pay type you use.

For your technical team

API. https://{companyDomain}.bamboohr.com/api/v1/. BambooHR replaced the https://api.bamboohr.com/api/gateway.php/{companyDomain}/v1/ form on 3 July 2025; the old form still works. Some endpoints are v2, such as POST /api/v2/datasets/{datasetName}/data.

Auth. HTTP Basic, with the API key as the username and any password, such as x. Hooks can't Base64-encode, so store the encoded {apiKey}:x value as the credential and send Authorization: Basic <value>. Requests carry the permissions of the key's user. BambooHR recommends OAuth 2.0 (an app registered in its Developer Portal) for new integrations; this set-up uses a customer-created API key.

Endpoints.

  • GET /employees/changed?since=<ISO 8601>&type=inserted|updated|deleted returns latest and employees{id: {id, action, lastChanged}}. Any field change counts, as does any change to the employment status, job info or compensation tables. Keep the last since in ctx.kv.
  • GET /employees/changed/tables/{table}?since= returns every row of each changed employee's table, not only the changed rows.
  • GET /employees pages by cursor (page[limit] up to 2500, page[after]), with filter[...] and fields=. Use it for the first full load.
  • GET /employees/{id|all}/tables/{table} reads jobInfo, employmentStatus and compensation rows.
  • GET /applicant_tracking/jobs returns job openings (id, title{label}, department, location, status, hiringLead, postedDate). It needs access to ATS settings.
  • GET /meta/fields and GET /meta/tables list fields and custom customN tables.
  • Don't rely on GET /employees/directory: it can be switched off per company, leaves out inactive employees and has no filters.

Fields.

  • Key on id, BambooHR's immutable employee ID. employeeNumber can be edited by the company.
  • terminationDate is read-only and comes from employmentStatus rows.
  • Compensation rows carry startDate, endDate, rate, type, paidPer, paySchedule and reason. Currency fields come back as {"value": "27000.00", "currency": "EUR"}.
  • At most 400 fields per request.
  • Fields the user can't see are left out, or come back null and are named in _restrictedFields. On List Employees, compare meta.total with the rows you could read.

Rate limits. BambooHR publishes no number. Throttled requests get 503, sometimes with Retry-After. From 16 September 2026 they get 429 with Retry-After, and genuine outages stay 503.

Webhooks, for middleware.

  • Global webhooks are set up in Account Settings → Webhooks by an admin. Permissioned webhooks are created with POST /api/v1/webhooks, see only the fields the key's user can see, and stop if that user loses access. The privateKey is returned once, at creation.
  • Event-based payloads (BambooHR's recommendation) send employee.created, employee.updated and employee.deleted, with data.companyId, data.employeeId and, on updates, data.changedFields. Field-based payloads send an employees[] array with the fields you choose. Custom table fields can't be monitored.
  • Verify X-BambooHR-Signature: HMAC-SHA256 of the raw body followed by the X-BambooHR-Timestamp value, keyed by the private key. Compare in constant time. No replay window is documented.
  • Failed deliveries (network errors or 5xx) are retried up to 5 times: immediately, then at 5, 10, 20 and 40 minutes.
  • Map employee.deleted and terminations to endDate in Flowstate. Don't delete the person.

BambooHR docs.

Flowstate Documentation