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

from __future__ import annotations

from typing import TYPE_CHECKING, Any, Literal, cast

if TYPE_CHECKING:
    from .._client import AsyncWorkOSClient, WorkOSClient

from dataclasses import dataclass

from workos.common.models.create_user_invite_options_locale import (
    CreateUserInviteOptionsLocale,
)
from workos.common.models.create_user_password_hash_type import (
    CreateUserPasswordHashType,
)
from workos.common.models.pagination_order import PaginationOrder
from workos.common.models.resend_user_invite_options_locale import (
    ResendUserInviteOptionsLocale,
)
from workos.common.models.user import User
from workos.common.models.user_sessions_list_item import UserSessionsListItem

from .._pagination import AsyncPage, SyncPage
from .._types import NOT_GIVEN, NotGiven, RequestOptions, enum_value
from ..session import (
    AsyncSession,
    AuthenticateWithSessionCookieErrorResponse,
    AuthenticateWithSessionCookieSuccessResponse,
    Session,
)
from .models import (
    AuthenticateResponse,
    AuthorizationCodeSessionAuthenticateRequest,
    AuthorizedConnectApplicationListData,
    CORSOriginResponse,
    DeviceAuthorizationResponse,
    DeviceCodeSessionAuthenticateRequest,
    EmailChange,
    EmailChangeConfirmation,
    EmailVerification,
    EmailVerificationCodeSessionAuthenticateRequest,
    Invitation,
    JwksResponse,
    JWTTemplateResponse,
    MagicAuth,
    MagicAuthCodeSessionAuthenticateRequest,
    MagicAuthSendMagicAuthCodeAndReturnResponse,
    MFATotpSessionAuthenticateRequest,
    OrganizationSelectionSessionAuthenticateRequest,
    PasswordReset,
    PasswordSessionAuthenticateRequest,
    RadarChallenge,
    RadarEmailChallengeCodeSessionAuthenticateRequest,
    RadarSmsChallengeCodeSessionAuthenticateRequest,
    RedirectUri,
    RefreshTokenSessionAuthenticateRequest,
    ResetPasswordResponse,
    SendRadarSmsChallengeResponse,
    SendVerificationEmailResponse,
    UserApiKey,
    UserApiKeyWithValue,
    UserCreateResponse,
    UserIdentitiesGetItem,
    UserInvite,
    UserManagementAuthenticationProvider,
    UserManagementAuthenticationScreenHint,
    VerifyEmailResponse,
)


@dataclass
class PasswordPlaintext:
    """Identify password plaintext."""

    password: str | None


@dataclass
class PasswordHashed:
    """Identify password hashed."""

    password_hash: str
    password_hash_type: CreateUserPasswordHashType | str


