# `CorvoNfse.Transport`
[🔗](https://github.com/corvo-technology/corvo-nfse-elixir/blob/main/lib/corvo_nfse/transport.ex#L1)

HTTP plumbing shared by every resource module.

Builds the URL (`base_url <> "/" <> prefix <> path`), sets the `X-API-Key`
header, performs the request through the client's `CorvoNfse.HTTP` adapter,
decodes JSON, unwraps the Corvo response envelope and maps every failure
onto `CorvoNfse.Error`.

Nothing here raises for API, network or timeout failures: every call returns
`{:ok, data}` or `{:error, %CorvoNfse.Error{}}`. Server field names are
passed through untouched - no re-casing of the wire format.

## Envelope unwrapping

  * `:data` (default) - `{data: X}` returns `X`; anything else returns
    `nil`. A `204` or empty body returns `nil`.
  * `:none` - the parsed body as-is (used by the health endpoints).

## Pagination

`list/4` returns `{:ok, %{data: [...], pagination: map}}` where
`pagination` is the server's `%{"limit" =>, "hasMore" =>, "nextCursor" =>}`
object passed through unchanged (camelCase preserved).

# `item_mode`

```elixir
@type item_mode() :: :raw
```

# `option`

```elixir
@type option() ::
  {:json, map() | list() | nil}
  | {:raw_body, iodata() | nil}
  | {:content_type, String.t() | nil}
  | {:query, map() | keyword() | nil}
  | {:idempotency_key, String.t() | nil}
  | {:unwrap, unwrap()}
```

# `page`

```elixir
@type page() :: %{data: [term()], pagination: map() | nil}
```

A page as returned by `list/4`.

# `unwrap`

```elixir
@type unwrap() :: :data | :none
```

# `list`

```elixir
@spec list(CorvoNfse.Client.t(), String.t(), map() | keyword() | nil, item_mode()) ::
  {:ok, page()} | {:error, CorvoNfse.Error.t()}
```

Fetches a single page of a list endpoint.

Items are passed through unchanged (`item_mode` is `:raw`).

# `paginate`

```elixir
@spec paginate(CorvoNfse.Client.t(), String.t(), map() | keyword() | nil, item_mode()) ::
  {:ok, Enumerable.t()} | {:error, CorvoNfse.Error.t()}
```

Lazily walks every page of a list endpoint.

The **first page is fetched eagerly**: when it fails, `paginate/4` returns
`{:error, %CorvoNfse.Error{}}` and nothing was streamed. On success it
returns `{:ok, stream}`; the stream yields items one by one, following
`pagination.hasMore` / `pagination.nextCursor`.

If a page *after the first* fails while the stream is being consumed, the
stream raises the `%CorvoNfse.Error{}` (this is the single documented
raising site in the SDK).

# `request`

```elixir
@spec request(CorvoNfse.Client.t(), :get | :post | :patch | :delete, String.t(), [
  option()
]) ::
  {:ok, term()} | {:error, CorvoNfse.Error.t()}
```

Performs a request and unwraps the response envelope.

## Options

  * `:json` - map/list encoded as the JSON body (sets `Content-Type`).
  * `:raw_body` / `:content_type` - pre-built body, e.g. multipart.
  * `:query` - map or keyword list of query parameters; `nil` values are
    skipped.
  * `:idempotency_key` - sent as `Idempotency-Key`.
  * `:unwrap` - `:data` (default) or `:none`.

# `request_raw`

```elixir
@spec request_raw(CorvoNfse.Client.t(), :get | :post | :patch | :delete, String.t(), [
  option()
]) ::
  {:ok, map()} | {:error, CorvoNfse.Error.t()}
```

Performs a request and returns the raw body (used by the PDF/XML downloads).

Returns `{:ok, %{body: binary, mime_type: binary | nil, file_name: binary | nil}}`.

# `segment`

```elixir
@spec segment(String.t() | atom() | integer()) :: String.t()
```

Percent-encodes a path segment with `encodeURIComponent` semantics.

---

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