# `PhoenixKit.Integrations.Providers`
[🔗](https://github.com/BeamLabEU/phoenix_kit/blob/v2.15.1/lib/phoenix_kit/integrations/providers.ex#L1)

Registry of known integration providers.

Each provider definition describes how to connect to an external service:
what auth type it uses, what fields the admin needs to fill in, and
how to validate the connection.

Providers are defined in code, not in the database. New providers are
added here as needed. External modules can also contribute providers
via the `integration_providers/0` callback on `PhoenixKit.Module`.

# `auth_type`

```elixir
@type auth_type() :: :oauth2 | :api_key | :key_secret | :bot_token | :credentials
```

# `provider`

```elixir
@type provider() :: %{
  :key =&gt; String.t(),
  :name =&gt; String.t(),
  :description =&gt; String.t(),
  :icon =&gt; String.t(),
  :auth_type =&gt; auth_type(),
  :oauth_config =&gt; map() | nil,
  :setup_fields =&gt; [setup_field()],
  :capabilities =&gt; [atom()],
  optional(:base_url) =&gt; String.t(),
  optional(:validation) =&gt; map(),
  optional(:instructions) =&gt; [map()],
  optional(:scopes) =&gt; [:system | :personal]
}
```

# `setup_field`

```elixir
@type setup_field() :: %{
  key: String.t(),
  label: String.t(),
  type: :text | :password | :textarea | :number | :select,
  required: boolean(),
  placeholder: String.t(),
  help: String.t() | nil,
  options: [%{value: String.t(), label: String.t()}] | nil
}
```

# `all`

```elixir
@spec all() :: [provider()]
```

Returns all known providers, including those contributed by external modules.

Results are cached in `persistent_term` after the first call.
`PhoenixKit.ModuleRegistry` calls `clear_cache/0` for you whenever the
registered-module set changes (`register/1`, `unregister/1`, `rescan/0`),
so a module discovered after the cache was warmed still contributes its
providers. Call it yourself only when something outside the registry
changes what `integration_providers/0` would return.

# `base_url`

```elixir
@spec base_url(String.t()) :: String.t() | nil
```

Returns the API base URL declared by a provider, or `nil` if it has none.

Accepts the same plain or named keys as `get/1` (`"openai"` /
`"openai:work"`). Only providers with a primary REST API (currently the
`:ai_completions` providers) declare a `:base_url`; everything else is `nil`.

# `clear_cache`

```elixir
@spec clear_cache() :: :ok
```

Clears the cached provider list and used-by map.

Call this when modules are added or removed at runtime so the next
call to `all/0` or `used_by_modules/0` recomputes from the module registry.

# `for_scope`

```elixir
@spec for_scope(:system | :personal) :: [provider()]
```

All providers usable under `scope` (`:system` or `:personal`).

Drives the provider grid on each page — the system setup lists
`for_scope(:system)`, the personal setup lists `for_scope(:personal)`.

# `get`

```elixir
@spec get(String.t()) :: provider() | nil
```

Look up a single provider by key.

Accepts both plain keys (`"google"`) and named keys (`"google:personal"`) —
the name is stripped before lookup since provider definitions are per-type.

# `personal_offered`

```elixir
@spec personal_offered() :: [provider()]
```

Providers offered on the personal integrations "add" picker — the subset of
`for_scope(:personal)` currently exposed (see `@personal_offered`), returned
in that list's order.

# `scopes_of`

```elixir
@spec scopes_of(String.t() | provider()) :: [:system | :personal]
```

The scopes a provider may hold a connection under. Defaults to `[:system]`
when the provider omits `:scopes` (so an external module's provider never
lands on the personal page unless it opts in).

# `used_by_modules`

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

Returns a map of provider_key => [module_name] showing which modules use each integration.

# `with_capability`

```elixir
@spec with_capability(atom()) :: [provider()]
```

Returns all providers (built-in + external) that declare the given capability.

Lets consumers discover providers by what they can do rather than by a
hardcoded list. For example, an AI module can render its provider picker
from `with_capability(:ai_completions)`, so adding a new chat provider to
the registry surfaces it automatically.

Order follows `all/0` (built-ins first, in definition order).

---

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