# This file is auto-generated by oagen. Do not edit.

from __future__ import annotations

from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union, cast

if TYPE_CHECKING:
    from .._client import AsyncWorkOSClient, WorkOSClient

from .._types import RequestOptions, enum_value, NOT_GIVEN, NotGiven
from .models import (
    ApplicationCredentialsListItem,
    CreateM2MApplication,
    CreateOAuthApplication,
    ExternalAuthCompleteResponse,
    NewConnectApplicationSecret,
    RedirectUriInput,
    UserConsentOption,
    UserObject,
)
from workos.common.models.connect_application import ConnectApplication
from workos.common.models.connect_application import ConnectApplicationVariant
from .models import ApplicationsRegistrationTypes
from workos.common.models.pagination_order import PaginationOrder
from .._pagination import AsyncPage, SyncPage


class Connect:
    """Connect API resources."""

    def __init__(self, client: "WorkOSClient") -> None:
        self._client = client

    def complete_oauth2(
        self,
        *,
        external_auth_id: str,
        user: UserObject,
        user_consent_options: Optional[List[UserConsentOption]] = None,
        request_options: Optional[RequestOptions] = None,
    ) -> ExternalAuthCompleteResponse:
        """Complete external authentication

        Completes an external authentication flow and returns control to AuthKit. This endpoint is used with [Standalone Connect](https://workos.com/docs/authkit/connect/standalone) to bridge your existing authentication system with the Connect OAuth API infrastructure.

        After successfully authenticating a user in your application, calling this endpoint will:

        - Create or update the user in AuthKit, using the given `id` as its `external_id`.
        - Return a `redirect_uri` your application should redirect to in order for AuthKit to complete the flow

        Users are automatically created or updated based on the `id` and `email` provided. If a user with the same `id` exists, their information is updated. Otherwise, a new user is created.

        If you provide a new `id` with an `email` that already belongs to an existing user, the request will fail with an error as email addresses are unique to a user.

        Args:
            external_auth_id: Identifier provided when AuthKit redirected to your login page.
            user: The user to create or update in AuthKit.
            user_consent_options: Array of [User Consent Options](https://workos.com/docs/reference/workos-connect/standalone/user-consent-options) to store with the session.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            ExternalAuthCompleteResponse

        Raises:
            BadRequestError: If the request is malformed (400).
            NotFoundError: If the resource is not found (404).
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        body: Dict[str, Any] = {
            k: v
            for k, v in {
                "external_auth_id": external_auth_id,
                "user": user.to_dict(),
                "user_consent_options": [
                    item.to_dict() for item in user_consent_options
                ]
                if user_consent_options is not None
                else None,
            }.items()
            if v is not None
        }
        return self._client.request(
            method="post",
            path=("authkit", "oauth2", "complete"),
            body=body,
            model=ExternalAuthCompleteResponse,
            request_options=request_options,
        )

    def list_applications(
        self,
        *,
        limit: Optional[int] = None,
        before: Optional[str] = None,
        after: Optional[str] = None,
        order: Optional[Union[PaginationOrder, str]] = "desc",
        registration_types: Optional[
            List[Union[ApplicationsRegistrationTypes, str]]
        ] = None,
        organization_id: Optional[str] = None,
        request_options: Optional[RequestOptions] = None,
    ) -> SyncPage[ConnectApplicationVariant]:
        """List Connect Applications

        List all Connect Applications in the current environment with optional filtering.

        Args:
            limit: Upper limit on the number of objects to return, between `1` and `100`. Defaults to `10`.
            before: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `before="obj_123"` to fetch a new batch of objects before `"obj_123"`.
            after: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `after="obj_123"` to fetch a new batch of objects after `"obj_123"`.
            order: Order the results by the creation time. Supported values are `"asc"` (ascending), `"desc"` (descending), and `"normal"` (descending with reversed cursor semantics where `before` fetches older records and `after` fetches newer records). Defaults to `desc`.
            registration_types: Filter Connect Applications by registration type. Specify multiple as a comma-separated list (e.g. `registration_types=dynamic,authenticated`). Defaults to `authenticated` only when not specified.
            organization_id: Filter Connect Applications by organization ID.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            SyncPage[ConnectApplicationVariant]

        Raises:
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        params = {
            k: v
            for k, v in {
                "limit": limit,
                "before": before,
                "after": after,
                "order": enum_value(order) if order is not None else None,
                "registration_types": ",".join(str(v) for v in registration_types)
                if registration_types is not None
                else None,
                "organization_id": organization_id,
            }.items()
            if v is not None
        }
        return cast(
            SyncPage[ConnectApplicationVariant],
            self._client.request_page(
                method="get",
                path=("connect", "applications"),
                model=ConnectApplication,  # type: ignore[arg-type]  # dispatcher; pagination only calls from_dict
                params=params,
                request_options=request_options,
            ),
        )

    def create_application(
        self,
        *,
        body: Union[CreateOAuthApplication, CreateM2MApplication, Dict[str, Any]],
        request_options: Optional[RequestOptions] = None,
    ) -> ConnectApplicationVariant:
        """Create a Connect Application

        Create a new Connect Application. Supports both OAuth and Machine-to-Machine (M2M) application types.

        Args:
            body: The request body. Accepts: CreateOAuthApplication, CreateM2MApplication, or a plain dict.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            ConnectApplicationVariant

        Raises:
            NotFoundError: If the resource is not found (404).
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        _body: Dict[str, Any] = body if isinstance(body, dict) else body.to_dict()
        return cast(
            ConnectApplicationVariant,
            self._client.request(
                method="post",
                path=("connect", "applications"),
                body=_body,
                model=ConnectApplication,  # type: ignore[arg-type]  # dispatcher; request only calls from_dict
                request_options=request_options,
            ),
        )

    def create_oauth_application(
        self,
        *,
        name: str,
        is_first_party: bool,
        description: Optional[str] = None,
        scopes: Optional[List[str]] = None,
        redirect_uris: Optional[List[RedirectUriInput]] = None,
        uses_pkce: Optional[bool] = None,
        organization_id: Optional[str] = None,
        request_options: Optional[RequestOptions] = None,
    ) -> ConnectApplicationVariant:
        """Create oauth application."""
        body: Dict[str, Any] = {
            "application_type": "oauth",
            "name": name,
            "is_first_party": is_first_party,
        }
        if description is not None:
            body["description"] = description
        if scopes is not None:
            body["scopes"] = scopes
        if redirect_uris is not None:
            body["redirect_uris"] = redirect_uris
        if uses_pkce is not None:
            body["uses_pkce"] = uses_pkce
        if organization_id is not None:
            body["organization_id"] = organization_id

        return cast(
            ConnectApplicationVariant,
            self._client.request(
                method="POST",
                path=("connect", "applications"),
                body=body,
                model=ConnectApplication,  # type: ignore[arg-type]  # dispatcher; request only calls from_dict
                request_options=request_options,
            ),
        )

    def create_m2m_application(
        self,
        *,
        name: str,
        organization_id: str,
        description: Optional[str] = None,
        scopes: Optional[List[str]] = None,
        request_options: Optional[RequestOptions] = None,
    ) -> ConnectApplicationVariant:
        """Create m2m application."""
        body: Dict[str, Any] = {
            "application_type": "m2m",
            "name": name,
            "organization_id": organization_id,
        }
        if description is not None:
            body["description"] = description
        if scopes is not None:
            body["scopes"] = scopes

        return cast(
            ConnectApplicationVariant,
            self._client.request(
                method="POST",
                path=("connect", "applications"),
                body=body,
                model=ConnectApplication,  # type: ignore[arg-type]  # dispatcher; request only calls from_dict
                request_options=request_options,
            ),
        )

    def get_application(
        self,
        id: str,
        *,
        request_options: Optional[RequestOptions] = None,
    ) -> ConnectApplicationVariant:
        """Get a Connect Application

        Retrieve details for a specific Connect Application by ID or client ID.

        Args:
            id: The application ID or client ID of the Connect Application.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            ConnectApplicationVariant

        Raises:
            NotFoundError: If the resource is not found (404).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        return cast(
            ConnectApplicationVariant,
            self._client.request(
                method="get",
                path=("connect", "applications", str(id)),
                model=ConnectApplication,  # type: ignore[arg-type]  # dispatcher; request only calls from_dict
                request_options=request_options,
            ),
        )

    def update_application(
        self,
        id: str,
        *,
        name: Optional[str] = None,
        description: Union[str, None, NotGiven] = NOT_GIVEN,
        scopes: Union[List[str], None, NotGiven] = NOT_GIVEN,
        redirect_uris: Union[List[RedirectUriInput], None, NotGiven] = NOT_GIVEN,
        request_options: Optional[RequestOptions] = None,
    ) -> ConnectApplicationVariant:
        """Update a Connect Application

        Update an existing Connect Application. For OAuth applications, you can update redirect URIs. For all applications, you can update the name, description, and scopes.

        Args:
            id: The application ID or client ID of the Connect Application.
            name: The name of the application.
            description: A description for the application.
            scopes: The OAuth scopes granted to the application.
            redirect_uris: Updated redirect URIs for the application. OAuth applications only.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            ConnectApplicationVariant

        Raises:
            NotFoundError: If the resource is not found (404).
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        body: Dict[str, Any] = {
            k: v
            for k, v in {
                "name": name,
            }.items()
            if v is not None
        }
        if not isinstance(description, NotGiven):
            body["description"] = description
        if not isinstance(scopes, NotGiven):
            body["scopes"] = scopes
        if not isinstance(redirect_uris, NotGiven):
            body["redirect_uris"] = (
                [item.to_dict() for item in redirect_uris]
                if redirect_uris is not None
                else None
            )
        return cast(
            ConnectApplicationVariant,
            self._client.request(
                method="put",
                path=("connect", "applications", str(id)),
                body=body,
                model=ConnectApplication,  # type: ignore[arg-type]  # dispatcher; request only calls from_dict
                request_options=request_options,
            ),
        )

    def delete_application(
        self,
        id: str,
        *,
        request_options: Optional[RequestOptions] = None,
    ) -> None:
        """Delete a Connect Application

        Delete an existing Connect Application.

        Args:
            id: The application ID or client ID of the Connect Application.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Raises:
            NotFoundError: If the resource is not found (404).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        self._client.request(
            method="delete",
            path=("connect", "applications", str(id)),
            request_options=request_options,
        )

    def list_application_client_secrets(
        self,
        id: str,
        *,
        request_options: Optional[RequestOptions] = None,
    ) -> List[ApplicationCredentialsListItem]:
        """List Client Secrets for a Connect Application

        List all client secrets associated with a Connect Application.

        Args:
            id: The application ID or client ID of the Connect Application.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            List[ApplicationCredentialsListItem]

        Raises:
            NotFoundError: If the resource is not found (404).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        raw = self._client.request_list(
            method="get",
            path=("connect", "applications", str(id), "client_secrets"),
            request_options=request_options,
        )
        return [
            ApplicationCredentialsListItem.from_dict(cast(Dict[str, Any], item))
            for item in raw
        ]

    def create_application_client_secret(
        self,
        id: str,
        *,
        request_options: Optional[RequestOptions] = None,
    ) -> NewConnectApplicationSecret:
        """Create a new client secret for a Connect Application

        Create new secrets for a Connect Application.

        Args:
            id: The application ID or client ID of the Connect Application.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            NewConnectApplicationSecret

        Raises:
            NotFoundError: If the resource is not found (404).
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        body: Dict[str, Any] = {}
        return self._client.request(
            method="post",
            path=("connect", "applications", str(id), "client_secrets"),
            body=body,
            model=NewConnectApplicationSecret,
            request_options=request_options,
        )

    def delete_client_secret(
        self,
        id: str,
        *,
        request_options: Optional[RequestOptions] = None,
    ) -> None:
        """Delete a Client Secret

        Delete (revoke) an existing client secret.

        Args:
            id: The unique ID of the client secret.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Raises:
            NotFoundError: If the resource is not found (404).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        self._client.request(
            method="delete",
            path=("connect", "client_secrets", str(id)),
            request_options=request_options,
        )


class AsyncConnect:
    """Connect API resources (async)."""

    def __init__(self, client: "AsyncWorkOSClient") -> None:
        self._client = client

    async def complete_oauth2(
        self,
        *,
        external_auth_id: str,
        user: UserObject,
        user_consent_options: Optional[List[UserConsentOption]] = None,
        request_options: Optional[RequestOptions] = None,
    ) -> ExternalAuthCompleteResponse:
        """Complete external authentication

        Completes an external authentication flow and returns control to AuthKit. This endpoint is used with [Standalone Connect](https://workos.com/docs/authkit/connect/standalone) to bridge your existing authentication system with the Connect OAuth API infrastructure.

        After successfully authenticating a user in your application, calling this endpoint will:

        - Create or update the user in AuthKit, using the given `id` as its `external_id`.
        - Return a `redirect_uri` your application should redirect to in order for AuthKit to complete the flow

        Users are automatically created or updated based on the `id` and `email` provided. If a user with the same `id` exists, their information is updated. Otherwise, a new user is created.

        If you provide a new `id` with an `email` that already belongs to an existing user, the request will fail with an error as email addresses are unique to a user.

        Args:
            external_auth_id: Identifier provided when AuthKit redirected to your login page.
            user: The user to create or update in AuthKit.
            user_consent_options: Array of [User Consent Options](https://workos.com/docs/reference/workos-connect/standalone/user-consent-options) to store with the session.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            ExternalAuthCompleteResponse

        Raises:
            BadRequestError: If the request is malformed (400).
            NotFoundError: If the resource is not found (404).
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        body: Dict[str, Any] = {
            k: v
            for k, v in {
                "external_auth_id": external_auth_id,
                "user": user.to_dict(),
                "user_consent_options": [
                    item.to_dict() for item in user_consent_options
                ]
                if user_consent_options is not None
                else None,
            }.items()
            if v is not None
        }
        return await self._client.request(
            method="post",
            path=("authkit", "oauth2", "complete"),
            body=body,
            model=ExternalAuthCompleteResponse,
            request_options=request_options,
        )

    async def list_applications(
        self,
        *,
        limit: Optional[int] = None,
        before: Optional[str] = None,
        after: Optional[str] = None,
        order: Optional[Union[PaginationOrder, str]] = "desc",
        registration_types: Optional[
            List[Union[ApplicationsRegistrationTypes, str]]
        ] = None,
        organization_id: Optional[str] = None,
        request_options: Optional[RequestOptions] = None,
    ) -> AsyncPage[ConnectApplicationVariant]:
        """List Connect Applications

        List all Connect Applications in the current environment with optional filtering.

        Args:
            limit: Upper limit on the number of objects to return, between `1` and `100`. Defaults to `10`.
            before: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `before="obj_123"` to fetch a new batch of objects before `"obj_123"`.
            after: An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `after="obj_123"` to fetch a new batch of objects after `"obj_123"`.
            order: Order the results by the creation time. Supported values are `"asc"` (ascending), `"desc"` (descending), and `"normal"` (descending with reversed cursor semantics where `before` fetches older records and `after` fetches newer records). Defaults to `desc`.
            registration_types: Filter Connect Applications by registration type. Specify multiple as a comma-separated list (e.g. `registration_types=dynamic,authenticated`). Defaults to `authenticated` only when not specified.
            organization_id: Filter Connect Applications by organization ID.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            AsyncPage[ConnectApplicationVariant]

        Raises:
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        params = {
            k: v
            for k, v in {
                "limit": limit,
                "before": before,
                "after": after,
                "order": enum_value(order) if order is not None else None,
                "registration_types": ",".join(str(v) for v in registration_types)
                if registration_types is not None
                else None,
                "organization_id": organization_id,
            }.items()
            if v is not None
        }
        return cast(
            AsyncPage[ConnectApplicationVariant],
            await self._client.request_page(
                method="get",
                path=("connect", "applications"),
                model=ConnectApplication,  # type: ignore[arg-type]  # dispatcher; pagination only calls from_dict
                params=params,
                request_options=request_options,
            ),
        )

    async def create_application(
        self,
        *,
        body: Union[CreateOAuthApplication, CreateM2MApplication, Dict[str, Any]],
        request_options: Optional[RequestOptions] = None,
    ) -> ConnectApplicationVariant:
        """Create a Connect Application

        Create a new Connect Application. Supports both OAuth and Machine-to-Machine (M2M) application types.

        Args:
            body: The request body. Accepts: CreateOAuthApplication, CreateM2MApplication, or a plain dict.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            ConnectApplicationVariant

        Raises:
            NotFoundError: If the resource is not found (404).
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        _body: Dict[str, Any] = body if isinstance(body, dict) else body.to_dict()
        return cast(
            ConnectApplicationVariant,
            await self._client.request(
                method="post",
                path=("connect", "applications"),
                body=_body,
                model=ConnectApplication,  # type: ignore[arg-type]  # dispatcher; request only calls from_dict
                request_options=request_options,
            ),
        )

    async def create_oauth_application(
        self,
        *,
        name: str,
        is_first_party: bool,
        description: Optional[str] = None,
        scopes: Optional[List[str]] = None,
        redirect_uris: Optional[List[RedirectUriInput]] = None,
        uses_pkce: Optional[bool] = None,
        organization_id: Optional[str] = None,
        request_options: Optional[RequestOptions] = None,
    ) -> ConnectApplicationVariant:
        """Create oauth application."""
        body: Dict[str, Any] = {
            "application_type": "oauth",
            "name": name,
            "is_first_party": is_first_party,
        }
        if description is not None:
            body["description"] = description
        if scopes is not None:
            body["scopes"] = scopes
        if redirect_uris is not None:
            body["redirect_uris"] = redirect_uris
        if uses_pkce is not None:
            body["uses_pkce"] = uses_pkce
        if organization_id is not None:
            body["organization_id"] = organization_id

        return cast(
            ConnectApplicationVariant,
            await self._client.request(
                method="POST",
                path=("connect", "applications"),
                body=body,
                model=ConnectApplication,  # type: ignore[arg-type]  # dispatcher; request only calls from_dict
                request_options=request_options,
            ),
        )

    async def create_m2m_application(
        self,
        *,
        name: str,
        organization_id: str,
        description: Optional[str] = None,
        scopes: Optional[List[str]] = None,
        request_options: Optional[RequestOptions] = None,
    ) -> ConnectApplicationVariant:
        """Create m2m application."""
        body: Dict[str, Any] = {
            "application_type": "m2m",
            "name": name,
            "organization_id": organization_id,
        }
        if description is not None:
            body["description"] = description
        if scopes is not None:
            body["scopes"] = scopes

        return cast(
            ConnectApplicationVariant,
            await self._client.request(
                method="POST",
                path=("connect", "applications"),
                body=body,
                model=ConnectApplication,  # type: ignore[arg-type]  # dispatcher; request only calls from_dict
                request_options=request_options,
            ),
        )

    async def get_application(
        self,
        id: str,
        *,
        request_options: Optional[RequestOptions] = None,
    ) -> ConnectApplicationVariant:
        """Get a Connect Application

        Retrieve details for a specific Connect Application by ID or client ID.

        Args:
            id: The application ID or client ID of the Connect Application.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            ConnectApplicationVariant

        Raises:
            NotFoundError: If the resource is not found (404).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        return cast(
            ConnectApplicationVariant,
            await self._client.request(
                method="get",
                path=("connect", "applications", str(id)),
                model=ConnectApplication,  # type: ignore[arg-type]  # dispatcher; request only calls from_dict
                request_options=request_options,
            ),
        )

    async def update_application(
        self,
        id: str,
        *,
        name: Optional[str] = None,
        description: Union[str, None, NotGiven] = NOT_GIVEN,
        scopes: Union[List[str], None, NotGiven] = NOT_GIVEN,
        redirect_uris: Union[List[RedirectUriInput], None, NotGiven] = NOT_GIVEN,
        request_options: Optional[RequestOptions] = None,
    ) -> ConnectApplicationVariant:
        """Update a Connect Application

        Update an existing Connect Application. For OAuth applications, you can update redirect URIs. For all applications, you can update the name, description, and scopes.

        Args:
            id: The application ID or client ID of the Connect Application.
            name: The name of the application.
            description: A description for the application.
            scopes: The OAuth scopes granted to the application.
            redirect_uris: Updated redirect URIs for the application. OAuth applications only.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            ConnectApplicationVariant

        Raises:
            NotFoundError: If the resource is not found (404).
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        body: Dict[str, Any] = {
            k: v
            for k, v in {
                "name": name,
            }.items()
            if v is not None
        }
        if not isinstance(description, NotGiven):
            body["description"] = description
        if not isinstance(scopes, NotGiven):
            body["scopes"] = scopes
        if not isinstance(redirect_uris, NotGiven):
            body["redirect_uris"] = (
                [item.to_dict() for item in redirect_uris]
                if redirect_uris is not None
                else None
            )
        return cast(
            ConnectApplicationVariant,
            await self._client.request(
                method="put",
                path=("connect", "applications", str(id)),
                body=body,
                model=ConnectApplication,  # type: ignore[arg-type]  # dispatcher; request only calls from_dict
                request_options=request_options,
            ),
        )

    async def delete_application(
        self,
        id: str,
        *,
        request_options: Optional[RequestOptions] = None,
    ) -> None:
        """Delete a Connect Application

        Delete an existing Connect Application.

        Args:
            id: The application ID or client ID of the Connect Application.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Raises:
            NotFoundError: If the resource is not found (404).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        await self._client.request(
            method="delete",
            path=("connect", "applications", str(id)),
            request_options=request_options,
        )

    async def list_application_client_secrets(
        self,
        id: str,
        *,
        request_options: Optional[RequestOptions] = None,
    ) -> List[ApplicationCredentialsListItem]:
        """List Client Secrets for a Connect Application

        List all client secrets associated with a Connect Application.

        Args:
            id: The application ID or client ID of the Connect Application.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            List[ApplicationCredentialsListItem]

        Raises:
            NotFoundError: If the resource is not found (404).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        raw = await self._client.request_list(
            method="get",
            path=("connect", "applications", str(id), "client_secrets"),
            request_options=request_options,
        )
        return [
            ApplicationCredentialsListItem.from_dict(cast(Dict[str, Any], item))
            for item in raw
        ]

    async def create_application_client_secret(
        self,
        id: str,
        *,
        request_options: Optional[RequestOptions] = None,
    ) -> NewConnectApplicationSecret:
        """Create a new client secret for a Connect Application

        Create new secrets for a Connect Application.

        Args:
            id: The application ID or client ID of the Connect Application.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            NewConnectApplicationSecret

        Raises:
            NotFoundError: If the resource is not found (404).
            UnprocessableEntityError: If the request data is unprocessable (422).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        body: Dict[str, Any] = {}
        return await self._client.request(
            method="post",
            path=("connect", "applications", str(id), "client_secrets"),
            body=body,
            model=NewConnectApplicationSecret,
            request_options=request_options,
        )

    async def delete_client_secret(
        self,
        id: str,
        *,
        request_options: Optional[RequestOptions] = None,
    ) -> None:
        """Delete a Client Secret

        Delete (revoke) an existing client secret.

        Args:
            id: The unique ID of the client secret.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Raises:
            NotFoundError: If the resource is not found (404).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        await self._client.request(
            method="delete",
            path=("connect", "client_secrets", str(id)),
            request_options=request_options,
        )
