Skip to content

Latest commit

 

History

History
# BambooHR Python SDK

Official Python SDK for the [BambooHR API](https://documentation.bamboohr.com).

## Overview

The BambooHR Python SDK provides a type-safe, Pythonic interface to the BambooHR REST API. It includes auto-generated client classes covering all public API endpoints, a fluent builder for authentication and configuration, and production-ready features such as automatic token refresh, retry with exponential backoff, and secure logging.

## Requirements

- Python 3.10+

## Installation

```bash
pip install bamboohr-sdk
```

## Quick Start

```python
from bamboohr_sdk.client import BambooHRClient
from bamboohr_sdk.exceptions import ApiException

client = (
    BambooHRClient()
    .with_oauth("your-access-token")
    .for_company("your-company-subdomain")
    .build()
)

try:
    directory = client.employees().get_employees_directory()
    for emp in directory.employees or []:
        print(emp.get("displayName"))
except ApiException as e:
    print(f"API error ({e.status}): {e.reason}")
```

See [GETTING_STARTED.md](GETTING_STARTED.md) for a full walkthrough and [AUTHENTICATION.md](AUTHENTICATION.md) for all authentication options. **OAuth 2.0 is recommended for all partner integrations** — see the authentication guide for setup.

## Documentation

- [Getting Started Guide](GETTING_STARTED.md) — installation, first API call, configuration options
- [Authentication Guide](AUTHENTICATION.md) — OAuth 2.0 (recommended), API key, automatic token refresh
- [API Reference]({{apiDocPath}}) — per-endpoint documentation for all API classes
- [Examples](examples/) — runnable examples covering common patterns
- [BambooHR API Docs](https://documentation.bamboohr.com/docs/getting-started)
- [Changelog](CHANGELOG.md)

## SDK Features

### Retry with Exponential Backoff

All API requests are automatically retried on transient failures (HTTP 408, 429, 504, 598). Configure via `BambooHRClient`:

```python
client = (
    BambooHRClient()
    .with_oauth("your-access-token")
    .for_company("your-company")
    .with_retries(3)  # 0–5, default 1
    .build()
)
```

### HTTPS Enforcement

All host URLs are automatically upgraded to HTTPS. Setting `host="http://..."` or `host="example.com"` will both resolve to `https://...`.

### Custom User-Agent

All requests include the header `User-Agent: BHR-SDK/{version}/Python`.

### Request ID Support

Exceptions automatically extract the request ID from response headers (`x-request-id`, `x-bamboohr-request-id`, or `request-id`) for easier debugging:

```python
try:
    api.some_endpoint()
except ApiException as e:
    print(e.request_id)  # Extracted from response headers
```

### Secure Logging

The SDK uses Python's `logging` module under the `bamboohr_sdk` logger name. Sensitive headers (Authorization, API keys, cookies) and URL query parameters are automatically redacted in log output.

```python
import logging
logging.getLogger("bamboohr_sdk").setLevel(logging.DEBUG)
```

### Raw Response for Void Endpoints

Endpoints without a defined return type return an `ApiResponse` object instead of `None`, giving access to status code, headers, and raw response data.

## API Endpoints

All URIs are relative to *{{basePath}}*

Class | Method | HTTP request | Description
------------ | ------------- | ------------- | -------------
{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}*{{classname}}* | [**{{operationId}}**]({{apiDocPath}}{{classname}}.md#{{operationIdLowerCase}}) | **{{httpMethod}}** {{path}} | {{summary}}
{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}}

## Models

{{#models}}{{#model}}- [{{{classname}}}]({{modelDocPath}}{{{classname}}}.md)
{{/model}}{{/models}}

## Exceptions

- [Exceptions](docs/Exceptions/Exceptions.md) - Information about exceptions, potential causes, and debugging tips

## Troubleshooting

### Common Errors

#### Authentication Errors (401)

**Symptom:** `AuthenticationFailedException` on every request.

**Solutions:**
- **API key:** Verify your key is correct and not disabled. The SDK sends it as HTTP Basic auth with `"x"` as the password — this is handled automatically.
- **OAuth:** Check that your access token hasn't expired. Use `with_oauth_refresh()` for automatic token renewal.
- **Company subdomain:** Ensure `for_company()` matches your BambooHR subdomain exactly (e.g., if your URL is `acme.bamboohr.com`, use `"acme"`).

#### Permission Errors (403)

**Symptom:** `PermissionDeniedException` for specific endpoints.

**Solutions:**
- Verify the API key or OAuth token has access to the requested resource.
- Contact your BambooHR administrator to review API access permissions.
- Check if IP restrictions are in place for API access.

#### Rate Limiting (429)

**Symptom:** `RateLimitExceededException` during batch operations.

**Solutions:**
- The SDK automatically retries on 429 responses with exponential backoff. Increase retries:
  ```python
  client = BambooHRClient().with_retries(5).for_company("acme").build()
  ```
- Add delays between batch requests: `time.sleep(0.1)` between calls.
- Check the `Retry-After` response header for server guidance.

### Network Troubleshooting

#### Connection Timeouts

**Symptom:** Requests hang or fail with timeout errors.

**Solutions:**
- Configure a timeout:
  ```python
  client = BambooHRClient().with_timeout(30.0).for_company("acme").build()
  ```
- Check your network connection and firewall settings.
- Verify that `*.bamboohr.com` is accessible from your network.

#### SSL/TLS Errors

**Symptom:** SSL certificate verification failures.

**Solutions:**
- Ensure your Python installation has up-to-date CA certificates: `pip install --upgrade certifi`
- If behind a corporate proxy, your IT team may need to add the proxy's CA certificate to your trust store.
- **Do not** disable SSL verification in production.

#### Proxy Configuration

If you're behind a corporate proxy, configure it via environment variables:

```bash
export HTTPS_PROXY=https://proxy.example.com:8080
```

### Enabling Debug Logging

Enable detailed request/response logging to diagnose issues:

```python
import logging
logging.basicConfig(level=logging.DEBUG)
logging.getLogger("bamboohr_sdk").setLevel(logging.DEBUG)
```

This will log request URLs, response status codes, retry attempts, and token refresh events. Sensitive data (API keys, tokens, Authorization headers) is automatically redacted.

### Getting Help

When reporting issues, include:
- The **request ID** from the exception (`e.request_id`) — this helps BambooHR support trace the request.
- The **HTTP status code** and error message.
- The **SDK version** (`pip show bamboohr-sdk`).
- Debug log output (sensitive data is auto-redacted).

## Project Structure

```
bhr-api-python/
├── bamboohr_sdk/               # Main package
│   ├── api/                    # Auto-generated API classes
│   ├── models/                 # Auto-generated data models
│   ├── client/                 # Custom API client & auth
│   │   ├── auth/               # TokenManager, RefreshProvider
│   │   ├── middleware/         # OAuth2, RequestId middleware
│   │   └── logger/             # SecureLogger
│   ├── api_helper.py           # Retry logic & logging utilities
│   └── api_error_helper.py     # Error catalog & exception factory
├── test/                       # Auto-generated API test stubs
├── tests/                      # Custom hand-written tests
├── docs/                       # Auto-generated API documentation
├── templates-python/           # Custom openapi-generator templates
├── scripts/                    # Post-generation scripts
├── examples/                   # Usage examples
└── pyproject.toml              # Project configuration
```

## Development Setup

```bash
# Clone the repository
git clone https://github.com/BambooHR/bhr-api-python.git
cd bhr-api-python

# Create a virtual environment
python -m venv .venv
source .venv/bin/activate

# Install with dev dependencies
pip install -e ".[dev]"
```

### Linting & Formatting

```bash
# Check linting
ruff check bamboohr_sdk/ tests/

# Auto-fix linting issues
ruff check --fix bamboohr_sdk/ tests/

# Format code
ruff format bamboohr_sdk/ tests/
```

### Type Checking

```bash
mypy bamboohr_sdk/
```

### Testing

```bash
pytest
```

### Protecting Implemented Tests

The `test/` directory contains auto-generated API test stubs created by `make generate`.
These stubs are overwritten on each regeneration. Once you implement real test logic in a
test file, add it to `.openapi-generator-ignore` to prevent it from being overwritten:

```
# .openapi-generator-ignore
test/test_employees_api.py
test/test_time_tracking_api.py
```

This ensures your implemented tests survive regeneration while new API test stubs are still
generated for any newly added APIs.

## Generating the SDK

This requires access to the internal BambooHR OpenAPI spec. The path to the spec file is
specified by the `OPENAPI_SPEC_PATH` environment variable.

```bash
make generate
```

### Manual changes to the auto-generated code

If you need to make manual changes to the auto-generated code, update the corresponding template in the `templates-python` directory and run `make generate` to regenerate the SDK. We have customized several templates to add SDK-specific features.

The following templates in `templates-python/` have been modified from the OpenAPI Generator defaults:

| Template | Modifications | Rationale |
|----------|--------------|-----------|
| `api.mustache` | Custom retry logic, secure logging, request ID extraction, void endpoint handling | Production-ready API calls with automatic retries and debugging support |
| `api_client.mustache` | HTTPS enforcement, custom User-Agent header, middleware pipeline | Security (HTTPS-only) and observability (request tracing) |
| `configuration.mustache` | HTTPS URL enforcement, retry configuration, custom defaults | Prevent accidental plaintext HTTP, sane retry defaults |
| `exceptions.mustache` | Status-specific exception hierarchy, `potential_causes()`/`debugging_tips()` methods, request ID support | Developer-friendly error handling with built-in troubleshooting |
| `README.mustache` | Complete custom README with troubleshooting and manual change tracking | Developer experience and onboarding |
| `api_test.mustache` | Test stub customizations | Consistent test structure |

Nearly all files under `bamboohr_sdk/api/`, `bamboohr_sdk/models/`, `test/`, and `docs/` are generated by the `make generate` command, with the following exceptions protected via `.openapi-generator-ignore`:

| File/Directory | Purpose | Why it's protected |
|---------------|---------|-------------------|
| `bamboohr_sdk/client/` | Fluent API client, auth builder, token manager, OAuth2 middleware, secure logger | Core SDK experience — all auth, retry, and logging logic lives here |
| `bamboohr_sdk/api_helper.py` | Retry logic with exponential backoff, secure request/response logging | Heavily customized from generator default — handles retry strategy and log redaction |
| `bamboohr_sdk/api_error_helper.py` | Error catalog mapping HTTP status codes to exception classes with causes/tips | Hand-written error metadata — regenerate exception classes via `scripts/generate_exceptions.py` |
| `bamboohr_sdk/api/manual_api.py` | Hand-written API class for endpoints not covered by the OpenAPI spec | Supplements auto-generated APIs |
| `tests/` | Hand-written unit and integration tests | Protected separately from auto-generated `test/` stubs |
| `examples/` | Usage examples and getting started code | Documentation — not generated |

Custom descriptions for some API docs are added in the `scripts/post_generate.py` script, which is run as part of the `make generate` command.

*Note: regeneration will not force an overwrite of tests in the `test/` directory, unless tests are deleted first.*

### Generating Error Documentation

The error documentation is automatically generated from the error messages defined in `api_error_helper.py`. To update the documentation when error messages are added or modified, run:

```bash
make generate-error-docs
```

Note that this script will also run as part of the `make generate` command.

This will:

1. Regenerate exception classes in `bamboohr_sdk/exceptions.py`
2. Regenerate the `docs/Exceptions/Exceptions.md` file with the latest error information
3. Generate exception documentation in `docs/Exceptions/Classes/`

## Contributing

Contributions are welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.

## Data Handling

This SDK is a thin HTTP client for the BambooHR API. All data transits directly between your application and the BambooHR API over HTTPS — the SDK does not send telemetry, analytics, or data to any other destination.

- **Authentication**: API keys and OAuth tokens are sent in request headers to `https://{subdomain}.bamboohr.com`. Credentials are automatically redacted from debug log output.
- **API data**: Requests and responses may include HR data such as employee records, payroll, time off, benefits, and related information. See the [API documentation](https://documentation.bamboohr.com/docs/getting-started) for details on specific endpoints and data types.
- **Logging**: The SDK's debug logger redacts sensitive headers (Authorization, API keys) by default. No request or response bodies are logged unless you explicitly enable verbose logging in your application.

## Support

If you encounter any issues or need assistance with this SDK, please contact us through one of these channels:

- **Documentation**: Refer to the [official documentation](https://documentation.bamboohr.com/docs/getting-started)
- **Community**: Check existing issues and discussions for similar problems
- **Issue Tracker**: Submit bugs and feature requests through our [GitHub issue tracker](https://github.com/BambooHR/bhr-api-python/issues)

## About this package

This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:

- API version: `{{appVersion}}`
- Package version: `{{packageVersion}}`
- Generator version: `{{generatorVersion}}`
- Build package: `{{generatorClass}}`

## Terms

Use of the BambooHR API is subject to the [BambooHR Developer Terms of Service](https://www.bamboohr.com/legal/developer-terms-of-service).

## License

[MIT](LICENSE)