class UserManagement:
    """User Management API resources."""

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

    def get_jwks(
        self,
        client_id: str,
        *,
        request_options: RequestOptions | None = None,
    ) -> JwksResponse:
        """Get JWKS

        Returns the JSON Web Key Set (JWKS) containing the public keys used for verifying access tokens.

        Args:
            client_id: Identifies the application making the request to the WorkOS server. You can obtain your client ID from the [API Keys](https://dashboard.workos.com/api-keys) page in the dashboard.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            JwksResponse

        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 self._client.request(
            method="get",
            path=("sso", "jwks", str(client_id)),
            model=JwksResponse,
            request_options=request_options,
        )

    def create_authenticate(
        self,
        *,
        body: AuthorizationCodeSessionAuthenticateRequest
        | PasswordSessionAuthenticateRequest
        | RefreshTokenSessionAuthenticateRequest
        | MagicAuthCodeSessionAuthenticateRequest
        | EmailVerificationCodeSessionAuthenticateRequest
        | MFATotpSessionAuthenticateRequest
        | OrganizationSelectionSessionAuthenticateRequest
        | RadarEmailChallengeCodeSessionAuthenticateRequest
        | RadarSmsChallengeCodeSessionAuthenticateRequest
        | DeviceCodeSessionAuthenticateRequest
        | dict[str, Any],
        request_options: RequestOptions | None = None,
    ) -> AuthenticateResponse:
        """Authenticate

        Authenticate a user with a specified [authentication method](https://workos.com/docs/reference/authkit/authentication).

        Args:
            body: The request body. Accepts: AuthorizationCodeSessionAuthenticateRequest, PasswordSessionAuthenticateRequest, RefreshTokenSessionAuthenticateRequest, MagicAuthCodeSessionAuthenticateRequest, EmailVerificationCodeSessionAuthenticateRequest, MFATotpSessionAuthenticateRequest, OrganizationSelectionSessionAuthenticateRequest, RadarEmailChallengeCodeSessionAuthenticateRequest, RadarSmsChallengeCodeSessionAuthenticateRequest, DeviceCodeSessionAuthenticateRequest, or a plain dict.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            AuthenticateResponse

        Raises:
            BadRequestError: If the request is malformed (400).
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            UnprocessableEntityError: If the request data is unprocessable (422).
            RateLimitExceededError: If rate limited (429).
            AuthenticationError: If the API key is invalid (401).
            ServerError: If the server returns a 5xx error.
        """
        _body: dict[str, Any] = body if isinstance(body, dict) else body.to_dict()
        return self._client.request(
            method="post",
            path=("user_management", "authenticate"),
            body=_body,
            model=AuthenticateResponse,
            request_options=request_options,
        )

    def authenticate_with_password(
        self,
        *,
        email: str,
        password: str,
        invitation_token: str | None = None,
        ip_address: str | None = None,
        device_id: str | None = None,
        user_agent: str | None = None,
        signals_id: str | None = None,
        radar_auth_attempt_id: str | None = None,
        request_options: RequestOptions | None = None,
    ) -> AuthenticateResponse:
        """Authenticate with password."""
        body: dict[str, Any] = {
            "grant_type": "password",
            "email": email,
            "password": password,
        }
        if self._client.client_id is not None:
            body["client_id"] = self._client.client_id
        if self._client._api_key is not None:
            body["client_secret"] = self._client._api_key
        if invitation_token is not None:
            body["invitation_token"] = invitation_token
        if ip_address is not None:
            body["ip_address"] = ip_address
        if device_id is not None:
            body["device_id"] = device_id
        if user_agent is not None:
            body["user_agent"] = user_agent
        if signals_id is not None:
            body["signals_id"] = signals_id
        if radar_auth_attempt_id is not None:
            body["radar_auth_attempt_id"] = radar_auth_attempt_id

        return self._client.request(
            method="POST",
            path=("user_management", "authenticate"),
            body=body,
            model=AuthenticateResponse,
            request_options=request_options,
        )

    def authenticate_with_code(
        self,
        *,
        code: str,
        code_verifier: str | None = None,
        invitation_token: str | None = None,
        ip_address: str | None = None,
        device_id: str | None = None,
        user_agent: str | None = None,
        signals_id: str | None = None,
        request_options: RequestOptions | None = None,
    ) -> AuthenticateResponse:
        """Authenticate with code."""
        body: dict[str, Any] = {
            "grant_type": "authorization_code",
            "code": code,
        }
        if self._client.client_id is not None:
            body["client_id"] = self._client.client_id
        if self._client._api_key is not None:
            body["client_secret"] = self._client._api_key
        if code_verifier is not None:
            body["code_verifier"] = code_verifier
        if invitation_token is not None:
            body["invitation_token"] = invitation_token
        if ip_address is not None:
            body["ip_address"] = ip_address
        if device_id is not None:
            body["device_id"] = device_id
        if user_agent is not None:
            body["user_agent"] = user_agent
        if signals_id is not None:
            body["signals_id"] = signals_id

        return self._client.request(
            method="POST",
            path=("user_management", "authenticate"),
            body=body,
            model=AuthenticateResponse,
            request_options=request_options,
        )

    def authenticate_with_refresh_token(
        self,
        *,
        refresh_token: str,
        organization_id: str | None = None,
        ip_address: str | None = None,
        device_id: str | None = None,
        user_agent: str | None = None,
        request_options: RequestOptions | None = None,
    ) -> AuthenticateResponse:
        """Authenticate with refresh token."""
        body: dict[str, Any] = {
            "grant_type": "refresh_token",
            "refresh_token": refresh_token,
        }
        if self._client.client_id is not None:
            body["client_id"] = self._client.client_id
        if self._client._api_key is not None:
            body["client_secret"] = self._client._api_key
        if organization_id is not None:
            body["organization_id"] = organization_id
        if ip_address is not None:
            body["ip_address"] = ip_address
        if device_id is not None:
            body["device_id"] = device_id
        if user_agent is not None:
            body["user_agent"] = user_agent

        return self._client.request(
            method="POST",
            path=("user_management", "authenticate"),
            body=body,
            model=AuthenticateResponse,
            request_options=request_options,
        )

    def authenticate_with_magic_auth(
        self,
        *,
        code: str,
        email: str,
        invitation_token: str | None = None,
        ip_address: str | None = None,
        device_id: str | None = None,
        user_agent: str | None = None,
        radar_auth_attempt_id: str | None = None,
        request_options: RequestOptions | None = None,
    ) -> AuthenticateResponse:
        """Authenticate with magic auth."""
        body: dict[str, Any] = {
            "grant_type": "urn:workos:oauth:grant-type:magic-auth:code",
            "code": code,
            "email": email,
        }
        if self._client.client_id is not None:
            body["client_id"] = self._client.client_id
        if self._client._api_key is not None:
            body["client_secret"] = self._client._api_key
        if invitation_token is not None:
            body["invitation_token"] = invitation_token
        if ip_address is not None:
            body["ip_address"] = ip_address
        if device_id is not None:
            body["device_id"] = device_id
        if user_agent is not None:
            body["user_agent"] = user_agent
        if radar_auth_attempt_id is not None:
            body["radar_auth_attempt_id"] = radar_auth_attempt_id

        return self._client.request(
            method="POST",
            path=("user_management", "authenticate"),
            body=body,
            model=AuthenticateResponse,
            request_options=request_options,
        )

    def authenticate_with_email_verification(
        self,
        *,
        code: str,
        pending_authentication_token: str,
        ip_address: str | None = None,
        device_id: str | None = None,
        user_agent: str | None = None,
        request_options: RequestOptions | None = None,
    ) -> AuthenticateResponse:
        """Authenticate with email verification."""
        body: dict[str, Any] = {
            "grant_type": "urn:workos:oauth:grant-type:email-verification:code",
            "code": code,
            "pending_authentication_token": pending_authentication_token,
        }
        if self._client.client_id is not None:
            body["client_id"] = self._client.client_id
        if self._client._api_key is not None:
            body["client_secret"] = self._client._api_key
        if ip_address is not None:
            body["ip_address"] = ip_address
        if device_id is not None:
            body["device_id"] = device_id
        if user_agent is not None:
            body["user_agent"] = user_agent

        return self._client.request(
            method="POST",
            path=("user_management", "authenticate"),
            body=body,
            model=AuthenticateResponse,
            request_options=request_options,
        )

    def authenticate_with_totp(
        self,
        *,
        code: str,
        pending_authentication_token: str,
        authentication_challenge_id: str,
        ip_address: str | None = None,
        device_id: str | None = None,
        user_agent: str | None = None,
        request_options: RequestOptions | None = None,
    ) -> AuthenticateResponse:
        """Authenticate with totp."""
        body: dict[str, Any] = {
            "grant_type": "urn:workos:oauth:grant-type:mfa-totp",
            "code": code,
            "pending_authentication_token": pending_authentication_token,
            "authentication_challenge_id": authentication_challenge_id,
        }
        if self._client.client_id is not None:
            body["client_id"] = self._client.client_id
        if self._client._api_key is not None:
            body["client_secret"] = self._client._api_key
        if ip_address is not None:
            body["ip_address"] = ip_address
        if device_id is not None:
            body["device_id"] = device_id
        if user_agent is not None:
            body["user_agent"] = user_agent

        return self._client.request(
            method="POST",
            path=("user_management", "authenticate"),
            body=body,
            model=AuthenticateResponse,
            request_options=request_options,
        )

    def authenticate_with_organization_selection(
        self,
        *,
        pending_authentication_token: str,
        organization_id: str,
        ip_address: str | None = None,
        device_id: str | None = None,
        user_agent: str | None = None,
        request_options: RequestOptions | None = None,
    ) -> AuthenticateResponse:
        """Authenticate with organization selection."""
        body: dict[str, Any] = {
            "grant_type": "urn:workos:oauth:grant-type:organization-selection",
            "pending_authentication_token": pending_authentication_token,
            "organization_id": organization_id,
        }
        if self._client.client_id is not None:
            body["client_id"] = self._client.client_id
        if self._client._api_key is not None:
            body["client_secret"] = self._client._api_key
        if ip_address is not None:
            body["ip_address"] = ip_address
        if device_id is not None:
            body["device_id"] = device_id
        if user_agent is not None:
            body["user_agent"] = user_agent

        return self._client.request(
            method="POST",
            path=("user_management", "authenticate"),
            body=body,
            model=AuthenticateResponse,
            request_options=request_options,
        )

    def authenticate_with_device_code(
        self,
        *,
        device_code: str,
        ip_address: str | None = None,
        device_id: str | None = None,
        user_agent: str | None = None,
        request_options: RequestOptions | None = None,
    ) -> AuthenticateResponse:
        """Authenticate with device code."""
        body: dict[str, Any] = {
            "grant_type": "urn:ietf:params:oauth:grant-type:device_code",
            "device_code": device_code,
        }
        if self._client.client_id is not None:
            body["client_id"] = self._client.client_id
        if ip_address is not None:
            body["ip_address"] = ip_address
        if device_id is not None:
            body["device_id"] = device_id
        if user_agent is not None:
            body["user_agent"] = user_agent

        return self._client.request(
            method="POST",
            path=("user_management", "authenticate"),
            body=body,
            model=AuthenticateResponse,
            request_options=request_options,
        )

    def authenticate_with_radar_email_challenge(
        self,
        *,
        code: str,
        radar_challenge_id: str,
        pending_authentication_token: str,
        ip_address: str | None = None,
        device_id: str | None = None,
        user_agent: str | None = None,
        request_options: RequestOptions | None = None,
    ) -> AuthenticateResponse:
        """Authenticate with radar email challenge."""
        body: dict[str, Any] = {
            "grant_type": "urn:workos:oauth:grant-type:radar-email-challenge:code",
            "code": code,
            "radar_challenge_id": radar_challenge_id,
            "pending_authentication_token": pending_authentication_token,
        }
        if self._client.client_id is not None:
            body["client_id"] = self._client.client_id
        if self._client._api_key is not None:
            body["client_secret"] = self._client._api_key
        if ip_address is not None:
            body["ip_address"] = ip_address
        if device_id is not None:
            body["device_id"] = device_id
        if user_agent is not None:
            body["user_agent"] = user_agent

        return self._client.request(
            method="POST",
            path=("user_management", "authenticate"),
            body=body,
            model=AuthenticateResponse,
            request_options=request_options,
        )

    def authenticate_with_radar_sms_challenge(
        self,
        *,
        code: str,
        verification_id: str,
        phone_number: str,
        pending_authentication_token: str,
        ip_address: str | None = None,
        device_id: str | None = None,
        user_agent: str | None = None,
        request_options: RequestOptions | None = None,
    ) -> AuthenticateResponse:
        """Authenticate with radar sms challenge."""
        body: dict[str, Any] = {
            "grant_type": "urn:workos:oauth:grant-type:radar-sms-challenge:code",
            "code": code,
            "verification_id": verification_id,
            "phone_number": phone_number,
            "pending_authentication_token": pending_authentication_token,
        }
        if self._client.client_id is not None:
            body["client_id"] = self._client.client_id
        if self._client._api_key is not None:
            body["client_secret"] = self._client._api_key
        if ip_address is not None:
            body["ip_address"] = ip_address
        if device_id is not None:
            body["device_id"] = device_id
        if user_agent is not None:
            body["user_agent"] = user_agent

        return self._client.request(
            method="POST",
            path=("user_management", "authenticate"),
            body=body,
            model=AuthenticateResponse,
            request_options=request_options,
        )

    def get_authorization_url(
        self,
        *,
        code_challenge_method: Literal["S256"] | None = None,
        code_challenge: str | None = None,
        domain_hint: str | None = None,
        connection_id: str | None = None,
        provider_query_params: dict[str, str] | None = None,
        provider_scopes: list[str] | None = None,
        invitation_token: str | None = None,
        max_age: int | None = None,
        screen_hint: UserManagementAuthenticationScreenHint | str | None = None,
        login_hint: str | None = None,
        provider: UserManagementAuthenticationProvider | str | None = None,
        prompt: str | None = None,
        state: str | None = None,
        organization_id: str | None = None,
        redirect_uri: str,
        client_id: str | None = None,
        request_options: RequestOptions | None = None,
    ) -> str:
        """Get an authorization URL

        Generates an OAuth 2.0 authorization URL to authenticate a user with AuthKit or SSO.

        Args:
            code_challenge_method: The only valid PKCE code challenge method is `"S256"`. Required when specifying a `code_challenge`.
            code_challenge: Code challenge derived from the code verifier used for the PKCE flow.
            domain_hint: A domain hint for SSO connection lookup.
            connection_id: The ID of an SSO connection to use for authentication.
            provider_query_params: Key/value pairs of query parameters to pass to the OAuth provider.
            provider_scopes: Additional OAuth scopes to request from the identity provider.
            invitation_token: A token representing a user invitation to redeem during authentication.
            max_age: Maximum allowable elapsed time, in seconds, since the user last actively authenticated. If the last authentication is older than this value, the user is prompted to re-authenticate; a value of `0` forces re-authentication. Only supported when the provider is `authkit`.
            screen_hint: Used to specify which screen to display when the provider is `authkit`. Defaults to `sign-in`.
            login_hint: A hint to the authorization server about the login identifier the user might use.
            provider: The OAuth provider to authenticate with (e.g., GoogleOAuth, MicrosoftOAuth, GitHubOAuth).
            prompt: Controls the authentication flow behavior for the user.
            state: An opaque value used to maintain state between the request and the callback.
            organization_id: The ID of the organization to authenticate the user against.
            redirect_uri: The callback URI where the authorization code will be sent after authentication.
            client_id: The unique identifier of the WorkOS environment client. Defaults to the client's configured client_id.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            str

        Raises:
            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 {
                "code_challenge_method": code_challenge_method,
                "code_challenge": code_challenge,
                "domain_hint": domain_hint,
                "connection_id": connection_id,
                "provider_query_params": provider_query_params,
                "provider_scopes": ",".join(str(v) for v in provider_scopes)
                if provider_scopes is not None
                else None,
                "invitation_token": invitation_token,
                "max_age": max_age,
                "screen_hint": enum_value(screen_hint)
                if screen_hint is not None
                else None,
                "login_hint": login_hint,
                "provider": enum_value(provider) if provider is not None else None,
                "prompt": prompt,
                "state": state,
                "organization_id": organization_id,
                "redirect_uri": redirect_uri,
                "client_id": client_id,
            }.items()
            if v is not None
        }
        params["response_type"] = "code"
        if "client_id" not in params and self._client.client_id is not None:
            params["client_id"] = self._client.client_id
        return self._client.build_url(("user_management", "authorize"), params)

    def create_device(
        self,
        *,
        client_id: str,
        request_options: RequestOptions | None = None,
    ) -> DeviceAuthorizationResponse:
        """Get device authorization URL

        Initiates the CLI Auth flow by requesting a device code and verification URLs. This endpoint implements the OAuth 2.0 Device Authorization Flow ([RFC 8628](https://datatracker.ietf.org/doc/html/rfc8628)) and is designed for command-line applications or other devices with limited input capabilities.

        Args:
            client_id: The WorkOS client ID for your application.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            DeviceAuthorizationResponse

        Raises:
            BadRequestError: If the request is malformed (400).
            AuthorizationError: If the request is forbidden (403).
            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] = {
            "client_id": client_id,
        }
        return self._client.request(
            method="post",
            path=("user_management", "authorize", "device"),
            body=body,
            model=DeviceAuthorizationResponse,
            request_options=request_options,
        )

    def create_radar_challenge(
        self,
        *,
        user_id: str,
        pending_authentication_token: str,
        phone_number: str,
        ip_address: str | None = None,
        user_agent: str | None = None,
        request_options: RequestOptions | None = None,
    ) -> SendRadarSmsChallengeResponse:
        """Send a Radar SMS challenge

        Sends a one-time verification code over SMS to a user as part of a Radar challenge. Use the returned `verification_id` to authenticate the user with the `urn:workos:oauth:grant-type:radar-sms-challenge:code` grant type.

        Args:
            user_id: The ID of the user to send the SMS challenge to.
            pending_authentication_token: The pending authentication token from a previous authentication attempt that triggered the Radar challenge.
            phone_number: The phone number to send the SMS verification code to.
            ip_address: The IP address of the user's request.
            user_agent: The user agent string from the user's request.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            SendRadarSmsChallengeResponse

        Raises:
            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 {
                "user_id": user_id,
                "pending_authentication_token": pending_authentication_token,
                "phone_number": phone_number,
                "ip_address": ip_address,
                "user_agent": user_agent,
            }.items()
            if v is not None
        }
        return self._client.request(
            method="post",
            path=("user_management", "radar_challenges"),
            body=body,
            model=SendRadarSmsChallengeResponse,
            request_options=request_options,
        )

    def get_radar_challenge(
        self,
        id: str,
        *,
        request_options: RequestOptions | None = None,
    ) -> RadarChallenge:
        """Get Radar Challenge details

        Get the details of an existing Radar Challenge, including the OTP code.

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

        Returns:
            RadarChallenge

        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 self._client.request(
            method="get",
            path=("user_management", "radar_challenges", str(id)),
            model=RadarChallenge,
            request_options=request_options,
        )

    def get_logout_url(
        self,
        *,
        session_id: str,
        return_to: str | None = None,
        request_options: RequestOptions | None = None,
    ) -> str:
        """Logout

        Logout a user from the current [session](https://workos.com/docs/reference/authkit/session).

        Args:
            session_id: The ID of the session. This can be extracted from the `sid` claim of the access token.
            return_to: The URL to redirect the user to after logout.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            str

        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 {
                "session_id": session_id,
                "return_to": return_to,
            }.items()
            if v is not None
        }
        return self._client.build_url(("user_management", "sessions", "logout"), params)

    def revoke_session(
        self,
        *,
        session_id: str,
        request_options: RequestOptions | None = None,
    ) -> None:
        """Revoke Session

        Revoke a [user session](https://workos.com/docs/reference/authkit/session).

        Args:
            session_id: The ID of the session to revoke. This can be extracted from the `sid` claim of the access token.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Raises:
            BadRequestError: If the request is malformed (400).
            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] = {
            "session_id": session_id,
        }
        self._client.request(
            method="post",
            path=("user_management", "sessions", "revoke"),
            body=body,
            request_options=request_options,
        )

    def list_cors_origins(
        self,
        *,
        limit: int | None = None,
        before: str | None = None,
        after: str | None = None,
        order: PaginationOrder | str | None = "desc",
        request_options: RequestOptions | None = None,
    ) -> SyncPage[CORSOriginResponse]:
        """List CORS origins

        Lists the CORS origins for the current environment.

        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`.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            SyncPage[CORSOriginResponse]

        Raises:
            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,
            }.items()
            if v is not None
        }
        return self._client.request_page(
            method="get",
            path=("user_management", "cors_origins"),
            model=CORSOriginResponse,
            params=params,
            request_options=request_options,
        )

    def create_cors_origin(
        self,
        *,
        origin: str,
        request_options: RequestOptions | None = None,
    ) -> CORSOriginResponse:
        """Create a CORS origin

        Creates a new CORS origin for the API key's application. CORS origins allow browser-based applications to make requests to the WorkOS API.

        Args:
            origin: The origin URL to allow for CORS requests.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            CORSOriginResponse

        Raises:
            ConflictError: If a conflict occurs (409).
            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] = {
            "origin": origin,
        }
        return self._client.request(
            method="post",
            path=("user_management", "cors_origins"),
            body=body,
            model=CORSOriginResponse,
            request_options=request_options,
        )

    def get_email_verification(
        self,
        id: str,
        *,
        request_options: RequestOptions | None = None,
    ) -> EmailVerification:
        """Get an email verification code

        Get the details of an existing email verification code that can be used to send an email to a user for verification.

        Args:
            id: The ID of the email verification code.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            EmailVerification

        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 self._client.request(
            method="get",
            path=("user_management", "email_verification", str(id)),
            model=EmailVerification,
            request_options=request_options,
        )

    def reset_password(
        self,
        *,
        email: str,
        request_options: RequestOptions | None = None,
    ) -> PasswordReset:
        """Create a password reset token

        Creates a one-time token that can be used to reset a user's password.

        Args:
            email: The email address of the user requesting a password reset.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            PasswordReset

        Raises:
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            UnprocessableEntityError: If the request data is unprocessable (422).
            RateLimitExceededError: If rate limited (429).
            AuthenticationError: If the API key is invalid (401).
            ServerError: If the server returns a 5xx error.
        """
        body: dict[str, Any] = {
            "email": email,
        }
        return self._client.request(
            method="post",
            path=("user_management", "password_reset"),
            body=body,
            model=PasswordReset,
            request_options=request_options,
        )

    def confirm_password_reset(
        self,
        *,
        token: str,
        new_password: str,
        request_options: RequestOptions | None = None,
    ) -> ResetPasswordResponse:
        """Reset the password

        Sets a new password using the `token` query parameter from the link that the user received. Successfully resetting the password will verify a user's email, if it hasn't been verified yet.

        Args:
            token: The password reset token.
            new_password: The new password to set for the user.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            ResetPasswordResponse

        Raises:
            BadRequestError: If the request is malformed (400).
            AuthorizationError: If the request is forbidden (403).
            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] = {
            "token": token,
            "new_password": new_password,
        }
        return self._client.request(
            method="post",
            path=("user_management", "password_reset", "confirm"),
            body=body,
            model=ResetPasswordResponse,
            request_options=request_options,
        )

    def get_password_reset(
        self,
        id: str,
        *,
        request_options: RequestOptions | None = None,
    ) -> PasswordReset:
        """Get a password reset token

        Get the details of an existing password reset token that can be used to reset a user's password.

        Args:
            id: The ID of the password reset token.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            PasswordReset

        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 self._client.request(
            method="get",
            path=("user_management", "password_reset", str(id)),
            model=PasswordReset,
            request_options=request_options,
        )

    def list_users(
        self,
        *,
        limit: int | None = None,
        before: str | None = None,
        after: str | None = None,
        order: PaginationOrder | str | None = "desc",
        organization: str | None = None,
        organization_id: str | None = None,
        email: str | None = None,
        request_options: RequestOptions | None = None,
    ) -> SyncPage[User]:
        """List users

        Get a list of all of your existing users matching the criteria specified.

        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`.
            organization: (deprecated) Filter users by the organization they are a member of. Deprecated in favor of `organization_id`.
            organization_id: Filter users by the organization they are a member of.
            email: Filter users by their email address.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            SyncPage[User]

        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,
                "organization": organization,
                "organization_id": organization_id,
                "email": email,
            }.items()
            if v is not None
        }
        return self._client.request_page(
            method="get",
            path=("user_management", "users"),
            model=User,
            params=params,
            request_options=request_options,
        )

    def create_user(
        self,
        *,
        email: str,
        first_name: str | None | NotGiven = NOT_GIVEN,
        last_name: str | None | NotGiven = NOT_GIVEN,
        name: str | None | NotGiven = NOT_GIVEN,
        email_verified: bool | None | NotGiven = NOT_GIVEN,
        metadata: dict[str, str] | None | NotGiven = NOT_GIVEN,
        external_id: str | None | NotGiven = NOT_GIVEN,
        ip_address: str | None | NotGiven = NOT_GIVEN,
        user_agent: str | None | NotGiven = NOT_GIVEN,
        signals_id: str | None = None,
        password: PasswordPlaintext | PasswordHashed | None = None,
        request_options: RequestOptions | None = None,
    ) -> UserCreateResponse:
        """Create a user

        Create a new user in the current environment.

        Args:
            email: The email address of the user.
            first_name: The first name of the user.
            last_name: The last name of the user.
            name: The user's full name.
            email_verified: Whether the user's email has been verified.
            metadata: Object containing metadata key/value pairs associated with the user.
            external_id: The external ID of the user.
            ip_address: The IP address of the user's request.
            user_agent: The user agent string from the user's request.
            signals_id: An optional Radar signals ID to correlate client-side signals with this request.
            password: Identifies the password. One of: PasswordPlaintext, PasswordHashed.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            UserCreateResponse

        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 {
                "email": email,
                "signals_id": signals_id,
            }.items()
            if v is not None
        }
        if not isinstance(first_name, NotGiven):
            body["first_name"] = first_name
        if not isinstance(last_name, NotGiven):
            body["last_name"] = last_name
        if not isinstance(name, NotGiven):
            body["name"] = name
        if not isinstance(email_verified, NotGiven):
            body["email_verified"] = email_verified
        if not isinstance(metadata, NotGiven):
            body["metadata"] = metadata
        if not isinstance(external_id, NotGiven):
            body["external_id"] = external_id
        if not isinstance(ip_address, NotGiven):
            body["ip_address"] = ip_address
        if not isinstance(user_agent, NotGiven):
            body["user_agent"] = user_agent
        if password is not None:
            if isinstance(password, PasswordPlaintext):
                body["password"] = password.password
            elif isinstance(password, PasswordHashed):
                body["password_hash"] = password.password_hash
                body["password_hash_type"] = enum_value(password.password_hash_type)
        return self._client.request(
            method="post",
            path=("user_management", "users"),
            body=body,
            model=UserCreateResponse,
            request_options=request_options,
        )

    def get_user_by_external_id(
        self,
        external_id: str,
        *,
        request_options: RequestOptions | None = None,
    ) -> User:
        """Get a user by external ID

        Get the details of an existing user by an [external identifier](https://workos.com/docs/authkit/metadata/external-identifiers).

        Args:
            external_id: The external ID of the user.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            User

        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 self._client.request(
            method="get",
            path=("user_management", "users", "external_id", str(external_id)),
            model=User,
            request_options=request_options,
        )

    def get_user(
        self,
        id: str,
        *,
        request_options: RequestOptions | None = None,
    ) -> User:
        """Get a user

        Get the details of an existing user.

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

        Returns:
            User

        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 self._client.request(
            method="get",
            path=("user_management", "users", str(id)),
            model=User,
            request_options=request_options,
        )

    def update_user(
        self,
        id: str,
        *,
        email: str | None = None,
        first_name: str | None = None,
        last_name: str | None = None,
        name: str | None = None,
        email_verified: bool | None = None,
        metadata: dict[str, str] | None | NotGiven = NOT_GIVEN,
        external_id: str | None | NotGiven = NOT_GIVEN,
        locale: str | None | NotGiven = NOT_GIVEN,
        password: PasswordPlaintext | PasswordHashed | None = None,
        request_options: RequestOptions | None = None,
    ) -> User:
        """Update a user

        Updates properties of a user. The omitted properties will be left unchanged.

        Args:
            id: The unique ID of the user.
            email: The email address of the user.
            first_name: The first name of the user.
            last_name: The last name of the user.
            name: The user's full name.
            email_verified: Whether the user's email has been verified.
            metadata: Object containing metadata key/value pairs associated with the user.
            external_id: The external ID of the user.
            locale: The user's preferred locale.
            password: Identifies the password. One of: PasswordPlaintext, PasswordHashed.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            User

        Raises:
            BadRequestError: If the request is malformed (400).
            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 {
                "email": email,
                "first_name": first_name,
                "last_name": last_name,
                "name": name,
                "email_verified": email_verified,
            }.items()
            if v is not None
        }
        if not isinstance(metadata, NotGiven):
            body["metadata"] = metadata
        if not isinstance(external_id, NotGiven):
            body["external_id"] = external_id
        if not isinstance(locale, NotGiven):
            body["locale"] = locale
        if password is not None:
            if isinstance(password, PasswordPlaintext):
                body["password"] = password.password
            elif isinstance(password, PasswordHashed):
                body["password_hash"] = password.password_hash
                body["password_hash_type"] = enum_value(password.password_hash_type)
        return self._client.request(
            method="put",
            path=("user_management", "users", str(id)),
            body=body,
            model=User,
            request_options=request_options,
        )

    def delete_user(
        self,
        id: str,
        *,
        request_options: RequestOptions | None = None,
    ) -> None:
        """Delete a user

        Permanently deletes a user in the current environment. It cannot be undone.

        Args:
            id: The unique ID of the user.
            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=("user_management", "users", str(id)),
            request_options=request_options,
        )

    def confirm_email_change(
        self,
        id: str,
        *,
        code: str,
        request_options: RequestOptions | None = None,
    ) -> EmailChangeConfirmation:
        """Confirm email change

        Confirms an email change using the one-time code received by the user.

        Args:
            id: The unique ID of the user.
            code: The one-time code used to confirm the email change.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            EmailChangeConfirmation

        Raises:
            BadRequestError: If the request is malformed (400).
            NotFoundError: If the resource is not found (404).
            ConflictError: If a conflict occurs (409).
            UnprocessableEntityError: If the request data is unprocessable (422).
            RateLimitExceededError: If rate limited (429).
            AuthenticationError: If the API key is invalid (401).
            ServerError: If the server returns a 5xx error.
        """
        body: dict[str, Any] = {
            "code": code,
        }
        return self._client.request(
            method="post",
            path=("user_management", "users", str(id), "email_change", "confirm"),
            body=body,
            model=EmailChangeConfirmation,
            request_options=request_options,
        )

    def send_email_change(
        self,
        id: str,
        *,
        new_email: str,
        request_options: RequestOptions | None = None,
    ) -> EmailChange:
        """Send email change code

        Sends an email that contains a one-time code used to change a user's email address.

        Args:
            id: The unique ID of the user.
            new_email: The new email address to change to.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            EmailChange

        Raises:
            NotFoundError: If the resource is not found (404).
            ConflictError: If a conflict occurs (409).
            UnprocessableEntityError: If the request data is unprocessable (422).
            RateLimitExceededError: If rate limited (429).
            AuthenticationError: If the API key is invalid (401).
            ServerError: If the server returns a 5xx error.
        """
        body: dict[str, Any] = {
            "new_email": new_email,
        }
        return self._client.request(
            method="post",
            path=("user_management", "users", str(id), "email_change", "send"),
            body=body,
            model=EmailChange,
            request_options=request_options,
        )

    def verify_email(
        self,
        id: str,
        *,
        code: str,
        request_options: RequestOptions | None = None,
    ) -> VerifyEmailResponse:
        """Verify email

        Verifies an email address using the one-time code received by the user.

        Args:
            id: The ID of the user.
            code: The one-time email verification code.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            VerifyEmailResponse

        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] = {
            "code": code,
        }
        return self._client.request(
            method="post",
            path=("user_management", "users", str(id), "email_verification", "confirm"),
            body=body,
            model=VerifyEmailResponse,
            request_options=request_options,
        )

    def send_verification_email(
        self,
        id: str,
        *,
        request_options: RequestOptions | None = None,
    ) -> SendVerificationEmailResponse:
        """Send verification email

        Sends an email that contains a one-time code used to verify a user's email address.

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

        Returns:
            SendVerificationEmailResponse

        Raises:
            BadRequestError: If the request is malformed (400).
            NotFoundError: If the resource is not found (404).
            RateLimitExceededError: If rate limited (429).
            AuthenticationError: If the API key is invalid (401).
            ServerError: If the server returns a 5xx error.
        """
        return self._client.request(
            method="post",
            path=("user_management", "users", str(id), "email_verification", "send"),
            model=SendVerificationEmailResponse,
            request_options=request_options,
        )

    def get_user_identities(
        self,
        id: str,
        *,
        request_options: RequestOptions | None = None,
    ) -> list[UserIdentitiesGetItem]:
        """Get user identities

        Get a list of identities associated with the user. A user can have multiple associated identities after going through [identity linking](https://workos.com/docs/authkit/identity-linking). Currently only OAuth identities are supported. More provider types may be added in the future.

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

        Returns:
            List[UserIdentitiesGetItem]

        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=("user_management", "users", str(id), "identities"),
            request_options=request_options,
        )
        return [
            UserIdentitiesGetItem.from_dict(cast(dict[str, Any], item)) for item in raw
        ]

    def list_sessions(
        self,
        id: str,
        *,
        limit: int | None = None,
        before: str | None = None,
        after: str | None = None,
        order: PaginationOrder | str | None = "desc",
        request_options: RequestOptions | None = None,
    ) -> SyncPage[UserSessionsListItem]:
        """List sessions

        Get a list of all active sessions for a specific user.

        Args:
            id: The ID of the user.
            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`.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            SyncPage[UserSessionsListItem]

        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.
        """
        params = {
            k: v
            for k, v in {
                "limit": limit,
                "before": before,
                "after": after,
                "order": enum_value(order) if order is not None else None,
            }.items()
            if v is not None
        }
        return self._client.request_page(
            method="get",
            path=("user_management", "users", str(id), "sessions"),
            model=UserSessionsListItem,
            params=params,
            request_options=request_options,
        )

    def list_invitations(
        self,
        *,
        limit: int | None = None,
        before: str | None = None,
        after: str | None = None,
        order: PaginationOrder | str | None = "desc",
        organization_id: str | None = None,
        email: str | None = None,
        request_options: RequestOptions | None = None,
    ) -> SyncPage[UserInvite]:
        """List invitations

        Get a list of all of invitations matching the criteria specified.

        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`.
            organization_id: The ID of the [organization](https://workos.com/docs/reference/organization) that the recipient will join.
            email: The email address of the recipient.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            SyncPage[UserInvite]

        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,
                "organization_id": organization_id,
                "email": email,
            }.items()
            if v is not None
        }
        return self._client.request_page(
            method="get",
            path=("user_management", "invitations"),
            model=UserInvite,
            params=params,
            request_options=request_options,
        )

    def send_invitation(
        self,
        *,
        email: str,
        organization_id: str | None = None,
        role_slug: str | None = None,
        expires_in_days: int | None = None,
        inviter_user_id: str | None = None,
        locale: CreateUserInviteOptionsLocale | str | None = None,
        request_options: RequestOptions | None = None,
    ) -> UserInvite:
        """Send an invitation

        Sends an invitation email to the recipient.

        Args:
            email: The email address of the recipient.
            organization_id: The ID of the [organization](https://workos.com/docs/reference/organization) that the recipient will join.
            role_slug: The [role](https://workos.com/docs/authkit/roles) that the recipient will receive when they join the organization in the invitation.
            expires_in_days: How many days the invitations will be valid for. Must be between 1 and 30 days. Defaults to 7 days if not specified.
            inviter_user_id: The ID of the [user](https://workos.com/docs/reference/authkit/user) who invites the recipient. The invitation email will mention the name of this user.
            locale: The locale to use when rendering the invitation email. See [supported locales](https://workos.com/docs/authkit/hosted-ui/localization).
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            UserInvite

        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 {
                "email": email,
                "organization_id": organization_id,
                "role_slug": role_slug,
                "expires_in_days": expires_in_days,
                "inviter_user_id": inviter_user_id,
                "locale": enum_value(locale) if locale is not None else None,
            }.items()
            if v is not None
        }
        return self._client.request(
            method="post",
            path=("user_management", "invitations"),
            body=body,
            model=UserInvite,
            request_options=request_options,
        )

    def find_invitation_by_token(
        self,
        token: str,
        *,
        request_options: RequestOptions | None = None,
    ) -> UserInvite:
        """Find an invitation by token

        Retrieve an existing invitation using the token.

        Args:
            token: The token used to accept the invitation.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            UserInvite

        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 self._client.request(
            method="get",
            path=("user_management", "invitations", "by_token", str(token)),
            model=UserInvite,
            request_options=request_options,
        )

    def get_invitation(
        self,
        id: str,
        *,
        request_options: RequestOptions | None = None,
    ) -> UserInvite:
        """Get an invitation

        Get the details of an existing invitation.

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

        Returns:
            UserInvite

        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 self._client.request(
            method="get",
            path=("user_management", "invitations", str(id)),
            model=UserInvite,
            request_options=request_options,
        )

    def accept_invitation(
        self,
        id: str,
        *,
        request_options: RequestOptions | None = None,
    ) -> Invitation:
        """Accept an invitation

        Accepts an invitation and, if linked to an organization, activates the user's membership in that organization.

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

        Returns:
            Invitation

        Raises:
            BadRequestError: If the request is malformed (400).
            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 self._client.request(
            method="post",
            path=("user_management", "invitations", str(id), "accept"),
            model=Invitation,
            request_options=request_options,
        )

    def resend_invitation(
        self,
        id: str,
        *,
        locale: ResendUserInviteOptionsLocale | str | None = None,
        request_options: RequestOptions | None = None,
    ) -> UserInvite:
        """Resend an invitation

        Resends an invitation email to the recipient. The invitation must be in a pending state.

        Args:
            id: The unique ID of the invitation.
            locale: The locale to use when rendering the invitation email. See [supported locales](https://workos.com/docs/authkit/hosted-ui/localization).
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            UserInvite

        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 {
                "locale": enum_value(locale) if locale is not None else None,
            }.items()
            if v is not None
        }
        return self._client.request(
            method="post",
            path=("user_management", "invitations", str(id), "resend"),
            body=body,
            model=UserInvite,
            request_options=request_options,
        )

    def revoke_invitation(
        self,
        id: str,
        *,
        request_options: RequestOptions | None = None,
    ) -> Invitation:
        """Revoke an invitation

        Revokes an existing invitation.

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

        Returns:
            Invitation

        Raises:
            BadRequestError: If the request is malformed (400).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        return self._client.request(
            method="post",
            path=("user_management", "invitations", str(id), "revoke"),
            model=Invitation,
            request_options=request_options,
        )

    def list_jwt_template(
        self,
        *,
        request_options: RequestOptions | None = None,
    ) -> JWTTemplateResponse:
        """Get JWT template

        Get the JWT template for the current environment.

        Returns:
            JWTTemplateResponse

        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 self._client.request(
            method="get",
            path=("user_management", "jwt_template"),
            model=JWTTemplateResponse,
            request_options=request_options,
        )

    def update_jwt_template(
        self,
        *,
        content: str,
        request_options: RequestOptions | None = None,
    ) -> JWTTemplateResponse:
        """Update JWT template

        Update the JWT template for the current environment.

        Args:
            content: The JWT template content as a Liquid template string.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            JWTTemplateResponse

        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.
        """
        body: dict[str, Any] = {
            "content": content,
        }
        return self._client.request(
            method="put",
            path=("user_management", "jwt_template"),
            body=body,
            model=JWTTemplateResponse,
            request_options=request_options,
        )

    def create_magic_auth(
        self,
        *,
        email: str,
        invitation_token: str | None = None,
        ip_address: str | None = None,
        user_agent: str | None = None,
        radar_auth_attempt_id: str | None = None,
        signals_id: str | None = None,
        request_options: RequestOptions | None = None,
    ) -> MagicAuthSendMagicAuthCodeAndReturnResponse:
        """Create a Magic Auth code

        Creates a one-time authentication code that can be sent to the user's email address. The code expires in 10 minutes. To verify the code, [authenticate the user with Magic Auth](https://workos.com/docs/reference/authkit/authentication/magic-auth).

        Args:
            email: The email address to send the magic code to.
            invitation_token: The invitation token to associate with this magic code.
            ip_address: The IP address of the user's request.
            user_agent: The user agent string from the user's request.
            radar_auth_attempt_id: The ID of an existing Radar authentication attempt to associate with this request.
            signals_id: An optional Radar signals ID to correlate client-side signals with this request.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            MagicAuthSendMagicAuthCodeAndReturnResponse

        Raises:
            BadRequestError: If the request is malformed (400).
            UnprocessableEntityError: If the request data is unprocessable (422).
            RateLimitExceededError: If rate limited (429).
            AuthenticationError: If the API key is invalid (401).
            ServerError: If the server returns a 5xx error.
        """
        body: dict[str, Any] = {
            k: v
            for k, v in {
                "email": email,
                "invitation_token": invitation_token,
                "ip_address": ip_address,
                "user_agent": user_agent,
                "radar_auth_attempt_id": radar_auth_attempt_id,
                "signals_id": signals_id,
            }.items()
            if v is not None
        }
        return self._client.request(
            method="post",
            path=("user_management", "magic_auth"),
            body=body,
            model=MagicAuthSendMagicAuthCodeAndReturnResponse,
            request_options=request_options,
        )

    def get_magic_auth(
        self,
        id: str,
        *,
        request_options: RequestOptions | None = None,
    ) -> MagicAuth:
        """Get Magic Auth code details

        Get the details of an existing [Magic Auth](https://workos.com/docs/reference/authkit/magic-auth) code that can be used to send an email to a user for authentication.

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

        Returns:
            MagicAuth

        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 self._client.request(
            method="get",
            path=("user_management", "magic_auth", str(id)),
            model=MagicAuth,
            request_options=request_options,
        )

    def list_redirect_uris(
        self,
        *,
        limit: int | None = None,
        before: str | None = None,
        after: str | None = None,
        order: PaginationOrder | str | None = "desc",
        request_options: RequestOptions | None = None,
    ) -> SyncPage[RedirectUri]:
        """List redirect URIs

        Lists the redirect URIs for an environment.

        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`.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            SyncPage[RedirectUri]

        Raises:
            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,
            }.items()
            if v is not None
        }
        return self._client.request_page(
            method="get",
            path=("user_management", "redirect_uris"),
            model=RedirectUri,
            params=params,
            request_options=request_options,
        )

    def create_redirect_uri(
        self,
        *,
        uri: str,
        request_options: RequestOptions | None = None,
    ) -> RedirectUri:
        """Create a redirect URI

        Creates a new redirect URI for an application.

        Args:
            uri: The redirect URI to create.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            RedirectUri

        Raises:
            BadRequestError: If the request is malformed (400).
            AuthenticationError: If the API key is invalid (401).
            UnprocessableEntityError: If the request data is unprocessable (422).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        body: dict[str, Any] = {
            "uri": uri,
        }
        return self._client.request(
            method="post",
            path=("user_management", "redirect_uris"),
            body=body,
            model=RedirectUri,
            request_options=request_options,
        )

    def delete_redirect_uris(
        self,
        id: str,
        *,
        request_options: RequestOptions | None = None,
    ) -> None:
        """Delete a redirect URI

        Deletes a redirect URI from an application.

        Args:
            id: The ID of the redirect URI to delete.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

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

    def list_user_authorized_applications(
        self,
        user_id: str,
        *,
        limit: int | None = None,
        before: str | None = None,
        after: str | None = None,
        order: PaginationOrder | str | None = "desc",
        request_options: RequestOptions | None = None,
    ) -> SyncPage[AuthorizedConnectApplicationListData]:
        """List authorized applications

        Get a list of all Connect applications that the user has authorized.

        Args:
            user_id: The ID of the user.
            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`.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            SyncPage[AuthorizedConnectApplicationListData]

        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.
        """
        params = {
            k: v
            for k, v in {
                "limit": limit,
                "before": before,
                "after": after,
                "order": enum_value(order) if order is not None else None,
            }.items()
            if v is not None
        }
        return self._client.request_page(
            method="get",
            path=("user_management", "users", str(user_id), "authorized_applications"),
            model=AuthorizedConnectApplicationListData,
            params=params,
            request_options=request_options,
        )

    def delete_user_authorized_application(
        self,
        application_id: str,
        user_id: str,
        *,
        request_options: RequestOptions | None = None,
    ) -> None:
        """Delete an authorized application

        Delete an existing Authorized Connect Application.

        Args:
            application_id: The ID or client ID of the application.
            user_id: The ID of the user.
            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=(
                "user_management",
                "users",
                str(user_id),
                "authorized_applications",
                str(application_id),
            ),
            request_options=request_options,
        )

    def list_user_api_keys(
        self,
        user_id: str,
        *,
        limit: int | None = None,
        before: str | None = None,
        after: str | None = None,
        order: PaginationOrder | str | None = "desc",
        organization_id: str | None = None,
        request_options: RequestOptions | None = None,
    ) -> SyncPage[UserApiKey]:
        """List API keys for a user

        Get a list of API keys owned by a specific user.

        Args:
            user_id: Unique identifier of the user.
            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.
            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.
            order: Order the results by the creation time. Defaults to `desc`.
            organization_id: The ID of the organization to filter user API keys by. When provided, only API keys created against that organization membership are returned.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            SyncPage[UserApiKey]

        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.
        """
        params = {
            k: v
            for k, v in {
                "limit": limit,
                "before": before,
                "after": after,
                "order": enum_value(order) if order is not None else None,
                "organization_id": organization_id,
            }.items()
            if v is not None
        }
        return self._client.request_page(
            method="get",
            path=("user_management", "users", str(user_id), "api_keys"),
            model=UserApiKey,
            params=params,
            request_options=request_options,
        )

    def create_user_api_key(
        self,
        user_id: str,
        *,
        name: str,
        organization_id: str,
        permissions: list[str] | None = None,
        expires_at: str | None = None,
        request_options: RequestOptions | None = None,
    ) -> UserApiKeyWithValue:
        """Create an API key for a user

        Create a new API key owned by a user. The user must have an active membership in the specified organization.

        Args:
            user_id: Unique identifier of the user.
            name: A descriptive name for the API key.
            organization_id: The ID of the organization the user API key is associated with. The user must have an active membership in this organization.
            permissions: The permission slugs to assign to the API key. Each permission must be enabled for user API keys.
            expires_at: The timestamp when the API key should expire. Must be a future timestamp. If omitted, the key does not expire.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            UserApiKeyWithValue

        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 {
                "name": name,
                "organization_id": organization_id,
                "permissions": permissions,
                "expires_at": expires_at,
            }.items()
            if v is not None
        }
        return self._client.request(
            method="post",
            path=("user_management", "users", str(user_id), "api_keys"),
            body=body,
            model=UserApiKeyWithValue,
            request_options=request_options,
        )

    # @oagen-ignore-start

    def get_jwks_url(self, client_id: str | None = None) -> str:
        """Get the JWKS URL used to verify access tokens.

        Use this when integrating with a JWT library that fetches and caches
        the JWKS itself (e.g. ``PyJWKClient``). For the JWKS document, call
        :meth:`get_jwks` instead.

        Args:
            client_id: The WorkOS client ID. Defaults to the client's
                configured client_id.

        Returns:
            The JWKS URL.
        """
        resolved_client_id = client_id or self._client._require_client_id()
        return f"{self._client.base_url}sso/jwks/{resolved_client_id}"

    def load_sealed_session(
        self,
        *,
        session_data: str,
        cookie_password: str,
    ) -> Session:
        """Create a Session object from sealed session data.

        Args:
            session_data: The sealed session cookie value.
            cookie_password: The password used to seal the session cookie.

        Returns:
            Session: A session object that can authenticate or refresh the session.
        """
        from ..session import Session

        return Session(
            client=self._client,
            session_data=session_data,
            cookie_password=cookie_password,
        )

    def authenticate_with_session_cookie(
        self,
        *,
        session_data: str,
        cookie_password: str,
    ) -> (
        AuthenticateWithSessionCookieSuccessResponse
        | AuthenticateWithSessionCookieErrorResponse
    ):
        """One-shot authenticate a sealed session cookie.

        Args:
            session_data: The sealed session cookie value.
            cookie_password: The password used to seal the session cookie.

        Returns:
            AuthenticateWithSessionCookieSuccessResponse if the session is valid,
            AuthenticateWithSessionCookieErrorResponse otherwise.
        """
        from ..session import Session

        session = Session(
            client=self._client,
            session_data=session_data,
            cookie_password=cookie_password,
        )
        return session.authenticate()

    def get_authorization_url_with_pkce(
        self,
        *,
        redirect_uri: str,
        client_id: str | None = None,
        provider: UserManagementAuthenticationProvider | str | None = None,
        connection_id: str | None = None,
        organization_id: str | None = None,
        domain_hint: str | None = None,
        login_hint: str | None = None,
        screen_hint: UserManagementAuthenticationScreenHint | str | None = None,
        prompt: str | None = None,
        provider_scopes: list[str] | None = None,
        provider_query_params: dict[str, str] | None = None,
        invitation_token: str | None = None,
    ) -> dict[str, str]:
        """Generate an AuthKit authorization URL with auto-generated PKCE parameters.

        Args:
            redirect_uri: The URI to redirect to after authorization.
            client_id: The WorkOS client ID. Defaults to the client's configured ID.
            provider: An SSO provider to directly initiate authentication with.
            connection_id: The ID of a specific SSO connection to authenticate with.
            organization_id: The ID of the organization to authenticate into.
            domain_hint: A domain hint for SSO provider discovery.
            login_hint: A login hint (e.g., email) for the identity provider.
            screen_hint: Whether to show 'sign-in' or 'sign-up' screen.
            prompt: The OIDC prompt parameter.
            provider_scopes: Additional OAuth scopes to request from the provider.
            provider_query_params: Additional query parameters for the provider.
            invitation_token: A token to accept an organization invitation during auth.

        Returns:
            Dict with keys 'url', 'state', and 'code_verifier'.
        """
        from ..pkce import PKCE

        pkce = PKCE()
        pair = pkce.generate()
        state = pkce.generate_code_verifier(43)

        url = self.get_authorization_url(
            redirect_uri=redirect_uri,
            client_id=client_id,
            code_challenge=pair.code_challenge,
            code_challenge_method="S256",
            state=state,
            provider=provider,
            connection_id=connection_id,
            organization_id=organization_id,
            domain_hint=domain_hint,
            login_hint=login_hint,
            screen_hint=screen_hint,
            prompt=prompt,
            provider_scopes=provider_scopes,
            provider_query_params=provider_query_params,
            invitation_token=invitation_token,
        )
        return {"url": url, "state": state, "code_verifier": pair.code_verifier}

    def authenticate_with_code_pkce(
        self,
        *,
        code: str,
        code_verifier: str,
        client_id: str | None = None,
        ip_address: str | None = None,
        device_id: str | None = None,
        user_agent: str | None = None,
        request_options: RequestOptions | None = None,
    ) -> AuthenticateResponse:
        """Exchange an authorization code using a PKCE code_verifier.

        Args:
            code: The authorization code received from the redirect.
            code_verifier: The PKCE code verifier generated alongside the code challenge.
            client_id: The WorkOS client ID. Defaults to the client's configured ID.
            ip_address: The IP address of the user's request.
            device_id: A unique identifier for the device.
            user_agent: The user agent string from the user's browser.
            request_options: Per-request options for headers, timeout, retries, or base URL.

        Returns:
            AuthenticateResponse: The authentication result with user and tokens.
        """
        resolved_client_id = client_id or (self._client.client_id or "")
        body: dict[str, Any] = {
            "grant_type": "authorization_code",
            "client_id": resolved_client_id,
            "code": code,
            "code_verifier": code_verifier,
        }
        if self._client._api_key:
            body["client_secret"] = self._client._api_key
        if ip_address is not None:
            body["ip_address"] = ip_address
        if device_id is not None:
            body["device_id"] = device_id
        if user_agent is not None:
            body["user_agent"] = user_agent

        return cast(
            AuthenticateResponse,
            self._client.request(
                method="POST",
                path=("user_management", "authenticate"),
                body=body,
                model=AuthenticateResponse,
                request_options=request_options,
            ),
        )

    # @oagen-ignore-end


class AsyncUserManagement:
    """User Management API resources (async)."""

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

    async def get_jwks(
        self,
        client_id: str,
        *,
        request_options: RequestOptions | None = None,
    ) -> JwksResponse:
        """Get JWKS

        Returns the JSON Web Key Set (JWKS) containing the public keys used for verifying access tokens.

        Args:
            client_id: Identifies the application making the request to the WorkOS server. You can obtain your client ID from the [API Keys](https://dashboard.workos.com/api-keys) page in the dashboard.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            JwksResponse

        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 await self._client.request(
            method="get",
            path=("sso", "jwks", str(client_id)),
            model=JwksResponse,
            request_options=request_options,
        )

    async def create_authenticate(
        self,
        *,
        body: AuthorizationCodeSessionAuthenticateRequest
        | PasswordSessionAuthenticateRequest
        | RefreshTokenSessionAuthenticateRequest
        | MagicAuthCodeSessionAuthenticateRequest
        | EmailVerificationCodeSessionAuthenticateRequest
        | MFATotpSessionAuthenticateRequest
        | OrganizationSelectionSessionAuthenticateRequest
        | RadarEmailChallengeCodeSessionAuthenticateRequest
        | RadarSmsChallengeCodeSessionAuthenticateRequest
        | DeviceCodeSessionAuthenticateRequest
        | dict[str, Any],
        request_options: RequestOptions | None = None,
    ) -> AuthenticateResponse:
        """Authenticate

        Authenticate a user with a specified [authentication method](https://workos.com/docs/reference/authkit/authentication).

        Args:
            body: The request body. Accepts: AuthorizationCodeSessionAuthenticateRequest, PasswordSessionAuthenticateRequest, RefreshTokenSessionAuthenticateRequest, MagicAuthCodeSessionAuthenticateRequest, EmailVerificationCodeSessionAuthenticateRequest, MFATotpSessionAuthenticateRequest, OrganizationSelectionSessionAuthenticateRequest, RadarEmailChallengeCodeSessionAuthenticateRequest, RadarSmsChallengeCodeSessionAuthenticateRequest, DeviceCodeSessionAuthenticateRequest, or a plain dict.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            AuthenticateResponse

        Raises:
            BadRequestError: If the request is malformed (400).
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            UnprocessableEntityError: If the request data is unprocessable (422).
            RateLimitExceededError: If rate limited (429).
            AuthenticationError: If the API key is invalid (401).
            ServerError: If the server returns a 5xx error.
        """
        _body: dict[str, Any] = body if isinstance(body, dict) else body.to_dict()
        return await self._client.request(
            method="post",
            path=("user_management", "authenticate"),
            body=_body,
            model=AuthenticateResponse,
            request_options=request_options,
        )

    async def authenticate_with_password(
        self,
        *,
        email: str,
        password: str,
        invitation_token: str | None = None,
        ip_address: str | None = None,
        device_id: str | None = None,
        user_agent: str | None = None,
        signals_id: str | None = None,
        radar_auth_attempt_id: str | None = None,
        request_options: RequestOptions | None = None,
    ) -> AuthenticateResponse:
        """Authenticate with password."""
        body: dict[str, Any] = {
            "grant_type": "password",
            "email": email,
            "password": password,
        }
        if self._client.client_id is not None:
            body["client_id"] = self._client.client_id
        if self._client._api_key is not None:
            body["client_secret"] = self._client._api_key
        if invitation_token is not None:
            body["invitation_token"] = invitation_token
        if ip_address is not None:
            body["ip_address"] = ip_address
        if device_id is not None:
            body["device_id"] = device_id
        if user_agent is not None:
            body["user_agent"] = user_agent
        if signals_id is not None:
            body["signals_id"] = signals_id
        if radar_auth_attempt_id is not None:
            body["radar_auth_attempt_id"] = radar_auth_attempt_id

        return await self._client.request(
            method="POST",
            path=("user_management", "authenticate"),
            body=body,
            model=AuthenticateResponse,
            request_options=request_options,
        )

    async def authenticate_with_code(
        self,
        *,
        code: str,
        code_verifier: str | None = None,
        invitation_token: str | None = None,
        ip_address: str | None = None,
        device_id: str | None = None,
        user_agent: str | None = None,
        signals_id: str | None = None,
        request_options: RequestOptions | None = None,
    ) -> AuthenticateResponse:
        """Authenticate with code."""
        body: dict[str, Any] = {
            "grant_type": "authorization_code",
            "code": code,
        }
        if self._client.client_id is not None:
            body["client_id"] = self._client.client_id
        if self._client._api_key is not None:
            body["client_secret"] = self._client._api_key
        if code_verifier is not None:
            body["code_verifier"] = code_verifier
        if invitation_token is not None:
            body["invitation_token"] = invitation_token
        if ip_address is not None:
            body["ip_address"] = ip_address
        if device_id is not None:
            body["device_id"] = device_id
        if user_agent is not None:
            body["user_agent"] = user_agent
        if signals_id is not None:
            body["signals_id"] = signals_id

        return await self._client.request(
            method="POST",
            path=("user_management", "authenticate"),
            body=body,
            model=AuthenticateResponse,
            request_options=request_options,
        )

    async def authenticate_with_refresh_token(
        self,
        *,
        refresh_token: str,
        organization_id: str | None = None,
        ip_address: str | None = None,
        device_id: str | None = None,
        user_agent: str | None = None,
        request_options: RequestOptions | None = None,
    ) -> AuthenticateResponse:
        """Authenticate with refresh token."""
        body: dict[str, Any] = {
            "grant_type": "refresh_token",
            "refresh_token": refresh_token,
        }
        if self._client.client_id is not None:
            body["client_id"] = self._client.client_id
        if self._client._api_key is not None:
            body["client_secret"] = self._client._api_key
        if organization_id is not None:
            body["organization_id"] = organization_id
        if ip_address is not None:
            body["ip_address"] = ip_address
        if device_id is not None:
            body["device_id"] = device_id
        if user_agent is not None:
            body["user_agent"] = user_agent

        return await self._client.request(
            method="POST",
            path=("user_management", "authenticate"),
            body=body,
            model=AuthenticateResponse,
            request_options=request_options,
        )

    async def authenticate_with_magic_auth(
        self,
        *,
        code: str,
        email: str,
        invitation_token: str | None = None,
        ip_address: str | None = None,
        device_id: str | None = None,
        user_agent: str | None = None,
        radar_auth_attempt_id: str | None = None,
        request_options: RequestOptions | None = None,
    ) -> AuthenticateResponse:
        """Authenticate with magic auth."""
        body: dict[str, Any] = {
            "grant_type": "urn:workos:oauth:grant-type:magic-auth:code",
            "code": code,
            "email": email,
        }
        if self._client.client_id is not None:
            body["client_id"] = self._client.client_id
        if self._client._api_key is not None:
            body["client_secret"] = self._client._api_key
        if invitation_token is not None:
            body["invitation_token"] = invitation_token
        if ip_address is not None:
            body["ip_address"] = ip_address
        if device_id is not None:
            body["device_id"] = device_id
        if user_agent is not None:
            body["user_agent"] = user_agent
        if radar_auth_attempt_id is not None:
            body["radar_auth_attempt_id"] = radar_auth_attempt_id

        return await self._client.request(
            method="POST",
            path=("user_management", "authenticate"),
            body=body,
            model=AuthenticateResponse,
            request_options=request_options,
        )

    async def authenticate_with_email_verification(
        self,
        *,
        code: str,
        pending_authentication_token: str,
        ip_address: str | None = None,
        device_id: str | None = None,
        user_agent: str | None = None,
        request_options: RequestOptions | None = None,
    ) -> AuthenticateResponse:
        """Authenticate with email verification."""
        body: dict[str, Any] = {
            "grant_type": "urn:workos:oauth:grant-type:email-verification:code",
            "code": code,
            "pending_authentication_token": pending_authentication_token,
        }
        if self._client.client_id is not None:
            body["client_id"] = self._client.client_id
        if self._client._api_key is not None:
            body["client_secret"] = self._client._api_key
        if ip_address is not None:
            body["ip_address"] = ip_address
        if device_id is not None:
            body["device_id"] = device_id
        if user_agent is not None:
            body["user_agent"] = user_agent

        return await self._client.request(
            method="POST",
            path=("user_management", "authenticate"),
            body=body,
            model=AuthenticateResponse,
            request_options=request_options,
        )

    async def authenticate_with_totp(
        self,
        *,
        code: str,
        pending_authentication_token: str,
        authentication_challenge_id: str,
        ip_address: str | None = None,
        device_id: str | None = None,
        user_agent: str | None = None,
        request_options: RequestOptions | None = None,
    ) -> AuthenticateResponse:
        """Authenticate with totp."""
        body: dict[str, Any] = {
            "grant_type": "urn:workos:oauth:grant-type:mfa-totp",
            "code": code,
            "pending_authentication_token": pending_authentication_token,
            "authentication_challenge_id": authentication_challenge_id,
        }
        if self._client.client_id is not None:
            body["client_id"] = self._client.client_id
        if self._client._api_key is not None:
            body["client_secret"] = self._client._api_key
        if ip_address is not None:
            body["ip_address"] = ip_address
        if device_id is not None:
            body["device_id"] = device_id
        if user_agent is not None:
            body["user_agent"] = user_agent

        return await self._client.request(
            method="POST",
            path=("user_management", "authenticate"),
            body=body,
            model=AuthenticateResponse,
            request_options=request_options,
        )

    async def authenticate_with_organization_selection(
        self,
        *,
        pending_authentication_token: str,
        organization_id: str,
        ip_address: str | None = None,
        device_id: str | None = None,
        user_agent: str | None = None,
        request_options: RequestOptions | None = None,
    ) -> AuthenticateResponse:
        """Authenticate with organization selection."""
        body: dict[str, Any] = {
            "grant_type": "urn:workos:oauth:grant-type:organization-selection",
            "pending_authentication_token": pending_authentication_token,
            "organization_id": organization_id,
        }
        if self._client.client_id is not None:
            body["client_id"] = self._client.client_id
        if self._client._api_key is not None:
            body["client_secret"] = self._client._api_key
        if ip_address is not None:
            body["ip_address"] = ip_address
        if device_id is not None:
            body["device_id"] = device_id
        if user_agent is not None:
            body["user_agent"] = user_agent

        return await self._client.request(
            method="POST",
            path=("user_management", "authenticate"),
            body=body,
            model=AuthenticateResponse,
            request_options=request_options,
        )

    async def authenticate_with_device_code(
        self,
        *,
        device_code: str,
        ip_address: str | None = None,
        device_id: str | None = None,
        user_agent: str | None = None,
        request_options: RequestOptions | None = None,
    ) -> AuthenticateResponse:
        """Authenticate with device code."""
        body: dict[str, Any] = {
            "grant_type": "urn:ietf:params:oauth:grant-type:device_code",
            "device_code": device_code,
        }
        if self._client.client_id is not None:
            body["client_id"] = self._client.client_id
        if ip_address is not None:
            body["ip_address"] = ip_address
        if device_id is not None:
            body["device_id"] = device_id
        if user_agent is not None:
            body["user_agent"] = user_agent

        return await self._client.request(
            method="POST",
            path=("user_management", "authenticate"),
            body=body,
            model=AuthenticateResponse,
            request_options=request_options,
        )

    async def authenticate_with_radar_email_challenge(
        self,
        *,
        code: str,
        radar_challenge_id: str,
        pending_authentication_token: str,
        ip_address: str | None = None,
        device_id: str | None = None,
        user_agent: str | None = None,
        request_options: RequestOptions | None = None,
    ) -> AuthenticateResponse:
        """Authenticate with radar email challenge."""
        body: dict[str, Any] = {
            "grant_type": "urn:workos:oauth:grant-type:radar-email-challenge:code",
            "code": code,
            "radar_challenge_id": radar_challenge_id,
            "pending_authentication_token": pending_authentication_token,
        }
        if self._client.client_id is not None:
            body["client_id"] = self._client.client_id
        if self._client._api_key is not None:
            body["client_secret"] = self._client._api_key
        if ip_address is not None:
            body["ip_address"] = ip_address
        if device_id is not None:
            body["device_id"] = device_id
        if user_agent is not None:
            body["user_agent"] = user_agent

        return await self._client.request(
            method="POST",
            path=("user_management", "authenticate"),
            body=body,
            model=AuthenticateResponse,
            request_options=request_options,
        )

    async def authenticate_with_radar_sms_challenge(
        self,
        *,
        code: str,
        verification_id: str,
        phone_number: str,
        pending_authentication_token: str,
        ip_address: str | None = None,
        device_id: str | None = None,
        user_agent: str | None = None,
        request_options: RequestOptions | None = None,
    ) -> AuthenticateResponse:
        """Authenticate with radar sms challenge."""
        body: dict[str, Any] = {
            "grant_type": "urn:workos:oauth:grant-type:radar-sms-challenge:code",
            "code": code,
            "verification_id": verification_id,
            "phone_number": phone_number,
            "pending_authentication_token": pending_authentication_token,
        }
        if self._client.client_id is not None:
            body["client_id"] = self._client.client_id
        if self._client._api_key is not None:
            body["client_secret"] = self._client._api_key
        if ip_address is not None:
            body["ip_address"] = ip_address
        if device_id is not None:
            body["device_id"] = device_id
        if user_agent is not None:
            body["user_agent"] = user_agent

        return await self._client.request(
            method="POST",
            path=("user_management", "authenticate"),
            body=body,
            model=AuthenticateResponse,
            request_options=request_options,
        )

    def get_authorization_url(
        self,
        *,
        code_challenge_method: Literal["S256"] | None = None,
        code_challenge: str | None = None,
        domain_hint: str | None = None,
        connection_id: str | None = None,
        provider_query_params: dict[str, str] | None = None,
        provider_scopes: list[str] | None = None,
        invitation_token: str | None = None,
        max_age: int | None = None,
        screen_hint: UserManagementAuthenticationScreenHint | str | None = None,
        login_hint: str | None = None,
        provider: UserManagementAuthenticationProvider | str | None = None,
        prompt: str | None = None,
        state: str | None = None,
        organization_id: str | None = None,
        redirect_uri: str,
        client_id: str | None = None,
        request_options: RequestOptions | None = None,
    ) -> str:
        """Get an authorization URL

        Generates an OAuth 2.0 authorization URL to authenticate a user with AuthKit or SSO.

        Args:
            code_challenge_method: The only valid PKCE code challenge method is `"S256"`. Required when specifying a `code_challenge`.
            code_challenge: Code challenge derived from the code verifier used for the PKCE flow.
            domain_hint: A domain hint for SSO connection lookup.
            connection_id: The ID of an SSO connection to use for authentication.
            provider_query_params: Key/value pairs of query parameters to pass to the OAuth provider.
            provider_scopes: Additional OAuth scopes to request from the identity provider.
            invitation_token: A token representing a user invitation to redeem during authentication.
            max_age: Maximum allowable elapsed time, in seconds, since the user last actively authenticated. If the last authentication is older than this value, the user is prompted to re-authenticate; a value of `0` forces re-authentication. Only supported when the provider is `authkit`.
            screen_hint: Used to specify which screen to display when the provider is `authkit`. Defaults to `sign-in`.
            login_hint: A hint to the authorization server about the login identifier the user might use.
            provider: The OAuth provider to authenticate with (e.g., GoogleOAuth, MicrosoftOAuth, GitHubOAuth).
            prompt: Controls the authentication flow behavior for the user.
            state: An opaque value used to maintain state between the request and the callback.
            organization_id: The ID of the organization to authenticate the user against.
            redirect_uri: The callback URI where the authorization code will be sent after authentication.
            client_id: The unique identifier of the WorkOS environment client. Defaults to the client's configured client_id.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            str

        Raises:
            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 {
                "code_challenge_method": code_challenge_method,
                "code_challenge": code_challenge,
                "domain_hint": domain_hint,
                "connection_id": connection_id,
                "provider_query_params": provider_query_params,
                "provider_scopes": ",".join(str(v) for v in provider_scopes)
                if provider_scopes is not None
                else None,
                "invitation_token": invitation_token,
                "max_age": max_age,
                "screen_hint": enum_value(screen_hint)
                if screen_hint is not None
                else None,
                "login_hint": login_hint,
                "provider": enum_value(provider) if provider is not None else None,
                "prompt": prompt,
                "state": state,
                "organization_id": organization_id,
                "redirect_uri": redirect_uri,
                "client_id": client_id,
            }.items()
            if v is not None
        }
        params["response_type"] = "code"
        if "client_id" not in params and self._client.client_id is not None:
            params["client_id"] = self._client.client_id
        return self._client.build_url(("user_management", "authorize"), params)

    async def create_device(
        self,
        *,
        client_id: str,
        request_options: RequestOptions | None = None,
    ) -> DeviceAuthorizationResponse:
        """Get device authorization URL

        Initiates the CLI Auth flow by requesting a device code and verification URLs. This endpoint implements the OAuth 2.0 Device Authorization Flow ([RFC 8628](https://datatracker.ietf.org/doc/html/rfc8628)) and is designed for command-line applications or other devices with limited input capabilities.

        Args:
            client_id: The WorkOS client ID for your application.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            DeviceAuthorizationResponse

        Raises:
            BadRequestError: If the request is malformed (400).
            AuthorizationError: If the request is forbidden (403).
            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] = {
            "client_id": client_id,
        }
        return await self._client.request(
            method="post",
            path=("user_management", "authorize", "device"),
            body=body,
            model=DeviceAuthorizationResponse,
            request_options=request_options,
        )

    async def create_radar_challenge(
        self,
        *,
        user_id: str,
        pending_authentication_token: str,
        phone_number: str,
        ip_address: str | None = None,
        user_agent: str | None = None,
        request_options: RequestOptions | None = None,
    ) -> SendRadarSmsChallengeResponse:
        """Send a Radar SMS challenge

        Sends a one-time verification code over SMS to a user as part of a Radar challenge. Use the returned `verification_id` to authenticate the user with the `urn:workos:oauth:grant-type:radar-sms-challenge:code` grant type.

        Args:
            user_id: The ID of the user to send the SMS challenge to.
            pending_authentication_token: The pending authentication token from a previous authentication attempt that triggered the Radar challenge.
            phone_number: The phone number to send the SMS verification code to.
            ip_address: The IP address of the user's request.
            user_agent: The user agent string from the user's request.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            SendRadarSmsChallengeResponse

        Raises:
            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 {
                "user_id": user_id,
                "pending_authentication_token": pending_authentication_token,
                "phone_number": phone_number,
                "ip_address": ip_address,
                "user_agent": user_agent,
            }.items()
            if v is not None
        }
        return await self._client.request(
            method="post",
            path=("user_management", "radar_challenges"),
            body=body,
            model=SendRadarSmsChallengeResponse,
            request_options=request_options,
        )

    async def get_radar_challenge(
        self,
        id: str,
        *,
        request_options: RequestOptions | None = None,
    ) -> RadarChallenge:
        """Get Radar Challenge details

        Get the details of an existing Radar Challenge, including the OTP code.

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

        Returns:
            RadarChallenge

        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 await self._client.request(
            method="get",
            path=("user_management", "radar_challenges", str(id)),
            model=RadarChallenge,
            request_options=request_options,
        )

    def get_logout_url(
        self,
        *,
        session_id: str,
        return_to: str | None = None,
        request_options: RequestOptions | None = None,
    ) -> str:
        """Logout

        Logout a user from the current [session](https://workos.com/docs/reference/authkit/session).

        Args:
            session_id: The ID of the session. This can be extracted from the `sid` claim of the access token.
            return_to: The URL to redirect the user to after logout.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            str

        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 {
                "session_id": session_id,
                "return_to": return_to,
            }.items()
            if v is not None
        }
        return self._client.build_url(("user_management", "sessions", "logout"), params)

    async def revoke_session(
        self,
        *,
        session_id: str,
        request_options: RequestOptions | None = None,
    ) -> None:
        """Revoke Session

        Revoke a [user session](https://workos.com/docs/reference/authkit/session).

        Args:
            session_id: The ID of the session to revoke. This can be extracted from the `sid` claim of the access token.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Raises:
            BadRequestError: If the request is malformed (400).
            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] = {
            "session_id": session_id,
        }
        await self._client.request(
            method="post",
            path=("user_management", "sessions", "revoke"),
            body=body,
            request_options=request_options,
        )

    async def list_cors_origins(
        self,
        *,
        limit: int | None = None,
        before: str | None = None,
        after: str | None = None,
        order: PaginationOrder | str | None = "desc",
        request_options: RequestOptions | None = None,
    ) -> AsyncPage[CORSOriginResponse]:
        """List CORS origins

        Lists the CORS origins for the current environment.

        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`.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            AsyncPage[CORSOriginResponse]

        Raises:
            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,
            }.items()
            if v is not None
        }
        return await self._client.request_page(
            method="get",
            path=("user_management", "cors_origins"),
            model=CORSOriginResponse,
            params=params,
            request_options=request_options,
        )

    async def create_cors_origin(
        self,
        *,
        origin: str,
        request_options: RequestOptions | None = None,
    ) -> CORSOriginResponse:
        """Create a CORS origin

        Creates a new CORS origin for the API key's application. CORS origins allow browser-based applications to make requests to the WorkOS API.

        Args:
            origin: The origin URL to allow for CORS requests.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            CORSOriginResponse

        Raises:
            ConflictError: If a conflict occurs (409).
            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] = {
            "origin": origin,
        }
        return await self._client.request(
            method="post",
            path=("user_management", "cors_origins"),
            body=body,
            model=CORSOriginResponse,
            request_options=request_options,
        )

    async def get_email_verification(
        self,
        id: str,
        *,
        request_options: RequestOptions | None = None,
    ) -> EmailVerification:
        """Get an email verification code

        Get the details of an existing email verification code that can be used to send an email to a user for verification.

        Args:
            id: The ID of the email verification code.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            EmailVerification

        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 await self._client.request(
            method="get",
            path=("user_management", "email_verification", str(id)),
            model=EmailVerification,
            request_options=request_options,
        )

    async def reset_password(
        self,
        *,
        email: str,
        request_options: RequestOptions | None = None,
    ) -> PasswordReset:
        """Create a password reset token

        Creates a one-time token that can be used to reset a user's password.

        Args:
            email: The email address of the user requesting a password reset.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            PasswordReset

        Raises:
            AuthorizationError: If the request is forbidden (403).
            NotFoundError: If the resource is not found (404).
            UnprocessableEntityError: If the request data is unprocessable (422).
            RateLimitExceededError: If rate limited (429).
            AuthenticationError: If the API key is invalid (401).
            ServerError: If the server returns a 5xx error.
        """
        body: dict[str, Any] = {
            "email": email,
        }
        return await self._client.request(
            method="post",
            path=("user_management", "password_reset"),
            body=body,
            model=PasswordReset,
            request_options=request_options,
        )

    async def confirm_password_reset(
        self,
        *,
        token: str,
        new_password: str,
        request_options: RequestOptions | None = None,
    ) -> ResetPasswordResponse:
        """Reset the password

        Sets a new password using the `token` query parameter from the link that the user received. Successfully resetting the password will verify a user's email, if it hasn't been verified yet.

        Args:
            token: The password reset token.
            new_password: The new password to set for the user.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            ResetPasswordResponse

        Raises:
            BadRequestError: If the request is malformed (400).
            AuthorizationError: If the request is forbidden (403).
            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] = {
            "token": token,
            "new_password": new_password,
        }
        return await self._client.request(
            method="post",
            path=("user_management", "password_reset", "confirm"),
            body=body,
            model=ResetPasswordResponse,
            request_options=request_options,
        )

    async def get_password_reset(
        self,
        id: str,
        *,
        request_options: RequestOptions | None = None,
    ) -> PasswordReset:
        """Get a password reset token

        Get the details of an existing password reset token that can be used to reset a user's password.

        Args:
            id: The ID of the password reset token.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            PasswordReset

        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 await self._client.request(
            method="get",
            path=("user_management", "password_reset", str(id)),
            model=PasswordReset,
            request_options=request_options,
        )

    async def list_users(
        self,
        *,
        limit: int | None = None,
        before: str | None = None,
        after: str | None = None,
        order: PaginationOrder | str | None = "desc",
        organization: str | None = None,
        organization_id: str | None = None,
        email: str | None = None,
        request_options: RequestOptions | None = None,
    ) -> AsyncPage[User]:
        """List users

        Get a list of all of your existing users matching the criteria specified.

        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`.
            organization: (deprecated) Filter users by the organization they are a member of. Deprecated in favor of `organization_id`.
            organization_id: Filter users by the organization they are a member of.
            email: Filter users by their email address.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            AsyncPage[User]

        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,
                "organization": organization,
                "organization_id": organization_id,
                "email": email,
            }.items()
            if v is not None
        }
        return await self._client.request_page(
            method="get",
            path=("user_management", "users"),
            model=User,
            params=params,
            request_options=request_options,
        )

    async def create_user(
        self,
        *,
        email: str,
        first_name: str | None | NotGiven = NOT_GIVEN,
        last_name: str | None | NotGiven = NOT_GIVEN,
        name: str | None | NotGiven = NOT_GIVEN,
        email_verified: bool | None | NotGiven = NOT_GIVEN,
        metadata: dict[str, str] | None | NotGiven = NOT_GIVEN,
        external_id: str | None | NotGiven = NOT_GIVEN,
        ip_address: str | None | NotGiven = NOT_GIVEN,
        user_agent: str | None | NotGiven = NOT_GIVEN,
        signals_id: str | None = None,
        password: PasswordPlaintext | PasswordHashed | None = None,
        request_options: RequestOptions | None = None,
    ) -> UserCreateResponse:
        """Create a user

        Create a new user in the current environment.

        Args:
            email: The email address of the user.
            first_name: The first name of the user.
            last_name: The last name of the user.
            name: The user's full name.
            email_verified: Whether the user's email has been verified.
            metadata: Object containing metadata key/value pairs associated with the user.
            external_id: The external ID of the user.
            ip_address: The IP address of the user's request.
            user_agent: The user agent string from the user's request.
            signals_id: An optional Radar signals ID to correlate client-side signals with this request.
            password: Identifies the password. One of: PasswordPlaintext, PasswordHashed.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            UserCreateResponse

        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 {
                "email": email,
                "signals_id": signals_id,
            }.items()
            if v is not None
        }
        if not isinstance(first_name, NotGiven):
            body["first_name"] = first_name
        if not isinstance(last_name, NotGiven):
            body["last_name"] = last_name
        if not isinstance(name, NotGiven):
            body["name"] = name
        if not isinstance(email_verified, NotGiven):
            body["email_verified"] = email_verified
        if not isinstance(metadata, NotGiven):
            body["metadata"] = metadata
        if not isinstance(external_id, NotGiven):
            body["external_id"] = external_id
        if not isinstance(ip_address, NotGiven):
            body["ip_address"] = ip_address
        if not isinstance(user_agent, NotGiven):
            body["user_agent"] = user_agent
        if password is not None:
            if isinstance(password, PasswordPlaintext):
                body["password"] = password.password
            elif isinstance(password, PasswordHashed):
                body["password_hash"] = password.password_hash
                body["password_hash_type"] = enum_value(password.password_hash_type)
        return await self._client.request(
            method="post",
            path=("user_management", "users"),
            body=body,
            model=UserCreateResponse,
            request_options=request_options,
        )

    async def get_user_by_external_id(
        self,
        external_id: str,
        *,
        request_options: RequestOptions | None = None,
    ) -> User:
        """Get a user by external ID

        Get the details of an existing user by an [external identifier](https://workos.com/docs/authkit/metadata/external-identifiers).

        Args:
            external_id: The external ID of the user.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            User

        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 await self._client.request(
            method="get",
            path=("user_management", "users", "external_id", str(external_id)),
            model=User,
            request_options=request_options,
        )

    async def get_user(
        self,
        id: str,
        *,
        request_options: RequestOptions | None = None,
    ) -> User:
        """Get a user

        Get the details of an existing user.

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

        Returns:
            User

        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 await self._client.request(
            method="get",
            path=("user_management", "users", str(id)),
            model=User,
            request_options=request_options,
        )

    async def update_user(
        self,
        id: str,
        *,
        email: str | None = None,
        first_name: str | None = None,
        last_name: str | None = None,
        name: str | None = None,
        email_verified: bool | None = None,
        metadata: dict[str, str] | None | NotGiven = NOT_GIVEN,
        external_id: str | None | NotGiven = NOT_GIVEN,
        locale: str | None | NotGiven = NOT_GIVEN,
        password: PasswordPlaintext | PasswordHashed | None = None,
        request_options: RequestOptions | None = None,
    ) -> User:
        """Update a user

        Updates properties of a user. The omitted properties will be left unchanged.

        Args:
            id: The unique ID of the user.
            email: The email address of the user.
            first_name: The first name of the user.
            last_name: The last name of the user.
            name: The user's full name.
            email_verified: Whether the user's email has been verified.
            metadata: Object containing metadata key/value pairs associated with the user.
            external_id: The external ID of the user.
            locale: The user's preferred locale.
            password: Identifies the password. One of: PasswordPlaintext, PasswordHashed.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            User

        Raises:
            BadRequestError: If the request is malformed (400).
            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 {
                "email": email,
                "first_name": first_name,
                "last_name": last_name,
                "name": name,
                "email_verified": email_verified,
            }.items()
            if v is not None
        }
        if not isinstance(metadata, NotGiven):
            body["metadata"] = metadata
        if not isinstance(external_id, NotGiven):
            body["external_id"] = external_id
        if not isinstance(locale, NotGiven):
            body["locale"] = locale
        if password is not None:
            if isinstance(password, PasswordPlaintext):
                body["password"] = password.password
            elif isinstance(password, PasswordHashed):
                body["password_hash"] = password.password_hash
                body["password_hash_type"] = enum_value(password.password_hash_type)
        return await self._client.request(
            method="put",
            path=("user_management", "users", str(id)),
            body=body,
            model=User,
            request_options=request_options,
        )

    async def delete_user(
        self,
        id: str,
        *,
        request_options: RequestOptions | None = None,
    ) -> None:
        """Delete a user

        Permanently deletes a user in the current environment. It cannot be undone.

        Args:
            id: The unique ID of the user.
            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=("user_management", "users", str(id)),
            request_options=request_options,
        )

    async def confirm_email_change(
        self,
        id: str,
        *,
        code: str,
        request_options: RequestOptions | None = None,
    ) -> EmailChangeConfirmation:
        """Confirm email change

        Confirms an email change using the one-time code received by the user.

        Args:
            id: The unique ID of the user.
            code: The one-time code used to confirm the email change.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            EmailChangeConfirmation

        Raises:
            BadRequestError: If the request is malformed (400).
            NotFoundError: If the resource is not found (404).
            ConflictError: If a conflict occurs (409).
            UnprocessableEntityError: If the request data is unprocessable (422).
            RateLimitExceededError: If rate limited (429).
            AuthenticationError: If the API key is invalid (401).
            ServerError: If the server returns a 5xx error.
        """
        body: dict[str, Any] = {
            "code": code,
        }
        return await self._client.request(
            method="post",
            path=("user_management", "users", str(id), "email_change", "confirm"),
            body=body,
            model=EmailChangeConfirmation,
            request_options=request_options,
        )

    async def send_email_change(
        self,
        id: str,
        *,
        new_email: str,
        request_options: RequestOptions | None = None,
    ) -> EmailChange:
        """Send email change code

        Sends an email that contains a one-time code used to change a user's email address.

        Args:
            id: The unique ID of the user.
            new_email: The new email address to change to.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            EmailChange

        Raises:
            NotFoundError: If the resource is not found (404).
            ConflictError: If a conflict occurs (409).
            UnprocessableEntityError: If the request data is unprocessable (422).
            RateLimitExceededError: If rate limited (429).
            AuthenticationError: If the API key is invalid (401).
            ServerError: If the server returns a 5xx error.
        """
        body: dict[str, Any] = {
            "new_email": new_email,
        }
        return await self._client.request(
            method="post",
            path=("user_management", "users", str(id), "email_change", "send"),
            body=body,
            model=EmailChange,
            request_options=request_options,
        )

    async def verify_email(
        self,
        id: str,
        *,
        code: str,
        request_options: RequestOptions | None = None,
    ) -> VerifyEmailResponse:
        """Verify email

        Verifies an email address using the one-time code received by the user.

        Args:
            id: The ID of the user.
            code: The one-time email verification code.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            VerifyEmailResponse

        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] = {
            "code": code,
        }
        return await self._client.request(
            method="post",
            path=("user_management", "users", str(id), "email_verification", "confirm"),
            body=body,
            model=VerifyEmailResponse,
            request_options=request_options,
        )

    async def send_verification_email(
        self,
        id: str,
        *,
        request_options: RequestOptions | None = None,
    ) -> SendVerificationEmailResponse:
        """Send verification email

        Sends an email that contains a one-time code used to verify a user's email address.

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

        Returns:
            SendVerificationEmailResponse

        Raises:
            BadRequestError: If the request is malformed (400).
            NotFoundError: If the resource is not found (404).
            RateLimitExceededError: If rate limited (429).
            AuthenticationError: If the API key is invalid (401).
            ServerError: If the server returns a 5xx error.
        """
        return await self._client.request(
            method="post",
            path=("user_management", "users", str(id), "email_verification", "send"),
            model=SendVerificationEmailResponse,
            request_options=request_options,
        )

    async def get_user_identities(
        self,
        id: str,
        *,
        request_options: RequestOptions | None = None,
    ) -> list[UserIdentitiesGetItem]:
        """Get user identities

        Get a list of identities associated with the user. A user can have multiple associated identities after going through [identity linking](https://workos.com/docs/authkit/identity-linking). Currently only OAuth identities are supported. More provider types may be added in the future.

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

        Returns:
            List[UserIdentitiesGetItem]

        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=("user_management", "users", str(id), "identities"),
            request_options=request_options,
        )
        return [
            UserIdentitiesGetItem.from_dict(cast(dict[str, Any], item)) for item in raw
        ]

    async def list_sessions(
        self,
        id: str,
        *,
        limit: int | None = None,
        before: str | None = None,
        after: str | None = None,
        order: PaginationOrder | str | None = "desc",
        request_options: RequestOptions | None = None,
    ) -> AsyncPage[UserSessionsListItem]:
        """List sessions

        Get a list of all active sessions for a specific user.

        Args:
            id: The ID of the user.
            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`.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            AsyncPage[UserSessionsListItem]

        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.
        """
        params = {
            k: v
            for k, v in {
                "limit": limit,
                "before": before,
                "after": after,
                "order": enum_value(order) if order is not None else None,
            }.items()
            if v is not None
        }
        return await self._client.request_page(
            method="get",
            path=("user_management", "users", str(id), "sessions"),
            model=UserSessionsListItem,
            params=params,
            request_options=request_options,
        )

    async def list_invitations(
        self,
        *,
        limit: int | None = None,
        before: str | None = None,
        after: str | None = None,
        order: PaginationOrder | str | None = "desc",
        organization_id: str | None = None,
        email: str | None = None,
        request_options: RequestOptions | None = None,
    ) -> AsyncPage[UserInvite]:
        """List invitations

        Get a list of all of invitations matching the criteria specified.

        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`.
            organization_id: The ID of the [organization](https://workos.com/docs/reference/organization) that the recipient will join.
            email: The email address of the recipient.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            AsyncPage[UserInvite]

        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,
                "organization_id": organization_id,
                "email": email,
            }.items()
            if v is not None
        }
        return await self._client.request_page(
            method="get",
            path=("user_management", "invitations"),
            model=UserInvite,
            params=params,
            request_options=request_options,
        )

    async def send_invitation(
        self,
        *,
        email: str,
        organization_id: str | None = None,
        role_slug: str | None = None,
        expires_in_days: int | None = None,
        inviter_user_id: str | None = None,
        locale: CreateUserInviteOptionsLocale | str | None = None,
        request_options: RequestOptions | None = None,
    ) -> UserInvite:
        """Send an invitation

        Sends an invitation email to the recipient.

        Args:
            email: The email address of the recipient.
            organization_id: The ID of the [organization](https://workos.com/docs/reference/organization) that the recipient will join.
            role_slug: The [role](https://workos.com/docs/authkit/roles) that the recipient will receive when they join the organization in the invitation.
            expires_in_days: How many days the invitations will be valid for. Must be between 1 and 30 days. Defaults to 7 days if not specified.
            inviter_user_id: The ID of the [user](https://workos.com/docs/reference/authkit/user) who invites the recipient. The invitation email will mention the name of this user.
            locale: The locale to use when rendering the invitation email. See [supported locales](https://workos.com/docs/authkit/hosted-ui/localization).
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            UserInvite

        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 {
                "email": email,
                "organization_id": organization_id,
                "role_slug": role_slug,
                "expires_in_days": expires_in_days,
                "inviter_user_id": inviter_user_id,
                "locale": enum_value(locale) if locale is not None else None,
            }.items()
            if v is not None
        }
        return await self._client.request(
            method="post",
            path=("user_management", "invitations"),
            body=body,
            model=UserInvite,
            request_options=request_options,
        )

    async def find_invitation_by_token(
        self,
        token: str,
        *,
        request_options: RequestOptions | None = None,
    ) -> UserInvite:
        """Find an invitation by token

        Retrieve an existing invitation using the token.

        Args:
            token: The token used to accept the invitation.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            UserInvite

        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 await self._client.request(
            method="get",
            path=("user_management", "invitations", "by_token", str(token)),
            model=UserInvite,
            request_options=request_options,
        )

    async def get_invitation(
        self,
        id: str,
        *,
        request_options: RequestOptions | None = None,
    ) -> UserInvite:
        """Get an invitation

        Get the details of an existing invitation.

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

        Returns:
            UserInvite

        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 await self._client.request(
            method="get",
            path=("user_management", "invitations", str(id)),
            model=UserInvite,
            request_options=request_options,
        )

    async def accept_invitation(
        self,
        id: str,
        *,
        request_options: RequestOptions | None = None,
    ) -> Invitation:
        """Accept an invitation

        Accepts an invitation and, if linked to an organization, activates the user's membership in that organization.

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

        Returns:
            Invitation

        Raises:
            BadRequestError: If the request is malformed (400).
            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 await self._client.request(
            method="post",
            path=("user_management", "invitations", str(id), "accept"),
            model=Invitation,
            request_options=request_options,
        )

    async def resend_invitation(
        self,
        id: str,
        *,
        locale: ResendUserInviteOptionsLocale | str | None = None,
        request_options: RequestOptions | None = None,
    ) -> UserInvite:
        """Resend an invitation

        Resends an invitation email to the recipient. The invitation must be in a pending state.

        Args:
            id: The unique ID of the invitation.
            locale: The locale to use when rendering the invitation email. See [supported locales](https://workos.com/docs/authkit/hosted-ui/localization).
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            UserInvite

        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 {
                "locale": enum_value(locale) if locale is not None else None,
            }.items()
            if v is not None
        }
        return await self._client.request(
            method="post",
            path=("user_management", "invitations", str(id), "resend"),
            body=body,
            model=UserInvite,
            request_options=request_options,
        )

    async def revoke_invitation(
        self,
        id: str,
        *,
        request_options: RequestOptions | None = None,
    ) -> Invitation:
        """Revoke an invitation

        Revokes an existing invitation.

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

        Returns:
            Invitation

        Raises:
            BadRequestError: If the request is malformed (400).
            AuthenticationError: If the API key is invalid (401).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        return await self._client.request(
            method="post",
            path=("user_management", "invitations", str(id), "revoke"),
            model=Invitation,
            request_options=request_options,
        )

    async def list_jwt_template(
        self,
        *,
        request_options: RequestOptions | None = None,
    ) -> JWTTemplateResponse:
        """Get JWT template

        Get the JWT template for the current environment.

        Returns:
            JWTTemplateResponse

        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 await self._client.request(
            method="get",
            path=("user_management", "jwt_template"),
            model=JWTTemplateResponse,
            request_options=request_options,
        )

    async def update_jwt_template(
        self,
        *,
        content: str,
        request_options: RequestOptions | None = None,
    ) -> JWTTemplateResponse:
        """Update JWT template

        Update the JWT template for the current environment.

        Args:
            content: The JWT template content as a Liquid template string.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            JWTTemplateResponse

        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.
        """
        body: dict[str, Any] = {
            "content": content,
        }
        return await self._client.request(
            method="put",
            path=("user_management", "jwt_template"),
            body=body,
            model=JWTTemplateResponse,
            request_options=request_options,
        )

    async def create_magic_auth(
        self,
        *,
        email: str,
        invitation_token: str | None = None,
        ip_address: str | None = None,
        user_agent: str | None = None,
        radar_auth_attempt_id: str | None = None,
        signals_id: str | None = None,
        request_options: RequestOptions | None = None,
    ) -> MagicAuthSendMagicAuthCodeAndReturnResponse:
        """Create a Magic Auth code

        Creates a one-time authentication code that can be sent to the user's email address. The code expires in 10 minutes. To verify the code, [authenticate the user with Magic Auth](https://workos.com/docs/reference/authkit/authentication/magic-auth).

        Args:
            email: The email address to send the magic code to.
            invitation_token: The invitation token to associate with this magic code.
            ip_address: The IP address of the user's request.
            user_agent: The user agent string from the user's request.
            radar_auth_attempt_id: The ID of an existing Radar authentication attempt to associate with this request.
            signals_id: An optional Radar signals ID to correlate client-side signals with this request.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            MagicAuthSendMagicAuthCodeAndReturnResponse

        Raises:
            BadRequestError: If the request is malformed (400).
            UnprocessableEntityError: If the request data is unprocessable (422).
            RateLimitExceededError: If rate limited (429).
            AuthenticationError: If the API key is invalid (401).
            ServerError: If the server returns a 5xx error.
        """
        body: dict[str, Any] = {
            k: v
            for k, v in {
                "email": email,
                "invitation_token": invitation_token,
                "ip_address": ip_address,
                "user_agent": user_agent,
                "radar_auth_attempt_id": radar_auth_attempt_id,
                "signals_id": signals_id,
            }.items()
            if v is not None
        }
        return await self._client.request(
            method="post",
            path=("user_management", "magic_auth"),
            body=body,
            model=MagicAuthSendMagicAuthCodeAndReturnResponse,
            request_options=request_options,
        )

    async def get_magic_auth(
        self,
        id: str,
        *,
        request_options: RequestOptions | None = None,
    ) -> MagicAuth:
        """Get Magic Auth code details

        Get the details of an existing [Magic Auth](https://workos.com/docs/reference/authkit/magic-auth) code that can be used to send an email to a user for authentication.

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

        Returns:
            MagicAuth

        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 await self._client.request(
            method="get",
            path=("user_management", "magic_auth", str(id)),
            model=MagicAuth,
            request_options=request_options,
        )

    async def list_redirect_uris(
        self,
        *,
        limit: int | None = None,
        before: str | None = None,
        after: str | None = None,
        order: PaginationOrder | str | None = "desc",
        request_options: RequestOptions | None = None,
    ) -> AsyncPage[RedirectUri]:
        """List redirect URIs

        Lists the redirect URIs for an environment.

        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`.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            AsyncPage[RedirectUri]

        Raises:
            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,
            }.items()
            if v is not None
        }
        return await self._client.request_page(
            method="get",
            path=("user_management", "redirect_uris"),
            model=RedirectUri,
            params=params,
            request_options=request_options,
        )

    async def create_redirect_uri(
        self,
        *,
        uri: str,
        request_options: RequestOptions | None = None,
    ) -> RedirectUri:
        """Create a redirect URI

        Creates a new redirect URI for an application.

        Args:
            uri: The redirect URI to create.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            RedirectUri

        Raises:
            BadRequestError: If the request is malformed (400).
            AuthenticationError: If the API key is invalid (401).
            UnprocessableEntityError: If the request data is unprocessable (422).
            RateLimitExceededError: If rate limited (429).
            ServerError: If the server returns a 5xx error.
        """
        body: dict[str, Any] = {
            "uri": uri,
        }
        return await self._client.request(
            method="post",
            path=("user_management", "redirect_uris"),
            body=body,
            model=RedirectUri,
            request_options=request_options,
        )

    async def delete_redirect_uris(
        self,
        id: str,
        *,
        request_options: RequestOptions | None = None,
    ) -> None:
        """Delete a redirect URI

        Deletes a redirect URI from an application.

        Args:
            id: The ID of the redirect URI to delete.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

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

    async def list_user_authorized_applications(
        self,
        user_id: str,
        *,
        limit: int | None = None,
        before: str | None = None,
        after: str | None = None,
        order: PaginationOrder | str | None = "desc",
        request_options: RequestOptions | None = None,
    ) -> AsyncPage[AuthorizedConnectApplicationListData]:
        """List authorized applications

        Get a list of all Connect applications that the user has authorized.

        Args:
            user_id: The ID of the user.
            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`.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            AsyncPage[AuthorizedConnectApplicationListData]

        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.
        """
        params = {
            k: v
            for k, v in {
                "limit": limit,
                "before": before,
                "after": after,
                "order": enum_value(order) if order is not None else None,
            }.items()
            if v is not None
        }
        return await self._client.request_page(
            method="get",
            path=("user_management", "users", str(user_id), "authorized_applications"),
            model=AuthorizedConnectApplicationListData,
            params=params,
            request_options=request_options,
        )

    async def delete_user_authorized_application(
        self,
        application_id: str,
        user_id: str,
        *,
        request_options: RequestOptions | None = None,
    ) -> None:
        """Delete an authorized application

        Delete an existing Authorized Connect Application.

        Args:
            application_id: The ID or client ID of the application.
            user_id: The ID of the user.
            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=(
                "user_management",
                "users",
                str(user_id),
                "authorized_applications",
                str(application_id),
            ),
            request_options=request_options,
        )

    async def list_user_api_keys(
        self,
        user_id: str,
        *,
        limit: int | None = None,
        before: str | None = None,
        after: str | None = None,
        order: PaginationOrder | str | None = "desc",
        organization_id: str | None = None,
        request_options: RequestOptions | None = None,
    ) -> AsyncPage[UserApiKey]:
        """List API keys for a user

        Get a list of API keys owned by a specific user.

        Args:
            user_id: Unique identifier of the user.
            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.
            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.
            order: Order the results by the creation time. Defaults to `desc`.
            organization_id: The ID of the organization to filter user API keys by. When provided, only API keys created against that organization membership are returned.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            AsyncPage[UserApiKey]

        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.
        """
        params = {
            k: v
            for k, v in {
                "limit": limit,
                "before": before,
                "after": after,
                "order": enum_value(order) if order is not None else None,
                "organization_id": organization_id,
            }.items()
            if v is not None
        }
        return await self._client.request_page(
            method="get",
            path=("user_management", "users", str(user_id), "api_keys"),
            model=UserApiKey,
            params=params,
            request_options=request_options,
        )

    async def create_user_api_key(
        self,
        user_id: str,
        *,
        name: str,
        organization_id: str,
        permissions: list[str] | None = None,
        expires_at: str | None = None,
        request_options: RequestOptions | None = None,
    ) -> UserApiKeyWithValue:
        """Create an API key for a user

        Create a new API key owned by a user. The user must have an active membership in the specified organization.

        Args:
            user_id: Unique identifier of the user.
            name: A descriptive name for the API key.
            organization_id: The ID of the organization the user API key is associated with. The user must have an active membership in this organization.
            permissions: The permission slugs to assign to the API key. Each permission must be enabled for user API keys.
            expires_at: The timestamp when the API key should expire. Must be a future timestamp. If omitted, the key does not expire.
            request_options: Per-request options. Supports extra_headers, timeout, max_retries, and base_url override.

        Returns:
            UserApiKeyWithValue

        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 {
                "name": name,
                "organization_id": organization_id,
                "permissions": permissions,
                "expires_at": expires_at,
            }.items()
            if v is not None
        }
        return await self._client.request(
            method="post",
            path=("user_management", "users", str(user_id), "api_keys"),
            body=body,
            model=UserApiKeyWithValue,
            request_options=request_options,
        )

    # @oagen-ignore-start

    def get_jwks_url(self, client_id: str | None = None) -> str:
        """Get the JWKS URL used to verify access tokens.

        Use this when integrating with a JWT library that fetches and caches
        the JWKS itself (e.g. ``PyJWKClient``). For the JWKS document, call
        :meth:`get_jwks` instead.

        Args:
            client_id: The WorkOS client ID. Defaults to the client's
                configured client_id.

        Returns:
            The JWKS URL.
        """
        resolved_client_id = client_id or self._client._require_client_id()
        return f"{self._client.base_url}sso/jwks/{resolved_client_id}"

    def load_sealed_session(
        self,
        *,
        session_data: str,
        cookie_password: str,
    ) -> AsyncSession:
        """Create an AsyncSession object from sealed session data.

        Args:
            session_data: The sealed session cookie value.
            cookie_password: The password used to seal the session cookie.

        Returns:
            AsyncSession: An async session object that can authenticate or refresh the session.
        """
        from ..session import AsyncSession

        return AsyncSession(
            client=self._client,
            session_data=session_data,
            cookie_password=cookie_password,
        )

    def authenticate_with_session_cookie(
        self,
        *,
        session_data: str,
        cookie_password: str,
    ) -> (
        AuthenticateWithSessionCookieSuccessResponse
        | AuthenticateWithSessionCookieErrorResponse
    ):
        """One-shot authenticate a sealed session cookie.

        Args:
            session_data: The sealed session cookie value.
            cookie_password: The password used to seal the session cookie.

        Returns:
            AuthenticateWithSessionCookieSuccessResponse if the session is valid,
            AuthenticateWithSessionCookieErrorResponse otherwise.
        """
        from ..session import AsyncSession

        session = AsyncSession(
            client=self._client,
            session_data=session_data,
            cookie_password=cookie_password,
        )
        return session.authenticate()

    async def get_authorization_url_with_pkce(
        self,
        *,
        redirect_uri: str,
        client_id: str | None = None,
        provider: UserManagementAuthenticationProvider | str | None = None,
        connection_id: str | None = None,
        organization_id: str | None = None,
        domain_hint: str | None = None,
        login_hint: str | None = None,
        screen_hint: UserManagementAuthenticationScreenHint | str | None = None,
        prompt: str | None = None,
        provider_scopes: list[str] | None = None,
        provider_query_params: dict[str, str] | None = None,
        invitation_token: str | None = None,
    ) -> dict[str, str]:
        """Generate an AuthKit authorization URL with auto-generated PKCE parameters.

        Args:
            redirect_uri: The URI to redirect to after authorization.
            client_id: The WorkOS client ID. Defaults to the client's configured ID.
            provider: An SSO provider to directly initiate authentication with.
            connection_id: The ID of a specific SSO connection to authenticate with.
            organization_id: The ID of the organization to authenticate into.
            domain_hint: A domain hint for SSO provider discovery.
            login_hint: A login hint (e.g., email) for the identity provider.
            screen_hint: Whether to show 'sign-in' or 'sign-up' screen.
            prompt: The OIDC prompt parameter.
            provider_scopes: Additional OAuth scopes to request from the provider.
            provider_query_params: Additional query parameters for the provider.
            invitation_token: A token to accept an organization invitation during auth.

        Returns:
            Dict with keys 'url', 'state', and 'code_verifier'.
        """
        from ..pkce import PKCE

        pkce = PKCE()
        pair = pkce.generate()
        state = pkce.generate_code_verifier(43)

        url = self.get_authorization_url(
            redirect_uri=redirect_uri,
            client_id=client_id,
            code_challenge=pair.code_challenge,
            code_challenge_method="S256",
            state=state,
            provider=provider,
            connection_id=connection_id,
            organization_id=organization_id,
            domain_hint=domain_hint,
            login_hint=login_hint,
            screen_hint=screen_hint,
            prompt=prompt,
            provider_scopes=provider_scopes,
            provider_query_params=provider_query_params,
            invitation_token=invitation_token,
        )
        return {"url": url, "state": state, "code_verifier": pair.code_verifier}

    async def authenticate_with_code_pkce(
        self,
        *,
        code: str,
        code_verifier: str,
        client_id: str | None = None,
        ip_address: str | None = None,
        device_id: str | None = None,
        user_agent: str | None = None,
        request_options: RequestOptions | None = None,
    ) -> AuthenticateResponse:
        """Exchange an authorization code using a PKCE code_verifier.

        Args:
            code: The authorization code received from the redirect.
            code_verifier: The PKCE code verifier generated alongside the code challenge.
            client_id: The WorkOS client ID. Defaults to the client's configured ID.
            ip_address: The IP address of the user's request.
            device_id: A unique identifier for the device.
            user_agent: The user agent string from the user's browser.
            request_options: Per-request options for headers, timeout, retries, or base URL.

        Returns:
            AuthenticateResponse: The authentication result with user and tokens.
        """
        resolved_client_id = client_id or (self._client.client_id or "")
        body: dict[str, Any] = {
            "grant_type": "authorization_code",
            "client_id": resolved_client_id,
            "code": code,
            "code_verifier": code_verifier,
        }
        if self._client._api_key:
            body["client_secret"] = self._client._api_key
        if ip_address is not None:
            body["ip_address"] = ip_address
        if device_id is not None:
            body["device_id"] = device_id
        if user_agent is not None:
            body["user_agent"] = user_agent

        return cast(
            AuthenticateResponse,
            await self._client.request(
                method="POST",
                path=("user_management", "authenticate"),
                body=body,
                model=AuthenticateResponse,
                request_options=request_options,
            ),
        )

    # @oagen-ignore-end
