A reference guide for building AI agents: every method, how to authenticate, and the permissions each one needs.
The BambooHR API is how an app or AI agent works with a company's HR records: reading and updating employee details, listing the directory, requesting and approving time off, pulling reports, and reading job and compensation history. Access is granted through an API key tied to one person's account, and a call can only see and change what that person could, since the API carries no separate scopes of its own. BambooHR can also push a notification to a webhook when a monitored employee field changes.
How an app or AI agent connects to BambooHR determines what it can reach. There are two routes, an API key tied to a person's account and OAuth on behalf of a user, and each one inherits exactly what that person can see and edit inside BambooHR.
The REST API answers at {companyDomain}.bamboohr.com/api/v1. As of July 2025 this is the standard host; the older api.bamboohr.com/api/gateway.php route is being retired. Responses are JSON or XML, chosen by the Accept header.
Webhooks deliver a notification when a monitored employee field changes, or when an employee is added or removed. A webhook is registered against chosen fields and posts the changed values to a receiver URL, removing the need to poll.
An API key is generated per person inside BambooHR and sent over HTTP Basic auth, as the username with any string for the password. The key inherits that person's access level, so it can see and edit exactly what they can. There are no separate API scopes.
OAuth 2.0 lets a registered application act on behalf of a user instead of holding a standing key. It was added in March 2025 and needs an application registered in the Developer Portal. Access is still bounded by the user's BambooHR permissions, not by API scopes.
The BambooHR API is split into areas an agent can act on, such as employee records, files, time off, reports, table data, and the fields that describe an account. There are no per-area permission settings on the API itself; what a call can reach is decided entirely by the account behind the key.
Read a single employee, add and update employees, and pull the published company directory.
List the files on an employee, download a file's contents, and upload a new file.
Read time off requests, add a request, approve or deny one, estimate a future balance, and see who is out.
Read, add, and update rows in employee tables such as job information and compensation.
List saved reports, pull a saved report by id, and request an ad-hoc custom report.
List the fields available in the account, list tabular fields, and list the account's users.
List, read, create, update, and delete webhooks, and list the fields a webhook can monitor.
Filter by method, access, or permission, or search any path. Select a row for version detail, rate limits, the related webhook event, and the source.
| Method | Endpoint | What it does | Access | Permission | Version | |
|---|---|---|---|---|---|---|
EmployeesRead a single employee, add and update employees, and pull the published company directory.5 | ||||||
| GET | /api/v1/employees/{id} | Get a single employee record, returning only the fields named in the request. | read | — | Current | |
No API scope. Which fields come back depends on the access level of the account behind the key; restricted fields are omitted rather than refused. Up to 400 fields can be requested at once. Acts onemployee Permission (capability)None required VersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /api/v1/employees/ | Add a new employee, requiring at least a first name and last name. | write | — | Current | |
No API scope. The account must have permission to add employees. A success returns 201 with a Location header pointing at the new record. Photo fields in the body are ignored. Acts onemployee Permission (capability)None required VersionAvailable since the API’s base version Webhook event employee_changedRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /api/v1/employees/{id} | Update an employee by submitting field name and value pairs. | write | — | Current | |
No API scope. The account can only change fields it has edit permission for; an update to a field it cannot edit is rejected. Acts onemployee Permission (capability)None required VersionAvailable since the API’s base version Webhook event employee_changedRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /api/v1/employees/directory | Get the company's published employee directory as a fieldset definition plus an array of employee records. | read | — | Current | |
No API scope. Returns the directory the account is permitted to see. The directory must be enabled in the account for this to return data. Acts ondirectory Permission (capability)None required VersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /api/v1/employees | List employees with filtering, sorting, and cursor-based pagination, choosing the fields to return. | read | — | New | |
No API scope. Added October 2025 as a more flexible way to retrieve employees. The returned set is limited to the employees the account can see. Acts onemployee Permission (capability)None required VersionIntroduced 2025-10-02 Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
Employee filesList the files on an employee, download a file's contents, and upload a new file.3 | ||||||
| GET | /api/v1/employees/{id}/files/view | List the file categories and files visible on an employee. | read | — | Current | |
No API scope. Only the files and categories the account is permitted to see are listed. Acts onfile Permission (capability)None required VersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /api/v1/employees/{id}/files/{fileId} | Download the binary contents of an employee file. | read | — | Current | |
No API scope. Returns the file's MIME type and original filename. Employee id 0 refers to the file of the account holding the key. Acts onfile Permission (capability)None required VersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /api/v1/employees/{id}/files | Upload a file to an employee as a multipart form post. | write | — | Current | |
No API scope. The request must be multipart/form-data, with the file plus category, fileName, and share fields. The account needs permission to add files to the employee. Acts onfile Permission (capability)None required VersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
Time offRead time off requests, add a request, approve or deny one, estimate a future balance, and see who is out.5 | ||||||
| GET | /api/v1/time_off/requests | List time off requests in a date range, optionally filtered by status, employee, or type. | read | — | Current | |
No API scope. The start and end query parameters are both required, in YYYY-MM-DD format. Results are limited to requests the account can see. Acts ontime off request Permission (capability)None required VersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| PUT | /api/v1/employees/{id}/time_off/request | Add a time off request for an employee. | write | — | Current | |
No API scope. A request must be approved before it counts in the history, though an account with enough permission can create and approve it in one step. Acts ontime off request Permission (capability)None required VersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| PUT | /api/v1/time_off/requests/{requestId}/status | Approve, deny, or cancel an existing time off request. | write | — | Current | |
No API scope. Valid statuses are approved, denied (or declined), and canceled. The account must be allowed to approve the request. Acts ontime off request Permission (capability)None required VersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /api/v1/employees/{id}/time_off/calculator | Estimate an employee's future time off balance on a given date. | read | — | Current | |
No API scope. Returns a projected balance per time off type, so the account needs to be able to see that employee's time off. Acts ontime off balance Permission (capability)None required VersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /api/v1/time_off/whos_out | Get a list of who is out across the company in a date range. | read | — | Current | |
No API scope. Returns approved time off and holidays in the window the account is permitted to see. Acts ontime off request Permission (capability)None required VersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
TablesRead, add, and update rows in employee tables such as job information and compensation.3 | ||||||
| GET | /api/v1/employees/{id}/tables/{table} | Read the rows of a named employee table, such as job information or compensation. | read | — | Current | |
No API scope. The {table} value is a name like jobInfo or compensation. Compensation in particular is often restricted, so the call returns rows only if the account can see that table. Acts ontable row Permission (capability)None required VersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /api/v1/employees/{id}/tables/{table} | Add a new row to a named employee table. | write | — | Current | |
No API scope. The account must be allowed to edit that table for the employee. Fields are submitted as name and value pairs in JSON or XML. Acts ontable row Permission (capability)None required VersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /api/v1/employees/{id}/tables/{table}/{rowId} | Update an existing row in a named employee table. | write | — | Current | |
No API scope. The account must be allowed to edit that table for the employee. This changes real job or pay history. Acts ontable row Permission (capability)None required VersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
ReportsList saved reports, pull a saved report by id, and request an ad-hoc custom report.3 | ||||||
| GET | /api/v1/custom-reports | List the saved custom reports available in the account. | read | — | Current | |
No API scope. Returns each report's id and name. The reports listed are those the account can access. Acts onreport Permission (capability)None required VersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /api/v1/reports/{id} | Pull the data of a saved company report by its id. | read | — | Current | |
No API scope. A report can return data across the whole company at once, so the account's access level decides which rows and columns it sees. Acts onreport Permission (capability)None required VersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /api/v1/reports/custom | Request an ad-hoc report by naming the fields and optional filters. | read | — | Current | |
No API scope. Returns JSON, XML, CSV, XLS, or PDF. This is a read despite using POST, because it builds a report rather than changing data; the account's access still bounds what it can pull. Acts onreport Permission (capability)None required VersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
MetadataList the fields available in the account, list tabular fields, and list the account's users.3 | ||||||
| GET | /api/v1/meta/fields | List the employee fields available in the account, with id, name, and type. | read | — | Current | |
No API scope. Returns the field catalogue that describes the account, used to know which field ids exist before reading or writing them. Acts onfield Permission (capability)None required VersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /api/v1/meta/tables | List the tabular fields, the tables and the columns inside them, available in the account. | read | — | Current | |
No API scope. Used to discover the names of standard and custom tables before reading their rows. Acts onfield Permission (capability)None required VersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /api/v1/meta/users | List the account's users, optionally filtered by enabled or disabled status. | read | — | Current | |
No API scope. Since March 2025, email addresses in this response are returned only to admin accounts. Support admin accounts are always excluded. Acts onuser Permission (capability)None required VersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
WebhooksList, read, create, update, and delete webhooks, and list the fields a webhook can monitor.6 | ||||||
| GET | /api/v1/webhooks | List the webhooks owned by the authenticated account. | read | — | Current | |
No API scope. Returns each webhook's id, name, url, creation time, and last-fired time. Only the caller's own webhooks are listed. Acts onwebhook Permission (capability)None required VersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /api/v1/webhooks/{id} | Get the full configuration of a single webhook. | read | — | Current | |
No API scope. Returns the webhook's name, url, format, monitored fields, post fields, events, and timestamps. Only a webhook the account owns can be read. Acts onwebhook Permission (capability)None required VersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /api/v1/webhooks | Create a webhook that fires when chosen events occur or monitored fields change. | write | — | Current | |
No API scope. A permissioned webhook can only ever report fields the creating account is allowed to see. The fields available to monitor come from the List Monitor Fields endpoint. Acts onwebhook Permission (capability)None required VersionAvailable since the API’s base version Webhook event employee_changedRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| PUT | /api/v1/webhooks/{id} | Replace a webhook's configuration in full. | write | — | Current | |
No API scope. This is a full replacement, so every body field overwrites the existing value and any omitted optional field reverts to its default. Acts onwebhook Permission (capability)None required VersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| DELETE | /api/v1/webhooks/{id} | Permanently delete a webhook. | write | — | Current | |
No API scope. Only a webhook the account owns can be deleted, and the removal cannot be undone. Acts onwebhook Permission (capability)None required VersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /api/v1/webhooks/monitor_fields | List the employee fields that a webhook can be set to monitor. | read | — | Current | |
No API scope. Returns the set of fields available to watch, which is bounded by what the calling account is permitted to see. Acts onfield Permission (capability)None required VersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
BambooHR can notify an app or AI agent when an employee record changes, instead of the app repeatedly asking. A webhook is registered against a chosen set of monitored fields, and BambooHR posts the changed values to a receiver URL whenever one of those fields changes, or when an employee is added or removed.
| Event | What it signals | Triggered by |
|---|---|---|
Employee created, updated, or deleted | Fires when a monitored employee field changes, or when an employee is added or removed. On an update the payload lists the changed monitored fields and their current values; on a create or delete the changed-fields list is empty and the event simply reports that the employee was added or removed. | /api/v1/employees//api/v1/employees/{id}/api/v1/webhooks |
BambooHR does not publish a fixed request quota. It throttles requests it judges to be too frequent and answers a throttled call with a 503 status, so an app or AI agent should slow down and retry rather than assume a hard ceiling.
BambooHR does not publish a fixed numeric rate limit. The documentation states that requests can be throttled if BambooHR judges them too frequent, and a throttled request is answered with a 503 status, sometimes carrying a Retry-After header that says how long to wait. The practical model is to back off and retry on a 503 rather than to plan against a known per-minute or per-hour ceiling. A 429 status can also be returned when a limit is exceeded.
Most endpoints return a full result set rather than paging. The newer List Employees endpoint added in October 2025 is the exception: it uses cursor-based pagination, returning a data array plus a meta block with the total count and the cursor state, and _links carrying next and prev when more pages exist. Older list-style endpoints, such as the directory and reports, return the whole collection in one response.
Requests and responses are JSON or XML, chosen by the Accept header. A single employee request can name up to 400 fields. File uploads are sent as multipart/form-data, and custom reports can be returned as JSON, XML, CSV, XLS, or PDF. No single overall payload size limit is documented across the API.
The status codes an agent should handle, and what to do about each.
| Status | Code | Meaning | What to do |
|---|---|---|---|
| 400 | Bad Request | The request was malformed, such as an invalid field name or value or a body that could not be parsed. | Check the field names against the account's field catalogue and fix the request body, then resend. |
| 401 | Unauthorized | The API key is missing or invalid. | Send a valid API key over Basic auth, as the username with any string for the password. |
| 403 | Forbidden | The key is valid but the account behind it lacks permission for the employee, field, or action requested. | Use a key from an account whose BambooHR access level covers the request, since the API has no separate scopes to grant. |
| 404 | Not Found | The resource does not exist, or the path is wrong. | Confirm the employee id, table name, or report id, and the path, then retry. |
| 406 | Not Acceptable | The requested response format in the Accept header is not supported for this endpoint. | Request a supported format, such as application/json or application/xml. |
| 409 | Conflict | The request conflicts with the current state of the resource. | Refetch the current state, resolve the conflict, then retry. |
| 429 | Limit Exceeded | A request limit was exceeded. | Slow the request rate and retry after a pause. |
| 503 | Unavailable | The request was throttled because BambooHR judged it too frequent, or the service is temporarily unavailable. A Retry-After header may say how long to wait. | Honour the Retry-After header if present, then back off and retry. |
BambooHR has a single API version, v1, in the request path. It does not mint new dated versions; changes ship continuously and are recorded in a historical changelog, with new endpoints and field behaviour added in place.
BambooHR runs one API version, v1, carried in the request path. It does not mint new dated versions or run parallel versions; changes ship continuously and are recorded in a historical changelog. The dated entries below are notable changes from that changelog, newest first.
Added a new List Employees endpoint with filtering, sorting, optional field selection, and cursor-based pagination, a more efficient way to retrieve employee data than the directory.
Webhooks moved to real-time, event-driven delivery, gained support for the delete event, and lost the older cron-based scheduling and rate-limiting controls.
Requests moved to the {companyDomain}.bamboohr.com/api/ host, replacing the older api.bamboohr.com/api/gateway.php/{companyDomain}/ routing.
OAuth 2.0 was added as an authentication method, letting a registered application act on behalf of a user instead of holding a standing API key. The legacy API key login flow began a gradual deprecation.
Email addresses in the meta users endpoint were restricted so that only admin accounts can retrieve them.
There is one version, v1, so there is nothing to pin or migrate between. Track the changelog for behaviour changes.
BambooHR API changelog ↗Bollard AI sits between a team's AI agents and BambooHR. Grant each agent exactly the access it needs, read or write, area by area, and every call is checked and logged.