# `Emaki`
[🔗](https://github.com/hanshs474/emaki-ex/blob/main/lib/emaki.ex#L1)

Official Elixir SDK for [emaki](https://emaki.ai): generate Seedance 2.5 and
Seedance 2.0 clips, and images, with the API key of your emaki account.

    {:ok, url} = Emaki.generate_video("a paper lantern drifting down a night river")
    {:ok, img} = Emaki.generate_image("a ramen stall in the rain, neon reflections")
    {:ok, left} = Emaki.credits()

Pass `api_key:` or set `EMAKI_API_KEY`; create a key at
https://emaki.ai/settings/apikeys.

Failures are `{:error, reason, message}` where `reason` is `:auth`, `:quota`,
`:plan`, `:busy`, `:rejected`, `:validation`, `:failed`, `:timeout` or `:other`.

Uses only `:httpc` from OTP and the standard `JSON` module; no dependencies.

# `error`

```elixir
@type error() :: {:error, reason(), String.t()}
```

# `reason`

```elixir
@type reason() ::
  :auth
  | :quota
  | :plan
  | :busy
  | :rejected
  | :validation
  | :failed
  | :timeout
  | :other
```

# `classify`

```elixir
@spec classify(integer(), term()) :: reason()
```

Maps an HTTP status and error body to the reason that says what to do next.

# `credits`

```elixir
@spec credits(keyword()) :: {:ok, integer()} | error()
```

Remaining credits on the account. Free to call.

# `generate_image`

```elixir
@spec generate_image(String.t(), map(), keyword()) :: {:ok, String.t()} | error()
```

Generates one image and returns its URL. Default model `"nano_banana_2_lite"`.
Same `params` and options as `generate_video/3`.

# `generate_video`

```elixir
@spec generate_video(String.t(), map(), keyword()) :: {:ok, String.t()} | error()
```

Generates one clip and returns the URL of the finished MP4.

`params` is passed through as the request's `parameters`, e.g.
`%{"duration" => 8, "resolution" => "720p", "aspect_ratio" => "9:16", "image" => url}`.

Options: `:model` (default `"seedance_2_5"`), `:api_key`, `:poll_ms` (5000),
`:timeout_ms` (15 minutes), `:base_url`.

# `status`

```elixir
@spec status(String.t(), keyword()) :: {:ok, map()} | error()
```

Returns the run's record: a map with `"id"`, `"status"` (`"generating"`,
`"completed"` or `"failed"`), `"videoUrl"` (images too) and `"failureCode"`.

# `submit`

```elixir
@spec submit(String.t(), String.t(), map(), keyword()) :: {:ok, String.t()} | error()
```

Submits a run and returns its id without waiting.

# `wait`

```elixir
@spec wait(String.t(), keyword()) :: {:ok, String.t()} | error()
```

Polls a submitted run until it completes, fails or the deadline passes.

---

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