# This file was auto-generated by Fern from our API Definition.

import datetime as dt
import typing

from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
from ..core.request_options import RequestOptions
from ..types.auth_type import AuthType
from ..types.bulk_export_connections_response import BulkExportConnectionsResponse
from ..types.bulk_import_connections_response import BulkImportConnectionsResponse
from ..types.bulk_ops_response import BulkOpsResponse
from ..types.connection_recipe import ConnectionRecipe
from ..types.demo_connection_status import DemoConnectionStatus
from ..types.demo_providers import DemoProviders
from ..types.link_token_exchange_response import LinkTokenExchangeResponse
from ..types.manual_providers import ManualProviders
from ..types.o_auth_providers import OAuthProviders
from ..types.password_providers import PasswordProviders
from ..types.provider_link_response import ProviderLinkResponse
from ..types.providers import Providers
from ..types.region import Region
from ..types.source import Source
from ..types.source_link import SourceLink
from ..types.vital_token_created_response import VitalTokenCreatedResponse
from .raw_client import AsyncRawLinkClient, RawLinkClient
from .types.bulk_export_link_request_team_id import BulkExportLinkRequestTeamId
from .types.bulk_import_link_request_team_id import BulkImportLinkRequestTeamId
from .types.bulk_pause_link_request_team_id import BulkPauseLinkRequestTeamId
from .types.bulk_trigger_historical_pull_link_request_team_id import BulkTriggerHistoricalPullLinkRequestTeamId
from .types.list_bulk_ops_link_request_team_id import ListBulkOpsLinkRequestTeamId

# this is used as the default value for optional parameters
OMIT = typing.cast(typing.Any, ...)


