# `PhoenixKitAI.ManualPrice`
[🔗](https://github.com/BeamLabEU/phoenix_kit_ai/blob/v0.26.1/lib/phoenix_kit_ai/manual_price.ex#L1)

A price entered by hand on an endpoint whose provider gives none (Z.ai,
say): `provider_settings["pricing"]` — `%{"model" => id, "input" => "0.60",
"output" => "2.2"}`, US dollars per 1M input and output tokens as decimal
strings (a JSON number would read back as a float), both required, for the
model it names. The
endpoint's changeset stamps the model when none is given and drops the
price when the endpoint's model changes (like a capability declaration).

A call whose provider reports no `usage.cost` and whose model no catalogue
prices gets its `cost` from it (`cost/3`), and its
usage row says `cost_source: "manual"` (`PhoenixKitAI.CallCost` keeps the
order of the sources). Money limits and the daily budget then count the
call like any other. That is chat, embeddings and the vision verbs
(`describe_image/3`, `extract_text/3`, `compare_images/4`), for a call
sent to the price's model. Making or editing images (`generate_image/3`,
`edit_image/4`, `process_image/4`) is priced per image or per call, not
per token, so a manual price does not apply there: those calls keep only
the provider's own cost.

A price whose halves are integers is in the shape the released versions
stored (millionths of a dollar); `legacy?/1` says so, the module's migration
chain converts it, and a call on such an endpoint is refused until it has.

# `t`

```elixir
@type t() :: %{optional(String.t()) =&gt; Decimal.t()}
```

# `cost`

```elixir
@spec cost(t() | nil, non_neg_integer(), non_neg_integer()) :: Decimal.t() | nil
```

What a call costs at a price per 1M tokens, in dollars, not rounded:
`(input_tokens × input + output_tokens × output) / 1_000_000`. nil when a
price the tokens need is missing (no price at all, or an output price for a
call with output).

# `get`

```elixir
@spec get(PhoenixKitAI.Endpoint.t() | map() | nil) :: t() | nil
```

The endpoint's manual price for its own model, `%{"input" => dollars,
"output" => dollars}` per 1M tokens as `Decimal`s, or nil — when it has none,
the stored price names another model, lacks a half, or is in the legacy shape
(`legacy?/1`).

# `legacy?`

```elixir
@spec legacy?(PhoenixKitAI.Endpoint.t() | map() | nil) :: boolean()
```

Whether the endpoint's stored price is in the released versions' shape:
integer millionths of a dollar per 1M tokens.

# `max`

```elixir
@spec max() :: Decimal.t()
```

The highest price per 1M tokens, in dollars ($10 000).

# `validate`

```elixir
@spec validate(term()) :: :ok | :error
```

Checks a stored price: `"input"` and `"output"` both, dollar strings from 0
to `max/0`, and an optional `"model"` (the model it prices). `:ok` or
`:error`.

---

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