# `Tink.Connectivity`
[🔗](https://github.com/iamkanishka/tink.ex/blob/v0.1.1/lib/tink/connectivity.ex#L1)

Connectivity API for checking provider and service availability.

This module provides functionality to check the connectivity status of:
- Financial institution providers
- Tink API services
- Provider credentials
- Data refresh status

## Features

- **Provider Status**: Check if providers are operational
- **Credential Health**: Monitor credential connectivity
- **Service Health**: Verify Tink API availability
- **Market Coverage**: Check provider availability by market

## Use Cases

### Check Provider Availability Before Connection

    @spec can_connect_to_provider?(String.t(), String.t()) :: boolean()

    def can_connect_to_provider?(provider_id, market) do
      case Tink.Connectivity.check_provider_status(provider_id, market) do
        {:ok, %{"status" => "ENABLED"}} ->
          {:ok, :available}

        {:ok, %{"status" => "DISABLED"}} ->
          {:error, :temporarily_unavailable}

        {:ok, %{"status" => "OBSOLETE"}} ->
          {:error, :no_longer_supported}

        {:error, error} ->
          {:error, error}
      end
    end

### Monitor Credential Connectivity

    @spec check_user_connections(Client.t()) :: {:ok, list(map())} | {:error, Error.t()}

    def check_user_connections(user_client) do
      {:ok, credentials} = Tink.Users.list_credentials(user_client)

      Enum.map(credentials["credentials"], fn cred ->
        status = check_credential_connectivity(cred)

        %{
          provider: cred["providerName"],
          status: cred["status"],
          connectivity: status,
          last_updated: cred["statusUpdated"]
        }
      end)
    end

    defp check_credential_connectivity(%{"status" => "UPDATED"}), do: :healthy
    defp check_credential_connectivity(%{"status" => "TEMPORARY_ERROR"}), do: :degraded
    defp check_credential_connectivity(%{"status" => "AUTHENTICATION_ERROR"}), do: :auth_failed
    defp check_credential_connectivity(%{"status" => "PERMANENT_ERROR"}), do: :failed
    defp check_credential_connectivity(_), do: :unknown

### Provider Health Dashboard

    @spec get_provider_health_by_market(String.t()) :: {:ok, map()} | {:error, Error.t()}

    def get_provider_health_by_market(market) do
      {:ok, providers} = Tink.Connectivity.list_providers_by_market(market)

      providers["providers"]
      |> Enum.group_by(& &1["status"])
      |> Enum.map(fn {status, providers} ->
        {status, %{
          count: length(providers),
          providers: Enum.map(providers, & &1["name"])
        }}
      end)
      |> Map.new()
    end

## Provider Status Types

- `ENABLED` - Provider is operational
- `DISABLED` - Temporarily unavailable
- `OBSOLETE` - No longer supported
- `UNKNOWN` - Status cannot be determined

## Credential Status Types

- `CREATED` - Just created, not yet authenticated
- `AUTHENTICATING` - Authentication in progress
- `UPDATING` - Refreshing data
- `UPDATED` - Successfully updated
- `TEMPORARY_ERROR` - Temporary connectivity issue
- `AUTHENTICATION_ERROR` - Invalid credentials
- `PERMANENT_ERROR` - Permanent failure
- `AWAITING_MOBILE_BANKID_AUTHENTICATION` - Waiting for BankID
- `AWAITING_THIRD_PARTY_APP_AUTHENTICATION` - Waiting for external app

## Links

- [Providers API Documentation](https://docs.tink.com/api/providers)
- [Credentials Status Documentation](https://docs.tink.com/api/credentials)

# `check_api_health`

```elixir
@spec check_api_health() :: {:ok, :healthy} | {:error, binary()}
```

Checks if the Tink API is accessible.

Performs a basic connectivity check to verify the API is reachable.

## Returns

  * `{:ok, :healthy}` - API is accessible
  * `{:error, reason}` - API is not accessible

## Examples

    case Tink.Connectivity.check_api_health() do
      {:ok, :healthy} ->
        Logger.info("Tink API is operational")
        :ok

      {:error, reason} ->
        Logger.error("Tink API unreachable: #{inspect(reason)}")
        {:error, :api_unavailable}
    end

## Use Cases

- **Health Checks**: Verify service availability
- **Monitoring**: Track API uptime
- **Diagnostics**: Debug connectivity issues

# `check_credential_connectivity`

```elixir
@spec check_credential_connectivity(
  Tink.Client.t(),
  keyword()
) :: {:ok, map()} | {:error, Tink.Error.t()}
```

Checks the connectivity status of user credentials.

## Parameters

  * `client` - Tink client with user access token and `credentials:read` scope
  * `opts` - Options:
    * `:include_healthy` - Include healthy credentials (default: true)
    * `:include_errors` - Include error credentials (default: true)

## Returns

  * `{:ok, connectivity_report}` - Credential connectivity status
  * `{:error, error}` - If the request fails

## Examples

    user_client = Tink.client(access_token: user_access_token)

    {:ok, report} = Tink.Connectivity.check_credential_connectivity(user_client)
    #=> {:ok, %{
    #     "total" => 3,
    #     "healthy" => 2,
    #     "degraded" => 1,
    #     "failed" => 0,
    #     "credentials" => [
    #       %{
    #         "credentialId" => "cred_123",
    #         "provider" => "Example Bank",
    #         "status" => "UPDATED",
    #         "connectivity" => "healthy",
    #         "lastUpdated" => "2024-01-15T10:00:00Z"
    #       },
    #       %{
    #         "credentialId" => "cred_456",
    #         "provider" => "Another Bank",
    #         "status" => "TEMPORARY_ERROR",
    #         "connectivity" => "degraded",
    #         "lastUpdated" => "2024-01-15T09:00:00Z",
    #         "errorMessage" => "Temporary connection issue"
    #       }
    #     ]
    #   }}

    # Check only problematic credentials
    {:ok, issues} = Tink.Connectivity.check_credential_connectivity(
      user_client,
      include_healthy: false
    )

## Connectivity Classifications

- **healthy**: Credential is working normally
- **degraded**: Temporary issues but may recover
- **auth_failed**: Authentication failed, requires user action
- **failed**: Permanent failure
- **authenticating**: Authentication in progress
- **updating**: Data refresh in progress

## Required Scope

`credentials:read`

# `check_provider_status`

```elixir
@spec check_provider_status(String.t(), String.t() | nil) ::
  {:ok, map()} | {:error, Tink.Error.t()}
```

Checks the status of a specific provider.

## Parameters

  * `provider_id` - Provider ID
  * `market` - Market code (optional, for verification)

## Returns

  * `{:ok, status}` - Provider status information
  * `{:error, error}` - If the request fails

## Examples

    {:ok, status} = Tink.Connectivity.check_provider_status("provider_123", "GB")
    #=> {:ok, %{
    #     "id" => "provider_123",
    #     "name" => "Example Bank",
    #     "status" => "ENABLED",
    #     "statusMessage" => nil,
    #     "lastChecked" => "2024-01-15T10:00:00Z"
    #   }}

    # Check if provider is operational
    case status do
      {:ok, %{"status" => "ENABLED"}} ->
        :operational

      {:ok, %{"status" => "DISABLED"}} ->
        :temporarily_unavailable

      {:ok, %{"status" => "OBSOLETE"}} ->
        :no_longer_supported
    end

## Status Values

- `ENABLED` - Provider is working normally
- `DISABLED` - Provider is temporarily unavailable
- `OBSOLETE` - Provider is no longer supported

## No Authentication Required

# `get_credential_connectivity`

```elixir
@spec get_credential_connectivity(Tink.Client.t(), String.t()) ::
  {:ok, map()} | {:error, Tink.Error.t()}
```

Gets detailed connectivity information for a specific credential.

## Parameters

  * `client` - Tink client with user access token and `credentials:read` scope
  * `credential_id` - Credential ID

## Returns

  * `{:ok, connectivity_info}` - Detailed connectivity information
  * `{:error, error}` - If the request fails

## Examples

    user_client = Tink.client(access_token: user_access_token)

    {:ok, info} = Tink.Connectivity.get_credential_connectivity(
      user_client,
      "cred_123"
    )
    #=> {:ok, %{
    #     "credentialId" => "cred_123",
    #     "provider" => "Example Bank",
    #     "providerId" => "provider_123",
    #     "status" => "UPDATED",
    #     "connectivity" => "healthy",
    #     "lastUpdated" => "2024-01-15T10:00:00Z",
    #     "lastSuccess" => "2024-01-15T10:00:00Z",
    #     "canRefresh" => true
    #   }}

## Required Scope

`credentials:read`

# `list_providers_by_market`

```elixir
@spec list_providers_by_market(String.t()) :: {:ok, map()} | {:error, Tink.Error.t()}
```

Lists providers by market (unauthenticated).

This endpoint can be called without authentication to check provider
availability in a specific market.

## Parameters

  * `market` - Market code (e.g., "GB", "SE", "DE")

## Returns

  * `{:ok, providers}` - List of providers for the market
  * `{:error, error}` - If the request fails

## Examples

    # Check UK providers (no auth required)
    {:ok, providers} = Tink.Connectivity.list_providers_by_market("GB")
    #=> {:ok, %{
    #     "providers" => [
    #       %{
    #         "id" => "provider_123",
    #         "name" => "Example Bank",
    #         "displayName" => "Example Bank",
    #         "status" => "ENABLED",
    #         "type" => "BANK",
    #         "financialInstitutionId" => "fi_example_gb",
    #         "capabilities" => ["TRANSFERS", "ACCOUNT_VERIFICATION"]
    #       }
    #     ]
    #   }}

    # Check German providers
    {:ok, de_providers} = Tink.Connectivity.list_providers_by_market("DE")

## Provider Fields

- **id**: Provider identifier
- **name**: Provider name
- **displayName**: Display name
- **status**: ENABLED, DISABLED, or OBSOLETE
- **type**: BANK, CREDIT_CARD, BROKER, OTHER
- **capabilities**: Supported features

## No Authentication Required

This endpoint is publicly accessible and does not require authentication.

# `list_providers_by_market_authenticated`

```elixir
@spec list_providers_by_market_authenticated(Tink.Client.t(), String.t()) ::
  {:ok, map()} | {:error, Tink.Error.t()}
```

Lists providers by market (authenticated).

Authenticated version that may return additional provider details.

## Parameters

  * `client` - Tink client with `providers:read` scope
  * `market` - Market code (e.g., "GB", "SE", "DE")

## Returns

  * `{:ok, providers}` - List of providers for the market
  * `{:error, error}` - If the request fails

## Examples

    client = Tink.client(scope: "providers:read")

    {:ok, providers} = Tink.Connectivity.list_providers_by_market_authenticated(
      client,
      "GB"
    )

## Required Scope

`providers:read`

# `provider_operational?`

```elixir
@spec provider_operational?(String.t(), String.t() | nil) :: boolean()
```

Checks if a provider is operational (enabled).

## Parameters

  * `provider_id` - Provider ID
  * `market` - Market code (optional)

## Returns

  * `true` if provider is enabled
  * `false` if provider is disabled or obsolete

## Examples

    if Tink.Connectivity.provider_operational?("provider_123", "GB") do
      # Proceed with connection
      initiate_connection(provider_id)
    else
      # Show error message
      show_provider_unavailable_message()
    end

---

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