# `Deputy`
[🔗](https://github.com/sgerrand/ex_deputy/blob/v0.4.0/lib/deputy.ex#L1)

Deputy is an Elixir client for the Deputy API.

## Configuration

You can configure the Deputy client with:

```elixir
client = Deputy.new(
  base_url: "https://your-subdomain.deputy.com",
  api_key: "your-api-key"
)
```

## Usage Example

```elixir
# Create a client
client = Deputy.new(
  base_url: "https://your-subdomain.deputy.com",
  api_key: "your-api-key"
)

# Get locations
{:ok, locations} = Deputy.Locations.get_locations(client)

# Error handling
case Deputy.Locations.get_location(client, 12345) do
  {:ok, location} ->
    # Process location data
    IO.inspect(location)

  {:error, %Deputy.Error.API{status: 404}} ->
    # Handle not found error
    IO.puts("Location not found")

  {:error, %Deputy.Error.HTTP{reason: reason}} ->
    # Handle HTTP error
    IO.puts("HTTP error: " <> inspect(reason))

  {:error, %Deputy.Error.RateLimitError{retry_after: seconds}} ->
    # Handle rate limit
    IO.puts("Rate limited. Try again in " <> to_string(seconds) <> " seconds")
end
```

## Telemetry

Deputy emits the following `:telemetry` events for every API request made via `Deputy.HTTPClient.Req`:

### `[:deputy, :request, :start]`

Emitted before the HTTP request is sent.

| measurements | type | description |
|---|---|---|
| `system_time` | `integer` | Current system time in native units (`System.system_time/0`) |

| metadata | type | description |
|---|---|---|
| `method` | `atom` | HTTP method (e.g. `:get`, `:post`) |
| `url` | `String.t()` | Full request URL |

### `[:deputy, :request, :stop]`

Emitted after the HTTP response is received and classified.

| measurements | type | description |
|---|---|---|
| `duration` | `integer` | Elapsed time in native units (use `System.convert_time_unit/3` to convert) |

| metadata | type | description |
|---|---|---|
| `method` | `atom` | HTTP method |
| `url` | `String.t()` | Full request URL |
| `status` | `atom | integer` | `:ok` for 2xx responses, HTTP status integer for API errors, `:error` for transport errors |

# `t`

```elixir
@type t() :: %Deputy{api_key: String.t(), base_url: String.t(), http_client: module()}
```

# `new`

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

Creates a new Deputy client with the given configuration.

## Options

* `:base_url` - Required. The base URL for the Deputy API.
* `:api_key` - Required. The API key for authentication.
* `:http_client` - Optional. Module implementing the HTTPClient behavior. Defaults to Deputy.HTTPClient.Req.

## Examples

    iex> Deputy.new(base_url: "https://your-subdomain.deputy.com", api_key: "your-api-key")
    %Deputy{base_url: "https://your-subdomain.deputy.com", api_key: "your-api-key", http_client: Deputy.HTTPClient.Req}

# `request`

```elixir
@spec request(t(), atom(), String.t(), keyword()) ::
  {:ok, map() | list()} | {:error, Deputy.Error.t()}
```

Makes a HTTP request to the Deputy API.

This is used internally by the API module functions.

## Returns

* `{:ok, response_body}` - Successful API call with response body
* `{:error, error}` - Error from an API call where `error` is one of:
  * `%Deputy.Error.API{}` - API error with details from Deputy
  * `%Deputy.Error.HTTP{}` - HTTP transport-level error
  * `%Deputy.Error.RateLimitError{}` - Rate limit exceeded
  * `%Deputy.Error.ParseError{}` - Failed to parse response
  * `%Deputy.Error.ValidationError{}` - Validation of request parameters failed

# `request!`

```elixir
@spec request!(t(), atom(), String.t(), keyword()) :: map() | list()
```

Makes a HTTP request to the Deputy API.

Raises an exception if the API call returns an error.

## Examples

    # client = Deputy.new(base_url: "https://test.deputy.com", api_key: "test-key")
    # locations = Deputy.request!(client, :get, "/api/v1/resource/Company")

---

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