# `Noizu.Slack.Request`
[🔗](https://github.com/noizu-labs-sdks/elixir-slack/blob/v0.1.0/lib/noizu/slack/request.ex#L1)

Web API request engine: builds the `Req` call, performs it with the bounded retry
policy, and decodes Slack's `{"ok": ...}` envelope.

Resource modules (`Noizu.Slack.Chat`, …) are thin wrappers over `get/4` and
`post/4`; call these directly for any Web API method this library does not wrap:

    Noizu.Slack.Request.post(client, "bookmarks.add", %{channel_id: "C1", title: "x", type: "link"})

## Results

  * `{"ok": true, ...}` ⇒ `{:ok, body}` — the decoded body with string keys. When
    Slack attaches warnings (top-level `"warning"` and/or
    `"response_metadata" => %{"warnings" => [...]}`), they are also collected under
    `body["_meta"]["warnings"]` (a de-duplicated list of strings). `"_meta"` is
    absent when there are no warnings.
  * `{"ok": false, "error": e}` ⇒ `{:error, %Error{tag: :api, reason: e}}`.
  * HTTP 429 ⇒ retried honouring `Retry-After` (seconds, clamped) up to the client's
    `:max_attempts` (default 3 total), then `{:error, %Error{tag: :rate_limited}}`.
  * HTTP 5xx / transport failures are retried only for GET requests.

## Request options (the last argument of `get/4` / `post/4`)

  * `:encoding` (`post/4` only) — `:json` (default) or `:form`. Form values that are
    maps or lists (e.g. `blocks`) are JSON-encoded, booleans become `"true"`/`"false"`.
  * `:token` — per-call token override (e.g. a user token for `search.messages`).
  * `:headers` — extra request headers.

# `result`

```elixir
@type result() :: {:ok, map()} | {:error, Noizu.Slack.Error.t()}
```

# `get`

```elixir
@spec get(Noizu.Slack.Client.t(), String.t(), map() | keyword(), keyword()) ::
  result()
```

GET `<base_url>/<method>` with query params.

# `post`

```elixir
@spec post(Noizu.Slack.Client.t(), String.t(), map() | keyword(), keyword()) ::
  result()
```

POST `<base_url>/<method>` with a JSON (default) or form body.

# `request_keys`

```elixir
@spec request_keys() :: [atom()]
```

Request-level option keys (`[:encoding, :token, :headers]`) — never sent as Slack params.

# `split_opts`

```elixir
@spec split_opts(keyword() | map()) :: {keyword(), map()}
```

Splits a resource function's `opts` into `{request_opts, slack_params}`.

# `warnings`

```elixir
@spec warnings(map()) :: [String.t()]
```

Collects Slack warnings from a decoded body (top-level `warning` + `response_metadata.warnings`).

---

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