- Documentation
- Integrations
- Apps
- BambooHR integration
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:
- Create a free account at the BambooHR Developer Portal.
- Create an application to get a Client ID and Client Secret.
- Register
https://app.taskjuice.ai/oauth/callbackas 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 returnsredirect_uri_mismatchinstead of issuing a code. - Under Application Scopes, grant the scopes listed below. Do not also grant
public.user: BambooHR treats it andpublic.integrationas mutually exclusive and rejects any authorization request carrying both, so the consent screen never appears. - In TaskJuice, add the Client ID and Secret as a BYOC OAuth client under Settings → Integrations.
Per client:
- Open your workspace in TaskJuice and navigate to Connections.
- Choose BambooHR and enter the client's subdomain — the part before
.bamboohr.comin their BambooHR URL. - 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:
| Level | Scopes |
|---|---|
| Read/Write | employee, employee:name, employee:contact, employee:job, employee:file, time_off, webhooks |
| Read | employee_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-employeefires when an employee record is created. TaskJuice registers the webhook with BambooHR automatically when you publish.bamboohr/updated-employeefires 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-requestpolls time-off requests and fires once per cycle, with every newly observed request initems.bamboohr/new-job-applicationpolls Applicant Tracking and fires once per cycle, with the applications it admits initems. 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-employeeslists the employee directory.bamboohr/get-employeefetches one employee with the fields you request.bamboohr/create-employeecreates an employee record and returns its new ID.bamboohr/update-employeeupdates fields on an existing employee.bamboohr/get-employee-tablereads one historical table on an employee — job history, employment status, emergency contacts, assets, education, certifications, passports, or visas.bamboohr/list-changed-employee-tableslists every employee whose rows in a chosen table changed since a timestamp.bamboohr/list-employee-fileslists the files attached to an employee, grouped by category.bamboohr/upload-employee-fileuploads a file to an employee record.bamboohr/list-time-off-requestslists time-off requests, filtered by date range, employee, type, or status.bamboohr/create-time-off-requestfiles a time-off request for an employee.bamboohr/respond-to-time-off-requestapproves, denies, or cancels a request.bamboohr/get-whos-outlists who is out over a date range.bamboohr/list-updated-employeeslists employees changed since a timestamp.bamboohr/get-reportruns a saved company report by ID.
Known limitations
- Webhooks cover employees only. BambooHR emits
employee.created,employee.updated, andemployee.deletedand 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.createdand thenemployee.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-employeeto 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.updatedis permission-gated. It only fires if the connecting user can see every monitored field.employee.createdandemployee.deletedare not gated.- There is no "employee terminated" event. Watch
employee.updatedand filter onstatusoremploymentHistoryStatus. - 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
notesas an array of{ from, note }entries wherefromisemployeeormanager. 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
201and an empty body; the new file's id is only in aLocationheader, which TaskJuice does not surface. Use List Employee Files afterwards if a later step needs the id. get-employeeneeds 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-Messageheader, 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
429without aRetry-Afterhint. Repeated use of an unknown API key disables API access temporarily and returns403.