class LinkClient:
    def __init__(self, *, client_wrapper: SyncClientWrapper):
        self._raw_client = RawLinkClient(client_wrapper=client_wrapper)

    @property
    def with_raw_response(self) -> RawLinkClient:
        """
        Retrieves a raw implementation of this client that returns raw responses.

        Returns
        -------
        RawLinkClient
        """
        return self._raw_client

    def list_bulk_ops(
        self,
        *,
        next_cursor: typing.Optional[str] = None,
        page_size: typing.Optional[int] = None,
        team_id: typing.Optional[ListBulkOpsLinkRequestTeamId] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> BulkOpsResponse:
        """
        Parameters
        ----------
        next_cursor : typing.Optional[str]

        page_size : typing.Optional[int]

        team_id : typing.Optional[ListBulkOpsLinkRequestTeamId]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        BulkOpsResponse
            Successful Response

        Examples
        --------
        from vital import Vital
        client = Vital(api_key="YOUR_API_KEY", )
        client.link.list_bulk_ops()
        """
        _response = self._raw_client.list_bulk_ops(
            next_cursor=next_cursor, page_size=page_size, team_id=team_id, request_options=request_options
        )
        return _response.data

    def bulk_import(
        self,
        *,
        provider: OAuthProviders,
        connections: typing.Sequence[ConnectionRecipe],
        team_id: typing.Optional[BulkImportLinkRequestTeamId] = None,
        wait_for_completion: typing.Optional[bool] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> BulkImportConnectionsResponse:
        """
        Parameters
        ----------
        provider : OAuthProviders

        connections : typing.Sequence[ConnectionRecipe]

        team_id : typing.Optional[BulkImportLinkRequestTeamId]

        wait_for_completion : typing.Optional[bool]

            Whether or not the endpoint should wait for the Bulk Op to complete before responding.

            When `wait_for_completion` is enabled, the endpoint may respond 200 OK if the Bulk Op takes less than 20 seconds to complete.

            Otherwise, the endpoint always responds with 202 Created once the submitted data have been enqueued successfully. You can use
            the [List Bulk Ops](https://docs.tryvital.io/api-reference/link/list-bulk-ops) endpoint to inspect the progress of the Bulk Op.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        BulkImportConnectionsResponse
            Successful Response

        Examples
        --------
        from vital import Vital
        from vital import OAuthProviders
        from vital import ConnectionRecipe
        client = Vital(api_key="YOUR_API_KEY", )
        client.link.bulk_import(provider=OAuthProviders.OURA, connections=[ConnectionRecipe(user_id='user_id', access_token='access_token', refresh_token='refresh_token', provider_id='provider_id', expires_at=1, )], )
        """
        _response = self._raw_client.bulk_import(
            provider=provider,
            connections=connections,
            team_id=team_id,
            wait_for_completion=wait_for_completion,
            request_options=request_options,
        )
        return _response.data

    def bulk_trigger_historical_pull(
        self,
        *,
        user_ids: typing.Sequence[str],
        provider: OAuthProviders,
        team_id: typing.Optional[BulkTriggerHistoricalPullLinkRequestTeamId] = None,
        wait_for_completion: typing.Optional[bool] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> typing.Optional[typing.Any]:
        """
        Parameters
        ----------
        user_ids : typing.Sequence[str]

        provider : OAuthProviders

        team_id : typing.Optional[BulkTriggerHistoricalPullLinkRequestTeamId]

        wait_for_completion : typing.Optional[bool]

            Whether or not the endpoint should wait for the Bulk Op to complete before responding.

            When `wait_for_completion` is enabled, the endpoint may respond 200 OK if the Bulk Op takes less than 20 seconds to complete.

            Otherwise, the endpoint always responds with 202 Created once the submitted data have been enqueued successfully. You can use
            the [List Bulk Ops](https://docs.tryvital.io/api-reference/link/list-bulk-ops) endpoint to inspect the progress of the Bulk Op.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        typing.Optional[typing.Any]
            Successful Response

        Examples
        --------
        from vital import Vital
        from vital import OAuthProviders
        client = Vital(api_key="YOUR_API_KEY", )
        client.link.bulk_trigger_historical_pull(user_ids=['user_ids'], provider=OAuthProviders.OURA, )
        """
        _response = self._raw_client.bulk_trigger_historical_pull(
            user_ids=user_ids,
            provider=provider,
            team_id=team_id,
            wait_for_completion=wait_for_completion,
            request_options=request_options,
        )
        return _response.data

    def bulk_export(
        self,
        *,
        provider: OAuthProviders,
        team_id: typing.Optional[BulkExportLinkRequestTeamId] = None,
        user_ids: typing.Optional[typing.Sequence[str]] = OMIT,
        next_token: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> BulkExportConnectionsResponse:
        """
        Parameters
        ----------
        provider : OAuthProviders

        team_id : typing.Optional[BulkExportLinkRequestTeamId]

        user_ids : typing.Optional[typing.Sequence[str]]

        next_token : typing.Optional[str]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        BulkExportConnectionsResponse
            Successful Response

        Examples
        --------
        from vital import Vital
        from vital import OAuthProviders
        client = Vital(api_key="YOUR_API_KEY", )
        client.link.bulk_export(provider=OAuthProviders.OURA, )
        """
        _response = self._raw_client.bulk_export(
            provider=provider,
            team_id=team_id,
            user_ids=user_ids,
            next_token=next_token,
            request_options=request_options,
        )
        return _response.data

    def bulk_pause(
        self,
        *,
        user_ids: typing.Sequence[str],
        provider: OAuthProviders,
        team_id: typing.Optional[BulkPauseLinkRequestTeamId] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> typing.Optional[typing.Any]:
        """
        Parameters
        ----------
        user_ids : typing.Sequence[str]

        provider : OAuthProviders

        team_id : typing.Optional[BulkPauseLinkRequestTeamId]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        typing.Optional[typing.Any]
            Successful Response

        Examples
        --------
        from vital import Vital
        from vital import OAuthProviders
        client = Vital(api_key="YOUR_API_KEY", )
        client.link.bulk_pause(user_ids=['user_ids'], provider=OAuthProviders.OURA, )
        """
        _response = self._raw_client.bulk_pause(
            user_ids=user_ids, provider=provider, team_id=team_id, request_options=request_options
        )
        return _response.data

    def token(
        self,
        *,
        user_id: str,
        provider: typing.Optional[Providers] = OMIT,
        redirect_url: typing.Optional[str] = OMIT,
        filter_on_providers: typing.Optional[typing.Sequence[Providers]] = OMIT,
        on_error: typing.Optional[typing.Literal["redirect"]] = OMIT,
        on_close: typing.Optional[typing.Literal["redirect"]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> LinkTokenExchangeResponse:
        """
        Endpoint to generate a user link token, to be used throughout the vital
        link process. The vital link token is a one time use token, that
        expires after 10 minutes. If you would like vital-link widget to launch
        with a specific provider, pass in a provider in the body. If you would
        like to redirect to a custom url after successful or error connection,
        pass in your own custom redirect_url parameter.

        Parameters
        ----------
        user_id : str
            User id returned by vital create user request. This id should be stored in your database against the user and used for all interactions with the vital api.

        provider : typing.Optional[Providers]

        redirect_url : typing.Optional[str]

        filter_on_providers : typing.Optional[typing.Sequence[Providers]]
            An allowlist of providers dictating what Vital Link Widget should show to the end user.
            If unspecified, all linkable providers are shown.

            This has no effect on programmatic Vital Link API usage.

        on_error : typing.Optional[typing.Literal["redirect"]]
            By default, Vital Link Widget input forms for password and email providers have in-built error handling.

            Specifying `on_error=redirect` disables this Vital Link Widget UI behaviour — it would
            instead redirect to your `redirect_url`, with Link Error parameters injected.

            This has no effect on OAuth providers — they always redirect to your `redirect_url`. This also has
            no effect on programmatic Vital Link API usage.

        on_close : typing.Optional[typing.Literal["redirect"]]
            By default, Vital Link Widget closes the window or tab when the user taps the Close button.

            Specifying `on_close=redirect` would change the Close button behaviour to redirect to your `redirect_url`
            with the `user_cancelled` error specified.

            This has no effect on programmatic Vital Link API usage.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        LinkTokenExchangeResponse
            Successful Response

        Examples
        --------
        from vital import Vital
        client = Vital(api_key="YOUR_API_KEY", )
        client.link.token(user_id='user_id', )
        """
        _response = self._raw_client.token(
            user_id=user_id,
            provider=provider,
            redirect_url=redirect_url,
            filter_on_providers=filter_on_providers,
            on_error=on_error,
            on_close=on_close,
            request_options=request_options,
        )
        return _response.data

    def is_token_valid(
        self, *, token: str, request_options: typing.Optional[RequestOptions] = None
    ) -> typing.Dict[str, typing.Optional[typing.Any]]:
        """
        Parameters
        ----------
        token : str

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        typing.Dict[str, typing.Optional[typing.Any]]
            Successful Response

        Examples
        --------
        from vital import Vital
        client = Vital(api_key="YOUR_API_KEY", )
        client.link.is_token_valid(token='token', )
        """
        _response = self._raw_client.is_token_valid(token=token, request_options=request_options)
        return _response.data

    def code_create(
        self,
        *,
        user_id: str,
        expires_at: typing.Optional[dt.datetime] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> VitalTokenCreatedResponse:
        """
        Generate a token to invite a user of Vital mobile app to your team

        Parameters
        ----------
        user_id : str

        expires_at : typing.Optional[dt.datetime]
            When the link code should expire. Defaults to server time plus 1 hour.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        VitalTokenCreatedResponse
            Successful Response

        Examples
        --------
        from vital import Vital
        client = Vital(api_key="YOUR_API_KEY", )
        client.link.code_create(user_id='user_id', )
        """
        _response = self._raw_client.code_create(
            user_id=user_id, expires_at=expires_at, request_options=request_options
        )
        return _response.data

    def start_connect(
        self, *, link_token: str, provider: Providers, request_options: typing.Optional[RequestOptions] = None
    ) -> typing.Dict[str, typing.Optional[typing.Any]]:
        """
        REQUEST_SOURCE: VITAL-LINK
        Start link token process

        Parameters
        ----------
        link_token : str

        provider : Providers

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        typing.Dict[str, typing.Optional[typing.Any]]
            Successful Response

        Examples
        --------
        from vital import Vital
        from vital import Providers
        client = Vital(api_key="YOUR_API_KEY", )
        client.link.start_connect(link_token='link_token', provider=Providers.OURA, )
        """
        _response = self._raw_client.start_connect(
            link_token=link_token, provider=provider, request_options=request_options
        )
        return _response.data

    def token_state(
        self, *, vital_link_token: typing.Optional[str] = None, request_options: typing.Optional[RequestOptions] = None
    ) -> typing.Dict[str, typing.Optional[typing.Any]]:
        """
        REQUEST_SOURCE: VITAL-LINK
        Check link token state - can be hit continuously used as heartbeat

        Parameters
        ----------
        vital_link_token : typing.Optional[str]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        typing.Dict[str, typing.Optional[typing.Any]]
            Successful Response

        Examples
        --------
        from vital import Vital
        client = Vital(api_key="YOUR_API_KEY", )
        client.link.token_state()
        """
        _response = self._raw_client.token_state(vital_link_token=vital_link_token, request_options=request_options)
        return _response.data

    def email_auth(
        self,
        *,
        email: str,
        provider: Providers,
        auth_type: AuthType,
        vital_link_token: typing.Optional[str] = None,
        region: typing.Optional[Region] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> typing.Optional[typing.Any]:
        """
        Deprecated. Use `POST /v2/link/provider/email/{provider}` instead.

        Parameters
        ----------
        email : str

        provider : Providers

        auth_type : AuthType

        vital_link_token : typing.Optional[str]

        region : typing.Optional[Region]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        typing.Optional[typing.Any]
            Successful Response

        Examples
        --------
        from vital import Vital
        from vital import Providers
        from vital import AuthType
        client = Vital(api_key="YOUR_API_KEY", )
        client.link.email_auth(email='email', provider=Providers.OURA, auth_type=AuthType.PASSWORD, )
        """
        _response = self._raw_client.email_auth(
            email=email,
            provider=provider,
            auth_type=auth_type,
            vital_link_token=vital_link_token,
            region=region,
            request_options=request_options,
        )
        return _response.data

    def password_auth(
        self,
        *,
        username: str,
        password: str,
        provider: Providers,
        auth_type: AuthType,
        vital_link_token: typing.Optional[str] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> typing.Optional[typing.Any]:
        """
        Deprecated. Use `POST /v2/link/provider/password/{provider}` instead.

        Parameters
        ----------
        username : str

        password : str

        provider : Providers

        auth_type : AuthType

        vital_link_token : typing.Optional[str]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        typing.Optional[typing.Any]
            Successful Response

        Examples
        --------
        from vital import Vital
        from vital import Providers
        from vital import AuthType
        client = Vital(api_key="YOUR_API_KEY", )
        client.link.password_auth(username='username', password='password', provider=Providers.OURA, auth_type=AuthType.PASSWORD, )
        """
        _response = self._raw_client.password_auth(
            username=username,
            password=password,
            provider=provider,
            auth_type=auth_type,
            vital_link_token=vital_link_token,
            request_options=request_options,
        )
        return _response.data

    def generate_oauth_link(
        self,
        oauth_provider: OAuthProviders,
        *,
        vital_link_token: typing.Optional[str] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> Source:
        """
        This endpoint generates an OAuth link for oauth provider

        Parameters
        ----------
        oauth_provider : OAuthProviders

        vital_link_token : typing.Optional[str]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        Source
            Successful Response

        Examples
        --------
        from vital import Vital
        from vital import OAuthProviders
        client = Vital(api_key="YOUR_API_KEY", )
        client.link.generate_oauth_link(oauth_provider=OAuthProviders.OURA, )
        """
        _response = self._raw_client.generate_oauth_link(
            oauth_provider, vital_link_token=vital_link_token, request_options=request_options
        )
        return _response.data

    def connect_password_provider(
        self,
        provider: PasswordProviders,
        *,
        username: str,
        password: str,
        vital_link_token: typing.Optional[str] = None,
        region: typing.Optional[Region] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> ProviderLinkResponse:
        """
        This connects auth providers that are password based.

        Parameters
        ----------
        provider : PasswordProviders

        username : str
            Username for provider

        password : str
            Password for provider

        vital_link_token : typing.Optional[str]

        region : typing.Optional[Region]
            Provider region to authenticate against. Only applicable to specific providers.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        ProviderLinkResponse
            Successful Response

        Examples
        --------
        from vital import Vital
        from vital import PasswordProviders
        client = Vital(api_key="YOUR_API_KEY", )
        client.link.connect_password_provider(provider=PasswordProviders.WHOOP, username='username', password='password', )
        """
        _response = self._raw_client.connect_password_provider(
            provider,
            username=username,
            password=password,
            vital_link_token=vital_link_token,
            region=region,
            request_options=request_options,
        )
        return _response.data

    def complete_password_provider_mfa(
        self,
        provider: PasswordProviders,
        *,
        mfa_code: str,
        vital_link_token: typing.Optional[str] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> ProviderLinkResponse:
        """
        This connects auth providers that are password based.

        Parameters
        ----------
        provider : PasswordProviders

        mfa_code : str

        vital_link_token : typing.Optional[str]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        ProviderLinkResponse
            Successful Response

        Examples
        --------
        from vital import Vital
        from vital import PasswordProviders
        client = Vital(api_key="YOUR_API_KEY", )
        client.link.complete_password_provider_mfa(provider=PasswordProviders.WHOOP, mfa_code='mfa_code', )
        """
        _response = self._raw_client.complete_password_provider_mfa(
            provider, mfa_code=mfa_code, vital_link_token=vital_link_token, request_options=request_options
        )
        return _response.data

    def connect_email_auth_provider(
        self,
        *,
        email: str,
        vital_link_token: typing.Optional[str] = None,
        email_provider_auth_link_provider: typing.Optional[Providers] = OMIT,
        region: typing.Optional[Region] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> typing.Optional[typing.Any]:
        """
        This connects auth providers that are email based.

        Parameters
        ----------
        email : str

        vital_link_token : typing.Optional[str]

        email_provider_auth_link_provider : typing.Optional[Providers]

        region : typing.Optional[Region]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        typing.Optional[typing.Any]
            Successful Response

        Examples
        --------
        from vital import Vital
        client = Vital(api_key="YOUR_API_KEY", )
        client.link.connect_email_auth_provider(email='email', )
        """
        _response = self._raw_client.connect_email_auth_provider(
            email=email,
            vital_link_token=vital_link_token,
            email_provider_auth_link_provider=email_provider_auth_link_provider,
            region=region,
            request_options=request_options,
        )
        return _response.data

    def get_all_providers(
        self, *, vital_link_token: typing.Optional[str] = None, request_options: typing.Optional[RequestOptions] = None
    ) -> typing.List[SourceLink]:
        """
        GET List of all available providers given the generated link token.

        Parameters
        ----------
        vital_link_token : typing.Optional[str]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        typing.List[SourceLink]
            Successful Response

        Examples
        --------
        from vital import Vital
        client = Vital(api_key="YOUR_API_KEY", )
        client.link.get_all_providers()
        """
        _response = self._raw_client.get_all_providers(
            vital_link_token=vital_link_token, request_options=request_options
        )
        return _response.data

    def connect_manual_provider(
        self,
        provider: ManualProviders,
        *,
        user_id: str,
        provider_id: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> typing.Dict[str, bool]:
        """
        Parameters
        ----------
        provider : ManualProviders

        user_id : str

        provider_id : typing.Optional[str]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        typing.Dict[str, bool]
            Successful Response

        Examples
        --------
        from vital import Vital
        from vital import ManualProviders
        client = Vital(api_key="YOUR_API_KEY", )
        client.link.connect_manual_provider(provider=ManualProviders.BEURER_BLE, user_id='user_id', )
        """
        _response = self._raw_client.connect_manual_provider(
            provider, user_id=user_id, provider_id=provider_id, request_options=request_options
        )
        return _response.data

    def connect_demo_provider(
        self, *, user_id: str, provider: DemoProviders, request_options: typing.Optional[RequestOptions] = None
    ) -> DemoConnectionStatus:
        """
        POST Connect the given Vital user to a demo provider.

        Parameters
        ----------
        user_id : str
            Vital user ID

        provider : DemoProviders
            Demo provider. For more information, please check out our docs (https://docs.tryvital.io/wearables/providers/test_data)

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        DemoConnectionStatus
            Successful Response

        Examples
        --------
        from vital import Vital
        from vital import DemoProviders
        client = Vital(api_key="YOUR_API_KEY", )
        client.link.connect_demo_provider(user_id='user_id', provider=DemoProviders.APPLE_HEALTH_KIT, )
        """
        _response = self._raw_client.connect_demo_provider(
            user_id=user_id, provider=provider, request_options=request_options
        )
        return _response.data


class AsyncLinkClient:
    def __init__(self, *, client_wrapper: AsyncClientWrapper):
        self._raw_client = AsyncRawLinkClient(client_wrapper=client_wrapper)

    @property
    def with_raw_response(self) -> AsyncRawLinkClient:
        """
        Retrieves a raw implementation of this client that returns raw responses.

        Returns
        -------
        AsyncRawLinkClient
        """
        return self._raw_client

    async def list_bulk_ops(
        self,
        *,
        next_cursor: typing.Optional[str] = None,
        page_size: typing.Optional[int] = None,
        team_id: typing.Optional[ListBulkOpsLinkRequestTeamId] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> BulkOpsResponse:
        """
        Parameters
        ----------
        next_cursor : typing.Optional[str]

        page_size : typing.Optional[int]

        team_id : typing.Optional[ListBulkOpsLinkRequestTeamId]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        BulkOpsResponse
            Successful Response

        Examples
        --------
        from vital import AsyncVital
        import asyncio
        client = AsyncVital(api_key="YOUR_API_KEY", )
        async def main() -> None:
            await client.link.list_bulk_ops()
        asyncio.run(main())
        """
        _response = await self._raw_client.list_bulk_ops(
            next_cursor=next_cursor, page_size=page_size, team_id=team_id, request_options=request_options
        )
        return _response.data

    async def bulk_import(
        self,
        *,
        provider: OAuthProviders,
        connections: typing.Sequence[ConnectionRecipe],
        team_id: typing.Optional[BulkImportLinkRequestTeamId] = None,
        wait_for_completion: typing.Optional[bool] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> BulkImportConnectionsResponse:
        """
        Parameters
        ----------
        provider : OAuthProviders

        connections : typing.Sequence[ConnectionRecipe]

        team_id : typing.Optional[BulkImportLinkRequestTeamId]

        wait_for_completion : typing.Optional[bool]

            Whether or not the endpoint should wait for the Bulk Op to complete before responding.

            When `wait_for_completion` is enabled, the endpoint may respond 200 OK if the Bulk Op takes less than 20 seconds to complete.

            Otherwise, the endpoint always responds with 202 Created once the submitted data have been enqueued successfully. You can use
            the [List Bulk Ops](https://docs.tryvital.io/api-reference/link/list-bulk-ops) endpoint to inspect the progress of the Bulk Op.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        BulkImportConnectionsResponse
            Successful Response

        Examples
        --------
        from vital import AsyncVital
        from vital import OAuthProviders
        from vital import ConnectionRecipe
        import asyncio
        client = AsyncVital(api_key="YOUR_API_KEY", )
        async def main() -> None:
            await client.link.bulk_import(provider=OAuthProviders.OURA, connections=[ConnectionRecipe(user_id='user_id', access_token='access_token', refresh_token='refresh_token', provider_id='provider_id', expires_at=1, )], )
        asyncio.run(main())
        """
        _response = await self._raw_client.bulk_import(
            provider=provider,
            connections=connections,
            team_id=team_id,
            wait_for_completion=wait_for_completion,
            request_options=request_options,
        )
        return _response.data

    async def bulk_trigger_historical_pull(
        self,
        *,
        user_ids: typing.Sequence[str],
        provider: OAuthProviders,
        team_id: typing.Optional[BulkTriggerHistoricalPullLinkRequestTeamId] = None,
        wait_for_completion: typing.Optional[bool] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> typing.Optional[typing.Any]:
        """
        Parameters
        ----------
        user_ids : typing.Sequence[str]

        provider : OAuthProviders

        team_id : typing.Optional[BulkTriggerHistoricalPullLinkRequestTeamId]

        wait_for_completion : typing.Optional[bool]

            Whether or not the endpoint should wait for the Bulk Op to complete before responding.

            When `wait_for_completion` is enabled, the endpoint may respond 200 OK if the Bulk Op takes less than 20 seconds to complete.

            Otherwise, the endpoint always responds with 202 Created once the submitted data have been enqueued successfully. You can use
            the [List Bulk Ops](https://docs.tryvital.io/api-reference/link/list-bulk-ops) endpoint to inspect the progress of the Bulk Op.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        typing.Optional[typing.Any]
            Successful Response

        Examples
        --------
        from vital import AsyncVital
        from vital import OAuthProviders
        import asyncio
        client = AsyncVital(api_key="YOUR_API_KEY", )
        async def main() -> None:
            await client.link.bulk_trigger_historical_pull(user_ids=['user_ids'], provider=OAuthProviders.OURA, )
        asyncio.run(main())
        """
        _response = await self._raw_client.bulk_trigger_historical_pull(
            user_ids=user_ids,
            provider=provider,
            team_id=team_id,
            wait_for_completion=wait_for_completion,
            request_options=request_options,
        )
        return _response.data

    async def bulk_export(
        self,
        *,
        provider: OAuthProviders,
        team_id: typing.Optional[BulkExportLinkRequestTeamId] = None,
        user_ids: typing.Optional[typing.Sequence[str]] = OMIT,
        next_token: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> BulkExportConnectionsResponse:
        """
        Parameters
        ----------
        provider : OAuthProviders

        team_id : typing.Optional[BulkExportLinkRequestTeamId]

        user_ids : typing.Optional[typing.Sequence[str]]

        next_token : typing.Optional[str]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        BulkExportConnectionsResponse
            Successful Response

        Examples
        --------
        from vital import AsyncVital
        from vital import OAuthProviders
        import asyncio
        client = AsyncVital(api_key="YOUR_API_KEY", )
        async def main() -> None:
            await client.link.bulk_export(provider=OAuthProviders.OURA, )
        asyncio.run(main())
        """
        _response = await self._raw_client.bulk_export(
            provider=provider,
            team_id=team_id,
            user_ids=user_ids,
            next_token=next_token,
            request_options=request_options,
        )
        return _response.data

    async def bulk_pause(
        self,
        *,
        user_ids: typing.Sequence[str],
        provider: OAuthProviders,
        team_id: typing.Optional[BulkPauseLinkRequestTeamId] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> typing.Optional[typing.Any]:
        """
        Parameters
        ----------
        user_ids : typing.Sequence[str]

        provider : OAuthProviders

        team_id : typing.Optional[BulkPauseLinkRequestTeamId]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        typing.Optional[typing.Any]
            Successful Response

        Examples
        --------
        from vital import AsyncVital
        from vital import OAuthProviders
        import asyncio
        client = AsyncVital(api_key="YOUR_API_KEY", )
        async def main() -> None:
            await client.link.bulk_pause(user_ids=['user_ids'], provider=OAuthProviders.OURA, )
        asyncio.run(main())
        """
        _response = await self._raw_client.bulk_pause(
            user_ids=user_ids, provider=provider, team_id=team_id, request_options=request_options
        )
        return _response.data

    async def token(
        self,
        *,
        user_id: str,
        provider: typing.Optional[Providers] = OMIT,
        redirect_url: typing.Optional[str] = OMIT,
        filter_on_providers: typing.Optional[typing.Sequence[Providers]] = OMIT,
        on_error: typing.Optional[typing.Literal["redirect"]] = OMIT,
        on_close: typing.Optional[typing.Literal["redirect"]] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> LinkTokenExchangeResponse:
        """
        Endpoint to generate a user link token, to be used throughout the vital
        link process. The vital link token is a one time use token, that
        expires after 10 minutes. If you would like vital-link widget to launch
        with a specific provider, pass in a provider in the body. If you would
        like to redirect to a custom url after successful or error connection,
        pass in your own custom redirect_url parameter.

        Parameters
        ----------
        user_id : str
            User id returned by vital create user request. This id should be stored in your database against the user and used for all interactions with the vital api.

        provider : typing.Optional[Providers]

        redirect_url : typing.Optional[str]

        filter_on_providers : typing.Optional[typing.Sequence[Providers]]
            An allowlist of providers dictating what Vital Link Widget should show to the end user.
            If unspecified, all linkable providers are shown.

            This has no effect on programmatic Vital Link API usage.

        on_error : typing.Optional[typing.Literal["redirect"]]
            By default, Vital Link Widget input forms for password and email providers have in-built error handling.

            Specifying `on_error=redirect` disables this Vital Link Widget UI behaviour — it would
            instead redirect to your `redirect_url`, with Link Error parameters injected.

            This has no effect on OAuth providers — they always redirect to your `redirect_url`. This also has
            no effect on programmatic Vital Link API usage.

        on_close : typing.Optional[typing.Literal["redirect"]]
            By default, Vital Link Widget closes the window or tab when the user taps the Close button.

            Specifying `on_close=redirect` would change the Close button behaviour to redirect to your `redirect_url`
            with the `user_cancelled` error specified.

            This has no effect on programmatic Vital Link API usage.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        LinkTokenExchangeResponse
            Successful Response

        Examples
        --------
        from vital import AsyncVital
        import asyncio
        client = AsyncVital(api_key="YOUR_API_KEY", )
        async def main() -> None:
            await client.link.token(user_id='user_id', )
        asyncio.run(main())
        """
        _response = await self._raw_client.token(
            user_id=user_id,
            provider=provider,
            redirect_url=redirect_url,
            filter_on_providers=filter_on_providers,
            on_error=on_error,
            on_close=on_close,
            request_options=request_options,
        )
        return _response.data

    async def is_token_valid(
        self, *, token: str, request_options: typing.Optional[RequestOptions] = None
    ) -> typing.Dict[str, typing.Optional[typing.Any]]:
        """
        Parameters
        ----------
        token : str

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        typing.Dict[str, typing.Optional[typing.Any]]
            Successful Response

        Examples
        --------
        from vital import AsyncVital
        import asyncio
        client = AsyncVital(api_key="YOUR_API_KEY", )
        async def main() -> None:
            await client.link.is_token_valid(token='token', )
        asyncio.run(main())
        """
        _response = await self._raw_client.is_token_valid(token=token, request_options=request_options)
        return _response.data

    async def code_create(
        self,
        *,
        user_id: str,
        expires_at: typing.Optional[dt.datetime] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> VitalTokenCreatedResponse:
        """
        Generate a token to invite a user of Vital mobile app to your team

        Parameters
        ----------
        user_id : str

        expires_at : typing.Optional[dt.datetime]
            When the link code should expire. Defaults to server time plus 1 hour.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        VitalTokenCreatedResponse
            Successful Response

        Examples
        --------
        from vital import AsyncVital
        import asyncio
        client = AsyncVital(api_key="YOUR_API_KEY", )
        async def main() -> None:
            await client.link.code_create(user_id='user_id', )
        asyncio.run(main())
        """
        _response = await self._raw_client.code_create(
            user_id=user_id, expires_at=expires_at, request_options=request_options
        )
        return _response.data

    async def start_connect(
        self, *, link_token: str, provider: Providers, request_options: typing.Optional[RequestOptions] = None
    ) -> typing.Dict[str, typing.Optional[typing.Any]]:
        """
        REQUEST_SOURCE: VITAL-LINK
        Start link token process

        Parameters
        ----------
        link_token : str

        provider : Providers

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        typing.Dict[str, typing.Optional[typing.Any]]
            Successful Response

        Examples
        --------
        from vital import AsyncVital
        from vital import Providers
        import asyncio
        client = AsyncVital(api_key="YOUR_API_KEY", )
        async def main() -> None:
            await client.link.start_connect(link_token='link_token', provider=Providers.OURA, )
        asyncio.run(main())
        """
        _response = await self._raw_client.start_connect(
            link_token=link_token, provider=provider, request_options=request_options
        )
        return _response.data

    async def token_state(
        self, *, vital_link_token: typing.Optional[str] = None, request_options: typing.Optional[RequestOptions] = None
    ) -> typing.Dict[str, typing.Optional[typing.Any]]:
        """
        REQUEST_SOURCE: VITAL-LINK
        Check link token state - can be hit continuously used as heartbeat

        Parameters
        ----------
        vital_link_token : typing.Optional[str]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        typing.Dict[str, typing.Optional[typing.Any]]
            Successful Response

        Examples
        --------
        from vital import AsyncVital
        import asyncio
        client = AsyncVital(api_key="YOUR_API_KEY", )
        async def main() -> None:
            await client.link.token_state()
        asyncio.run(main())
        """
        _response = await self._raw_client.token_state(
            vital_link_token=vital_link_token, request_options=request_options
        )
        return _response.data

    async def email_auth(
        self,
        *,
        email: str,
        provider: Providers,
        auth_type: AuthType,
        vital_link_token: typing.Optional[str] = None,
        region: typing.Optional[Region] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> typing.Optional[typing.Any]:
        """
        Deprecated. Use `POST /v2/link/provider/email/{provider}` instead.

        Parameters
        ----------
        email : str

        provider : Providers

        auth_type : AuthType

        vital_link_token : typing.Optional[str]

        region : typing.Optional[Region]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        typing.Optional[typing.Any]
            Successful Response

        Examples
        --------
        from vital import AsyncVital
        from vital import Providers
        from vital import AuthType
        import asyncio
        client = AsyncVital(api_key="YOUR_API_KEY", )
        async def main() -> None:
            await client.link.email_auth(email='email', provider=Providers.OURA, auth_type=AuthType.PASSWORD, )
        asyncio.run(main())
        """
        _response = await self._raw_client.email_auth(
            email=email,
            provider=provider,
            auth_type=auth_type,
            vital_link_token=vital_link_token,
            region=region,
            request_options=request_options,
        )
        return _response.data

    async def password_auth(
        self,
        *,
        username: str,
        password: str,
        provider: Providers,
        auth_type: AuthType,
        vital_link_token: typing.Optional[str] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> typing.Optional[typing.Any]:
        """
        Deprecated. Use `POST /v2/link/provider/password/{provider}` instead.

        Parameters
        ----------
        username : str

        password : str

        provider : Providers

        auth_type : AuthType

        vital_link_token : typing.Optional[str]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        typing.Optional[typing.Any]
            Successful Response

        Examples
        --------
        from vital import AsyncVital
        from vital import Providers
        from vital import AuthType
        import asyncio
        client = AsyncVital(api_key="YOUR_API_KEY", )
        async def main() -> None:
            await client.link.password_auth(username='username', password='password', provider=Providers.OURA, auth_type=AuthType.PASSWORD, )
        asyncio.run(main())
        """
        _response = await self._raw_client.password_auth(
            username=username,
            password=password,
            provider=provider,
            auth_type=auth_type,
            vital_link_token=vital_link_token,
            request_options=request_options,
        )
        return _response.data

    async def generate_oauth_link(
        self,
        oauth_provider: OAuthProviders,
        *,
        vital_link_token: typing.Optional[str] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> Source:
        """
        This endpoint generates an OAuth link for oauth provider

        Parameters
        ----------
        oauth_provider : OAuthProviders

        vital_link_token : typing.Optional[str]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        Source
            Successful Response

        Examples
        --------
        from vital import AsyncVital
        from vital import OAuthProviders
        import asyncio
        client = AsyncVital(api_key="YOUR_API_KEY", )
        async def main() -> None:
            await client.link.generate_oauth_link(oauth_provider=OAuthProviders.OURA, )
        asyncio.run(main())
        """
        _response = await self._raw_client.generate_oauth_link(
            oauth_provider, vital_link_token=vital_link_token, request_options=request_options
        )
        return _response.data

    async def connect_password_provider(
        self,
        provider: PasswordProviders,
        *,
        username: str,
        password: str,
        vital_link_token: typing.Optional[str] = None,
        region: typing.Optional[Region] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> ProviderLinkResponse:
        """
        This connects auth providers that are password based.

        Parameters
        ----------
        provider : PasswordProviders

        username : str
            Username for provider

        password : str
            Password for provider

        vital_link_token : typing.Optional[str]

        region : typing.Optional[Region]
            Provider region to authenticate against. Only applicable to specific providers.

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        ProviderLinkResponse
            Successful Response

        Examples
        --------
        from vital import AsyncVital
        from vital import PasswordProviders
        import asyncio
        client = AsyncVital(api_key="YOUR_API_KEY", )
        async def main() -> None:
            await client.link.connect_password_provider(provider=PasswordProviders.WHOOP, username='username', password='password', )
        asyncio.run(main())
        """
        _response = await self._raw_client.connect_password_provider(
            provider,
            username=username,
            password=password,
            vital_link_token=vital_link_token,
            region=region,
            request_options=request_options,
        )
        return _response.data

    async def complete_password_provider_mfa(
        self,
        provider: PasswordProviders,
        *,
        mfa_code: str,
        vital_link_token: typing.Optional[str] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> ProviderLinkResponse:
        """
        This connects auth providers that are password based.

        Parameters
        ----------
        provider : PasswordProviders

        mfa_code : str

        vital_link_token : typing.Optional[str]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        ProviderLinkResponse
            Successful Response

        Examples
        --------
        from vital import AsyncVital
        from vital import PasswordProviders
        import asyncio
        client = AsyncVital(api_key="YOUR_API_KEY", )
        async def main() -> None:
            await client.link.complete_password_provider_mfa(provider=PasswordProviders.WHOOP, mfa_code='mfa_code', )
        asyncio.run(main())
        """
        _response = await self._raw_client.complete_password_provider_mfa(
            provider, mfa_code=mfa_code, vital_link_token=vital_link_token, request_options=request_options
        )
        return _response.data

    async def connect_email_auth_provider(
        self,
        *,
        email: str,
        vital_link_token: typing.Optional[str] = None,
        email_provider_auth_link_provider: typing.Optional[Providers] = OMIT,
        region: typing.Optional[Region] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> typing.Optional[typing.Any]:
        """
        This connects auth providers that are email based.

        Parameters
        ----------
        email : str

        vital_link_token : typing.Optional[str]

        email_provider_auth_link_provider : typing.Optional[Providers]

        region : typing.Optional[Region]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        typing.Optional[typing.Any]
            Successful Response

        Examples
        --------
        from vital import AsyncVital
        import asyncio
        client = AsyncVital(api_key="YOUR_API_KEY", )
        async def main() -> None:
            await client.link.connect_email_auth_provider(email='email', )
        asyncio.run(main())
        """
        _response = await self._raw_client.connect_email_auth_provider(
            email=email,
            vital_link_token=vital_link_token,
            email_provider_auth_link_provider=email_provider_auth_link_provider,
            region=region,
            request_options=request_options,
        )
        return _response.data

    async def get_all_providers(
        self, *, vital_link_token: typing.Optional[str] = None, request_options: typing.Optional[RequestOptions] = None
    ) -> typing.List[SourceLink]:
        """
        GET List of all available providers given the generated link token.

        Parameters
        ----------
        vital_link_token : typing.Optional[str]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        typing.List[SourceLink]
            Successful Response

        Examples
        --------
        from vital import AsyncVital
        import asyncio
        client = AsyncVital(api_key="YOUR_API_KEY", )
        async def main() -> None:
            await client.link.get_all_providers()
        asyncio.run(main())
        """
        _response = await self._raw_client.get_all_providers(
            vital_link_token=vital_link_token, request_options=request_options
        )
        return _response.data

    async def connect_manual_provider(
        self,
        provider: ManualProviders,
        *,
        user_id: str,
        provider_id: typing.Optional[str] = OMIT,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> typing.Dict[str, bool]:
        """
        Parameters
        ----------
        provider : ManualProviders

        user_id : str

        provider_id : typing.Optional[str]

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        typing.Dict[str, bool]
            Successful Response

        Examples
        --------
        from vital import AsyncVital
        from vital import ManualProviders
        import asyncio
        client = AsyncVital(api_key="YOUR_API_KEY", )
        async def main() -> None:
            await client.link.connect_manual_provider(provider=ManualProviders.BEURER_BLE, user_id='user_id', )
        asyncio.run(main())
        """
        _response = await self._raw_client.connect_manual_provider(
            provider, user_id=user_id, provider_id=provider_id, request_options=request_options
        )
        return _response.data

    async def connect_demo_provider(
        self, *, user_id: str, provider: DemoProviders, request_options: typing.Optional[RequestOptions] = None
    ) -> DemoConnectionStatus:
        """
        POST Connect the given Vital user to a demo provider.

        Parameters
        ----------
        user_id : str
            Vital user ID

        provider : DemoProviders
            Demo provider. For more information, please check out our docs (https://docs.tryvital.io/wearables/providers/test_data)

        request_options : typing.Optional[RequestOptions]
            Request-specific configuration.

        Returns
        -------
        DemoConnectionStatus
            Successful Response

        Examples
        --------
        from vital import AsyncVital
        from vital import DemoProviders
        import asyncio
        client = AsyncVital(api_key="YOUR_API_KEY", )
        async def main() -> None:
            await client.link.connect_demo_provider(user_id='user_id', provider=DemoProviders.APPLE_HEALTH_KIT, )
        asyncio.run(main())
        """
        _response = await self._raw_client.connect_demo_provider(
            user_id=user_id, provider=provider, request_options=request_options
        )
        return _response.data
