# `PhoenixKit.API.FlowConfig`
[🔗](https://github.com/BeamLabEU/phoenix_kit/blob/v3.5.0/lib/phoenix_kit/api/flow_config.ex#L1)

Settings of the dangerous-operation flow of the machine API: when an operation needs
a confirmation, how long a code, an approval and a stored idempotent answer live.

| Setting | Default | Allowed |
|---|---|---|
| `api_confirm_batch_over` | `50` | 1 to 500 |
| `api_confirm_ttl_seconds` | `120` | 10 to 600 |
| `api_user_confirm_ttl_seconds` | `600` | 60 to 86400 |
| `api_approval_ttl_hours` | `72` | 1 to 720 |
| `api_approval_pending_max` | `20` | 1 to 1000 |
| `api_idempotency_ttl_hours` | `24` | 1 to 720 |
| `api_idempotency_lease_seconds` | `120` | 5 to 3600 |

(A module that tunes a flow threshold, such as `api_confirm_price_change_pct`, owns that setting.)

A stored value that does not parse or is below its minimum reads as the default;
one above its maximum reads as the maximum. A Settings read error reads as the
default (`PhoenixKit.API.Config.int/2`).

The same table drives the form on Settings -> API: `fields/0`, `current/0`,
`validate/1` and `save/2`. The form is all or nothing: one invalid field saves
nothing, and only the values that changed are written (each as a permanent
`setting.changed` Activity entry through `Settings.update_setting_with_module/4`).

# `approval_pending_max`

```elixir
@spec approval_pending_max() :: pos_integer()
```

Pending approvals one key may hold (`api_approval_pending_max`).

# `approval_ttl_hours`

```elixir
@spec approval_ttl_hours() :: pos_integer()
```

Hours a pending approval lives (`api_approval_ttl_hours`).

# `confirm_batch_over`

```elixir
@spec confirm_batch_over() :: pos_integer()
```

Rows above which an admin write is dangerous (`api_confirm_batch_over`).

# `confirm_ttl_seconds`

```elixir
@spec confirm_ttl_seconds() :: pos_integer()
```

Seconds a confirmation code lives (`api_confirm_ttl_seconds`, at most 600).

# `current`

```elixir
@spec current() :: %{required(String.t()) =&gt; String.t()}
```

The current value of every form field, as the text the field shows.

# `fields`

```elixir
@spec fields() :: [map()]
```

The seven fields of the form, in the order the page shows them.

# `idempotency_lease_seconds`

```elixir
@spec idempotency_lease_seconds() :: pos_integer()
```

Seconds an `in_progress` idempotency claim holds before a retry may take over.

# `idempotency_ttl_hours`

```elixir
@spec idempotency_ttl_hours() :: pos_integer()
```

Hours a stored idempotent answer lives (`api_idempotency_ttl_hours`).

# `save`

```elixir
@spec save(map(), keyword()) ::
  {:ok, [String.t()]} | {:error, [String.t()] | :save_failed}
```

Validates and writes a form. Returns the settings that changed. `opts` are the
history options of `Settings.update_setting_with_module/4` (`actor_uuid:`,
`source:`).

# `user_confirm_ttl_seconds`

```elixir
@spec user_confirm_ttl_seconds() :: pos_integer()
```

Seconds a confirmation of a person's live session lives (`api_user_confirm_ttl_seconds`,
at most a day): the person confirms in the page, which takes longer than an agent's
second call.

# `validate`

```elixir
@spec validate(map()) :: {:ok, [{String.t(), integer()}]} | {:error, [String.t()]}
```

Checks a submitted form. `{:ok, [{setting, integer}]}` when every field is a whole
number inside its range; otherwise `{:error, fields}` naming every bad field
(a missing field is bad, never the default).

---

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