# `BambooHR.Client`
[🔗](https://github.com/sgerrand/ex_bamboo_hr/blob/v0.6.0/lib/bamboo_hr/client.ex#L1)

Client for interacting with the BambooHR API.

## Configuration

To use this client, you'll need information from BambooHR:
- Your company's subdomain
- An API key

Optional configuration:
- `:base_url` — override the default API base URL
- `:http_client` — swap in a custom HTTP client module
- `:timeout` — HTTP receive timeout in milliseconds (default: `15_000`)

## API versions

Every request targets BambooHR's `v1` API by default. Some endpoints (for
example the Datasets API used by `BambooHR.Datasets`) live under a
different version segment. Pass `api_version:` in the `opts` of
`get/3`, `post/3`, `put/3`, or `delete/3` to target one of those instead —
one of `"v1"` (default), `"v1_1"`, `"v1_2"`, or `"v2"`.

## Usage

    client = BambooHR.Client.new(company_domain: "your_company", api_key: "your_api_key")
    {:ok, company_info} = BambooHR.Company.get_information(client)

## Telemetry

Every request emits a `:telemetry` span under the `[:bamboo_hr, :request]`
prefix, producing three events:

  * `[:bamboo_hr, :request, :start]`
  * `[:bamboo_hr, :request, :stop]`
  * `[:bamboo_hr, :request, :exception]` (on raise)

Measurements follow `:telemetry.span/3` conventions (`:system_time`,
`:monotonic_time`, `:duration`).

Metadata always includes:

  * `:method` — `:get`, `:post`, `:put`, or `:delete`
  * `:path` — request path passed to the resource module
  * `:url` — fully-qualified request URL (no credentials)

Stop metadata additionally includes:

  * `:result` — `:ok` or `:error`
  * `:status` — HTTP status integer when the upstream returned a non-2xx
  * `:reason` — error term for transport / decoding failures

# `response`

```elixir
@type response() :: {:ok, term()} | {:error, term()}
```

Result returned by client request functions.

The `:ok` payload is whatever `Jason.decode/1` produced from the response
body — typically a map, but it may also be a list, scalar, or `nil` when the
upstream returns an empty 2xx body. Passing `raw_response: true` skips JSON
decoding (needed for binary responses like file downloads), and passing
`expose_headers: true` wraps the payload as `%{body: body, headers:
headers}` — see `BambooHR.HTTPClient`.

The `:error` payload is one of:

  * `%{status: integer(), body: binary()}` — non-2xx HTTP response
  * `%Jason.DecodeError{}` — a 2xx response whose body was not valid JSON
  * a transport exception (e.g. `%Req.TransportError{}`)

# `t`

```elixir
@type t() :: %BambooHR.Client{
  api_key: String.t(),
  base_url: String.t(),
  company_domain: String.t(),
  http_client: module(),
  timeout: non_neg_integer()
}
```

# `delete`

```elixir
@spec delete(String.t(), t(), keyword()) :: response()
```

Makes a DELETE request to the BambooHR API.

This function is meant to be used by resource modules. `opts` are forwarded
to the underlying HTTP client; keys controlled by the client itself —
`:method`, `:url`, `:headers`, `:receive_timeout` — cannot be overridden
through this argument. `opts` may also include `api_version:` — see
"API versions" above.

# `get`

```elixir
@spec get(String.t(), t(), keyword()) :: response()
```

Makes a GET request to the BambooHR API.

This function is meant to be used by resource modules. `opts` are forwarded
to the underlying HTTP client; keys controlled by the client itself —
`:method`, `:url`, `:headers`, `:receive_timeout` — cannot be overridden
through this argument. `opts` may also include `api_version:` — see
"API versions" above.

# `new`

```elixir
@spec new(Keyword.t()) :: t()
```

Creates a new client configuration.

## Options

  * `:company_domain` - Your company's subdomain
  * `:api_key` - Your API key
  * `:base_url` - Optional. Custom base URL for the API (defaults to BambooHR's standard API URL)
  * `:http_client` - Optional. Module that implements the `HTTPClient` behavior. Defaults to `BambooHR.HTTPClient.Req`.
  * `:timeout` - Optional. HTTP receive timeout in milliseconds. Defaults to `15_000`.

## Examples

    iex> client = BambooHR.Client.new(company_domain: "acme", api_key: "api_key_123")
    iex> {client.company_domain, client.base_url, client.timeout}
    {"acme", "https://api.bamboohr.com/api/gateway.php", 15_000}

    iex> client =
    ...>   BambooHR.Client.new(
    ...>     company_domain: "acme",
    ...>     api_key: "api_key_123",
    ...>     base_url: "https://custom-api.example.com",
    ...>     timeout: 30_000
    ...>   )
    iex> {client.base_url, client.timeout}
    {"https://custom-api.example.com", 30_000}

# `post`

```elixir
@spec post(String.t(), t(), keyword()) :: response()
```

Makes a POST request to the BambooHR API.

This function is meant to be used by resource modules. `opts` are forwarded
to the underlying HTTP client; keys controlled by the client itself —
`:method`, `:url`, `:headers`, `:receive_timeout` — cannot be overridden
through this argument. `opts` may also include `api_version:` — see
"API versions" above.

# `put`

```elixir
@spec put(String.t(), t(), keyword()) :: response()
```

Makes a PUT request to the BambooHR API.

This function is meant to be used by resource modules. `opts` are forwarded
to the underlying HTTP client; keys controlled by the client itself —
`:method`, `:url`, `:headers`, `:receive_timeout` — cannot be overridden
through this argument. `opts` may also include `api_version:` — see
"API versions" above.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
