Skip to content Documentation index for agents (llms.txt)
Glotto Beta
Get started

Elixir

The Elixir SDK is an idiomatic Hex package emitted from the same GlottoIR as every other target. It is functional and module-first: the public package facade builds the client with Petstore.new/2, and each resource gets its own module whose functions take that struct as their first argument — Petstore.Pets.list_pets(client). It is built on Req.

Quickstart

def deps do
  [
    {:petstore, "~> 1.0"}
  ]
end
client =
  Petstore.new("https://api.petstore.example",
    token: System.get_env("PETSTORE_TOKEN")
  )

# calls return {:ok, _} / {:error, %Petstore.ApiError{}} tuples
{:ok, pet} = Petstore.Pets.create_pet(client, %{name: "Rex"})

# paginated functions return a lazy Stream
Petstore.Pets.list_pets(client)
|> Enum.each(&IO.puts(&1.name))

Typed models

Each GlottoIR model becomes a struct module with from_map/to_map; functions decode and return the typed response and accept a typed request body. Discriminated unions resolve to the right variant.

Typed errors

Functions return a %Glotto.ApiError{} struct carrying the parsed error body, with Glotto.ApiError.kind/1 mapping the status to a documented atom so callers case on :not_found rather than matching status codes. See Errors.

Pagination

Paginated list functions return a lazy Stream that walks every page as you enumerate, advancing the cursor for you. Manual-page companions expose typed items, the full response, and explicit next-page navigation. See Pagination.

Retries & backoff

Transient failures (5xx, 429, transport errors) retry with exponential backoff and jitter, configurable per client and per call. A trailing keyword list accepts request headers, timeout, retry count, idempotency and applicable extra query/body values; explicit values override configured method/resource defaults. Terminating the request-owning Task cancels its request and retry wait. See Retries & timeouts.

SSE streaming

Server-sent-event endpoints return a Stream of typed events decoded from the text/event-stream framing. See Streaming and Authentication.

Unknown response fields

Your API can add a response field without it being a breaking change — but a generated struct has only the keys it declares, and its from_map/1 factory reads only those. The generated models keep it instead: a field the SDK wasn’t generated from is retained on decode, readable through an accessor, and written back out when the model is re-serialized.

{:ok, pet} = Glotto.Pets.create_pet(client, body)

# A field your API started returning after this SDK was generated.
species = Glotto.Pet.extra_fields(pet)["species"]

# Re-encoding preserves it — a read-modify-write never silently drops it.
json = pet |> Glotto.Pet.to_map() |> Jason.encode!()

extra_fields/1 returns a plain map, so nested objects and lists survive intact, and retention is recursive.

The struct key defaults to an empty map, so %Glotto.Pet{id: "p1"} still builds.

The retained fields are read-only by design. To send a field your spec doesn’t model yet, use the per-call extra-body escape hatch rather than writing to the retained bag.

File uploads

multipart/form-data operations build the multipart body from their fields for you; an application/octet-stream operation takes a positional body (a binary) sent raw with the right content-type.

Binary downloads

Declared binary responses return an owned Glotto.BinaryDownload with status, headers, media type, content length, filename and request ID. Consume its chunks/1 stream, call read_all/2 with a required max_bytes bound, or pipe/2 to a binary IO device or callback. Limits count delivered bytes, including decoded gzip bytes. Close an abandoned response explicitly; terminating its original request Task also closes it. The request timeout covers the first byte or EOF, and no retry occurs after delivery. See File transfers.