Skip to main content

BambooHR integration

Sync employees, time-off requests, applicants, and HR reports between BambooHR and the rest of your clients' stack.

What it does

The BambooHR integration lets your agency orchestrate employee records, time-off, job applications, and HR reports on behalf of your clients' BambooHR accounts. Use it to mirror new hires into downstream tools, route pending time-off requests to Slack or email for approval, react to job applications as they arrive, and pipe BambooHR reports and historical tables into spreadsheets or a warehouse.

Connect a BambooHR account

BambooHR uses OAuth 2.0. Because BambooHR issues OAuth credentials per developer application, each agency registers its own app once and every client then connects with a single approval — no API keys are copied or emailed.

One-time setup, per agency:

  1. Create a free account at the BambooHR Developer Portal.
  2. Create an application to get a Client ID and Client Secret.
  3. Register https://app.taskjuice.ai/oauth/callback as the application's Redirect URI. It must match exactly — an extra slash or a changed capital breaks the flow. A URI that is not registered fails only at the very END of the flow: BambooHR shows the consent screen, accepts the approval, and then returns redirect_uri_mismatch instead of issuing a code.
  4. Under Application Scopes, grant the scopes listed below. Do not also grant public.user: BambooHR treats it and public.integration as mutually exclusive and rejects any authorization request carrying both, so the consent screen never appears.
  5. In TaskJuice, add the Client ID and Secret as a BYOC OAuth client under Settings → Integrations.

Per client:

  1. Open your workspace in TaskJuice and navigate to Connections.
  2. Choose BambooHR and enter the client's subdomain — the part before .bamboohr.com in their BambooHR URL.
  3. Click Connect and approve the requested access in the client's BambooHR account.

Scopes

BambooHR models access as a scope plus a level (Read or Read/Write). Grant:

LevelScopes
Read/Writeemployee, employee:name, employee:contact, employee:job, employee:file, time_off, webhooks
Reademployee_directory, meta, field, report, offline_access, public.integration, onboarding, hiring:applications, employee:assets, employee:custom_fields, employee:education, employee:emergency_contacts

offline_access is required, not optional: BambooHR access tokens expire after one hour and it is the scope that causes a refresh token to be issued. Without it every connection stops working an hour after it is created.

field at Read is what fills the Job Title, Department, Division and Location pickers — those read your account's configured list options, and without it the pickers fail to load with an authentication error even though the rest of the connection works.

webhooks at Read/Write is what lets TaskJuice register and tear down the employee webhooks for you. Deliberately not requested: compensation, payroll, dependents, SSN, and the other sensitive tiers — nothing in this integration reads them, and requesting them would make your clients' consent screen alarming for no benefit.

Triggers

  • bamboohr/new-employee fires when an employee record is created. TaskJuice registers the webhook with BambooHR automatically when you publish.
  • bamboohr/updated-employee fires when a monitored field changes on an employee record — name, work email, job title, department, division, location, status, employment status, or hire date.
  • bamboohr/new-time-off-request polls time-off requests and fires once per cycle, with every newly observed request in items.
  • bamboohr/new-job-application polls Applicant Tracking and fires once per cycle, with the applications it admits in items. Only applications created after the workflow is first published fire, judged by the application's own creation date, so changing the status of an older application does not fire it. Requires the BambooHR Hiring add-on.

Each polling trigger emits one activation per cycle wrapping every new record in an items array. Add a Loop node downstream to process records one at a time; leave it off to handle the batch as a digest.

Actions

  • bamboohr/list-employees lists the employee directory.
  • bamboohr/get-employee fetches one employee with the fields you request.
  • bamboohr/create-employee creates an employee record and returns its new ID.
  • bamboohr/update-employee updates fields on an existing employee.
  • bamboohr/get-employee-table reads one historical table on an employee — job history, employment status, emergency contacts, assets, education, certifications, passports, or visas.
  • bamboohr/list-changed-employee-tables lists every employee whose rows in a chosen table changed since a timestamp.
  • bamboohr/list-employee-files lists the files attached to an employee, grouped by category.
  • bamboohr/upload-employee-file uploads a file to an employee record.
  • bamboohr/list-time-off-requests lists time-off requests, filtered by date range, employee, type, or status.
  • bamboohr/create-time-off-request files a time-off request for an employee.
  • bamboohr/respond-to-time-off-request approves, denies, or cancels a request.
  • bamboohr/get-whos-out lists who is out over a date range.
  • bamboohr/list-updated-employees lists employees changed since a timestamp.
  • bamboohr/get-report runs a saved company report by ID.

Known limitations

  • Webhooks cover employees only. BambooHR emits employee.created, employee.updated, and employee.deleted and nothing else, so time-off and hiring triggers poll rather than receive pushes.
  • New hires fire twice. BambooHR creates the record and then initialises it, so a new hire raises employee.created and then employee.updated. Filter downstream if you only want one.
  • Webhook payloads carry no field values. A delivery carries the employee ID and the names of the changed fields, not their contents. Chain get-employee to read the new values.
  • Updated Employee watches a fixed field set. TaskJuice registers the webhook against ten standard fields (name, work email, job title, department, division, location, status, employment status, hire date). BambooHR silently drops any of these your account does not define — the registration still succeeds — so a change to a field your account lacks raises no event. Verified live: registering with unknown field names returned 201 with an empty monitored-field list rather than an error.
  • employee.updated is permission-gated. It only fires if the connecting user can see every monitored field. employee.created and employee.deleted are not gated.
  • There is no "employee terminated" event. Watch employee.updated and filter on status or employmentHistoryStatus.
  • Job title, department, division, and location are company lists. Create Employee and Update Employee offer these as pickers filled from your BambooHR account. A value that is not already an option on the account is discarded silently — the call still succeeds and the field stays empty — so add the option in BambooHR first rather than typing a new one.
  • Job title and department cannot be set on the same call that creates an employee unless the value already exists as a list option; otherwise create the employee, add the option in BambooHR, then run Update Employee.
  • Create Time Off Request takes Notes as a list, not a sentence. BambooHR expects notes as an array of { from, note } entries where from is employee or manager. A plain string is rejected: 400 Missing required "from" attribute on the note. Must be either "manager" or "employee". Leave Notes empty if you do not need it. BambooHR echoes the saved notes back in a DIFFERENT shape than it accepts — an object keyed by author ({"employee": "..."}), or [] when there are none — so do not expect the response to mirror what you sent.
  • Upload Employee File gives you nothing to chain. BambooHR answers the upload with 201 and an empty body; the new file's id is only in a Location header, which TaskJuice does not surface. Use List Employee Files afterwards if a later step needs the id.
  • get-employee needs an explicit field list. Called without one, BambooHR returns only the employee ID with a 200 status rather than an error.
  • Compensation, bonus, commission, earnings, dependents, and equity tables are not offered by get-employee-table — they need permission tiers this integration deliberately does not request.
  • Errors carry no response body. BambooHR returns failures with an empty body and the reason in an X-BambooHR-Error-Message header, so TaskJuice surfaces the HTTP status rather than the provider's sentence.
  • No documented rate limits. BambooHR publishes no rate-limit headers; TaskJuice backs off on 429 without a Retry-After hint. Repeated use of an unknown API key disables API access temporarily and returns 403.
Was this helpful?