"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""

from .basesdk import BaseSDK
from datetime import datetime
from factify import errors, models, utils
from factify._hooks import HookContext
from factify.types import OptionalNullable, UNSET
from factify.utils.unmarshal_json_response import unmarshal_json_response
from jsonpath import JSONPath
from typing import Any, Awaitable, Dict, List, Mapping, Optional, Union


class Invites(BaseSDK):
    def list(
        self,
        *,
        organization_id: str,
        status: Optional[List[models.OrganizationInviteStatus]] = None,
        page_token: Optional[str] = None,
        page_size: Optional[int] = None,
        email_contains: Optional[str] = None,
        email_exact: Optional[str] = None,
        sender_id: Optional[str] = None,
        created_after: Optional[datetime] = None,
        created_before: Optional[datetime] = None,
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> Optional[models.ListOrganizationInvitesResponseResponse]:
        r"""List organization invitations

        List invitations for an organization. Requires permission to invite organization members.

        :param organization_id: Organization to list invitations for.
            Pattern: org_[0-9a-hjkmnp-tv-z]{26}
        :param status: Filter by invitation status.
            If empty, returns all invitations.
            REST: ?status=pending or ?status=pending&status=expired
        :param page_token: Opaque pagination token from a previous response.
        :param page_size: Maximum number of items to return per page (1-100). Default: 50.
        :param email_contains: Case-insensitive substring match.
            REST: ?field.contains=value
        :param email_exact: Exact match (case-sensitive).
            REST: ?field.exact=value
        :param sender_id: Filter by sender. Only returns invitations sent by this user.
            REST: ?sender_id=user_01h2xcejqtf2nbrexx3vqjhp41
            Pattern: user_[0-9a-hjkmnp-tv-z]{26}
        :param created_after: Return results after this timestamp (inclusive).
        :param created_before: Return results before this timestamp (inclusive).
        :param retries: Override the default retry configuration for this method
        :param server_url: Override the default server URL for this method
        :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
        :param http_headers: Additional headers to set or replace on requests.
        """
        base_url = None
        url_variables = None
        if timeout_ms is None:
            timeout_ms = self.sdk_configuration.timeout_ms

        if server_url is not None:
            base_url = server_url
        else:
            base_url = self._get_url(base_url, url_variables)

        request = models.ListOrganizationInvitesRequest(
            organization_id=organization_id,
            status=status,
            page_token=page_token,
            page_size=page_size,
            email_contains=email_contains,
            email_exact=email_exact,
            sender_id=sender_id,
            created_after=created_after,
            created_before=created_before,
        )

        req = self._build_request(
            method="GET",
            path="/v1beta/organizations/{organization_id}/invites",
            base_url=base_url,
            url_variables=url_variables,
            request=request,
            request_body_required=False,
            request_has_path_params=True,
            request_has_query_params=True,
            user_agent_header="user-agent",
            accept_header_value="application/json",
            http_headers=http_headers,
            security=self.sdk_configuration.security,
            allow_empty_value=None,
            timeout_ms=timeout_ms,
        )

        if retries == UNSET:
            if self.sdk_configuration.retry_config is not UNSET:
                retries = self.sdk_configuration.retry_config

        retry_config = None
        if isinstance(retries, utils.RetryConfig):
            retry_config = (retries, ["429", "500", "502", "503", "504"])

        http_res = self.do_request(
            hook_ctx=HookContext(
                config=self.sdk_configuration,
                base_url=base_url or "",
                operation_id="listOrganizationInvites",
                oauth2_scopes=None,
                security_source=self.sdk_configuration.security,
            ),
            request=req,
            error_status_codes=["400", "401", "403", "404", "429", "4XX", "500", "5XX"],
            retry_config=retry_config,
        )

        def next_func() -> Optional[models.ListOrganizationInvitesResponseResponse]:
            body = utils.unmarshal_json(http_res.text, Union[Dict[Any, Any], List[Any]])

            next_cursor = JSONPath("$.pagination.next_page_token").parse(body)

            if len(next_cursor) == 0:
                return None

            next_cursor = next_cursor[0]
            if next_cursor is None or str(next_cursor).strip() == "":
                return None

            return self.list(
                organization_id=organization_id,
                status=status,
                page_token=next_cursor,
                page_size=page_size,
                email_contains=email_contains,
                email_exact=email_exact,
                sender_id=sender_id,
                created_after=created_after,
                created_before=created_before,
                retries=retries,
            )

        response_data: Any = None
        if utils.match_response(http_res, "200", "application/json"):
            return models.ListOrganizationInvitesResponseResponse(
                result=unmarshal_json_response(
                    models.ListOrganizationInvitesResponse, http_res
                ),
                next=next_func,
                headers={},
            )
        if utils.match_response(
            http_res, ["400", "401", "403", "404"], "application/json"
        ):
            response_data = unmarshal_json_response(errors.ErrorResponseData, http_res)
            raise errors.ErrorResponse(response_data, http_res)
        if utils.match_response(http_res, "429", "application/json"):
            response_data = unmarshal_json_response(errors.ErrorResponseData, http_res)
            raise errors.ErrorResponse(response_data, http_res)
        if utils.match_response(http_res, "500", "application/json"):
            response_data = unmarshal_json_response(errors.ErrorResponseData, http_res)
            raise errors.ErrorResponse(response_data, http_res)
        if utils.match_response(http_res, "4XX", "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise errors.FactifyDefaultError(
                "API error occurred", http_res, http_res_text
            )
        if utils.match_response(http_res, "5XX", "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise errors.FactifyDefaultError(
                "API error occurred", http_res, http_res_text
            )

        raise errors.FactifyDefaultError("Unexpected response received", http_res)

    async def list_async(
        self,
        *,
        organization_id: str,
        status: Optional[List[models.OrganizationInviteStatus]] = None,
        page_token: Optional[str] = None,
        page_size: Optional[int] = None,
        email_contains: Optional[str] = None,
        email_exact: Optional[str] = None,
        sender_id: Optional[str] = None,
        created_after: Optional[datetime] = None,
        created_before: Optional[datetime] = None,
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> Optional[models.ListOrganizationInvitesResponseResponse]:
        r"""List organization invitations

        List invitations for an organization. Requires permission to invite organization members.

        :param organization_id: Organization to list invitations for.
            Pattern: org_[0-9a-hjkmnp-tv-z]{26}
        :param status: Filter by invitation status.
            If empty, returns all invitations.
            REST: ?status=pending or ?status=pending&status=expired
        :param page_token: Opaque pagination token from a previous response.
        :param page_size: Maximum number of items to return per page (1-100). Default: 50.
        :param email_contains: Case-insensitive substring match.
            REST: ?field.contains=value
        :param email_exact: Exact match (case-sensitive).
            REST: ?field.exact=value
        :param sender_id: Filter by sender. Only returns invitations sent by this user.
            REST: ?sender_id=user_01h2xcejqtf2nbrexx3vqjhp41
            Pattern: user_[0-9a-hjkmnp-tv-z]{26}
        :param created_after: Return results after this timestamp (inclusive).
        :param created_before: Return results before this timestamp (inclusive).
        :param retries: Override the default retry configuration for this method
        :param server_url: Override the default server URL for this method
        :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
        :param http_headers: Additional headers to set or replace on requests.
        """
        base_url = None
        url_variables = None
        if timeout_ms is None:
            timeout_ms = self.sdk_configuration.timeout_ms

        if server_url is not None:
            base_url = server_url
        else:
            base_url = self._get_url(base_url, url_variables)

        request = models.ListOrganizationInvitesRequest(
            organization_id=organization_id,
            status=status,
            page_token=page_token,
            page_size=page_size,
            email_contains=email_contains,
            email_exact=email_exact,
            sender_id=sender_id,
            created_after=created_after,
            created_before=created_before,
        )

        req = self._build_request_async(
            method="GET",
            path="/v1beta/organizations/{organization_id}/invites",
            base_url=base_url,
            url_variables=url_variables,
            request=request,
            request_body_required=False,
            request_has_path_params=True,
            request_has_query_params=True,
            user_agent_header="user-agent",
            accept_header_value="application/json",
            http_headers=http_headers,
            security=self.sdk_configuration.security,
            allow_empty_value=None,
            timeout_ms=timeout_ms,
        )

        if retries == UNSET:
            if self.sdk_configuration.retry_config is not UNSET:
                retries = self.sdk_configuration.retry_config

        retry_config = None
        if isinstance(retries, utils.RetryConfig):
            retry_config = (retries, ["429", "500", "502", "503", "504"])

        http_res = await self.do_request_async(
            hook_ctx=HookContext(
                config=self.sdk_configuration,
                base_url=base_url or "",
                operation_id="listOrganizationInvites",
                oauth2_scopes=None,
                security_source=self.sdk_configuration.security,
            ),
            request=req,
            error_status_codes=["400", "401", "403", "404", "429", "4XX", "500", "5XX"],
            retry_config=retry_config,
        )

        def next_func() -> (
            Awaitable[Optional[models.ListOrganizationInvitesResponseResponse]]
        ):
            body = utils.unmarshal_json(http_res.text, Union[Dict[Any, Any], List[Any]])

            async def empty_result():
                return None

            next_cursor = JSONPath("$.pagination.next_page_token").parse(body)

            if len(next_cursor) == 0:
                return empty_result()

            next_cursor = next_cursor[0]
            if next_cursor is None or str(next_cursor).strip() == "":
                return empty_result()

            return self.list_async(
                organization_id=organization_id,
                status=status,
                page_token=next_cursor,
                page_size=page_size,
                email_contains=email_contains,
                email_exact=email_exact,
                sender_id=sender_id,
                created_after=created_after,
                created_before=created_before,
                retries=retries,
            )

        response_data: Any = None
        if utils.match_response(http_res, "200", "application/json"):
            return models.ListOrganizationInvitesResponseResponse(
                result=unmarshal_json_response(
                    models.ListOrganizationInvitesResponse, http_res
                ),
                next=next_func,
                headers={},
            )
        if utils.match_response(
            http_res, ["400", "401", "403", "404"], "application/json"
        ):
            response_data = unmarshal_json_response(errors.ErrorResponseData, http_res)
            raise errors.ErrorResponse(response_data, http_res)
        if utils.match_response(http_res, "429", "application/json"):
            response_data = unmarshal_json_response(errors.ErrorResponseData, http_res)
            raise errors.ErrorResponse(response_data, http_res)
        if utils.match_response(http_res, "500", "application/json"):
            response_data = unmarshal_json_response(errors.ErrorResponseData, http_res)
            raise errors.ErrorResponse(response_data, http_res)
        if utils.match_response(http_res, "4XX", "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise errors.FactifyDefaultError(
                "API error occurred", http_res, http_res_text
            )
        if utils.match_response(http_res, "5XX", "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise errors.FactifyDefaultError(
                "API error occurred", http_res, http_res_text
            )

        raise errors.FactifyDefaultError("Unexpected response received", http_res)

    def create(
        self,
        *,
        organization_id: str,
        email: str,
        idempotency_key: OptionalNullable[str] = UNSET,
        message: OptionalNullable[str] = UNSET,
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> models.CreateOrganizationInviteResponseResponse:
        r"""Invite a user to join an organization

        Creates an invitation and sends an email to the specified address. Returns FAILED_PRECONDITION if the email belongs to an existing organization member. Idempotency: If a PENDING invitation already exists for this email, the existing invitation is resent with a new token and refreshed expiration. Expired or revoked invitations are ignored - a new invitation is created.

        :param organization_id: Organization to invite the user to.
            Pattern: org_[0-9a-hjkmnp-tv-z]{26}
        :param email: Email address of the recipient.
        :param idempotency_key: Reserved for future use. Currently, idempotency is based on email matching:
            if a PENDING invitation exists for the same email in this organization,
            that invitation is resent rather than creating a duplicate.
        :param message: Optional custom message from the sender (max 2000 bytes to support ~500 multibyte characters).
        :param retries: Override the default retry configuration for this method
        :param server_url: Override the default server URL for this method
        :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
        :param http_headers: Additional headers to set or replace on requests.
        """
        base_url = None
        url_variables = None
        if timeout_ms is None:
            timeout_ms = self.sdk_configuration.timeout_ms

        if server_url is not None:
            base_url = server_url
        else:
            base_url = self._get_url(base_url, url_variables)

        request = models.CreateOrganizationInviteRequest(
            organization_id=organization_id,
            body=models.CreateOrganizationInviteCreateOrganizationInviteRequest(
                email=email,
                idempotency_key=idempotency_key,
                message=message,
            ),
        )

        req = self._build_request(
            method="POST",
            path="/v1beta/organizations/{organization_id}/invites",
            base_url=base_url,
            url_variables=url_variables,
            request=request,
            request_body_required=True,
            request_has_path_params=True,
            request_has_query_params=True,
            user_agent_header="user-agent",
            accept_header_value="application/json",
            http_headers=http_headers,
            security=self.sdk_configuration.security,
            get_serialized_body=lambda: utils.serialize_request_body(
                request.body,
                False,
                False,
                "json",
                models.CreateOrganizationInviteCreateOrganizationInviteRequest,
            ),
            allow_empty_value=None,
            timeout_ms=timeout_ms,
        )

        if retries == UNSET:
            if self.sdk_configuration.retry_config is not UNSET:
                retries = self.sdk_configuration.retry_config

        retry_config = None
        if isinstance(retries, utils.RetryConfig):
            retry_config = (retries, ["429", "500", "502", "503", "504"])

        http_res = self.do_request(
            hook_ctx=HookContext(
                config=self.sdk_configuration,
                base_url=base_url or "",
                operation_id="createOrganizationInvite",
                oauth2_scopes=None,
                security_source=self.sdk_configuration.security,
            ),
            request=req,
            error_status_codes=["400", "401", "403", "404", "429", "4XX", "500", "5XX"],
            retry_config=retry_config,
        )

        response_data: Any = None
        if utils.match_response(http_res, "200", "application/json"):
            return models.CreateOrganizationInviteResponseResponse(
                result=unmarshal_json_response(
                    models.CreateOrganizationInviteResponse, http_res
                ),
                headers={},
            )
        if utils.match_response(
            http_res, ["400", "401", "403", "404"], "application/json"
        ):
            response_data = unmarshal_json_response(errors.ErrorResponseData, http_res)
            raise errors.ErrorResponse(response_data, http_res)
        if utils.match_response(http_res, "429", "application/json"):
            response_data = unmarshal_json_response(errors.ErrorResponseData, http_res)
            raise errors.ErrorResponse(response_data, http_res)
        if utils.match_response(http_res, "500", "application/json"):
            response_data = unmarshal_json_response(errors.ErrorResponseData, http_res)
            raise errors.ErrorResponse(response_data, http_res)
        if utils.match_response(http_res, "4XX", "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise errors.FactifyDefaultError(
                "API error occurred", http_res, http_res_text
            )
        if utils.match_response(http_res, "5XX", "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise errors.FactifyDefaultError(
                "API error occurred", http_res, http_res_text
            )

        raise errors.FactifyDefaultError("Unexpected response received", http_res)

    async def create_async(
        self,
        *,
        organization_id: str,
        email: str,
        idempotency_key: OptionalNullable[str] = UNSET,
        message: OptionalNullable[str] = UNSET,
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> models.CreateOrganizationInviteResponseResponse:
        r"""Invite a user to join an organization

        Creates an invitation and sends an email to the specified address. Returns FAILED_PRECONDITION if the email belongs to an existing organization member. Idempotency: If a PENDING invitation already exists for this email, the existing invitation is resent with a new token and refreshed expiration. Expired or revoked invitations are ignored - a new invitation is created.

        :param organization_id: Organization to invite the user to.
            Pattern: org_[0-9a-hjkmnp-tv-z]{26}
        :param email: Email address of the recipient.
        :param idempotency_key: Reserved for future use. Currently, idempotency is based on email matching:
            if a PENDING invitation exists for the same email in this organization,
            that invitation is resent rather than creating a duplicate.
        :param message: Optional custom message from the sender (max 2000 bytes to support ~500 multibyte characters).
        :param retries: Override the default retry configuration for this method
        :param server_url: Override the default server URL for this method
        :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
        :param http_headers: Additional headers to set or replace on requests.
        """
        base_url = None
        url_variables = None
        if timeout_ms is None:
            timeout_ms = self.sdk_configuration.timeout_ms

        if server_url is not None:
            base_url = server_url
        else:
            base_url = self._get_url(base_url, url_variables)

        request = models.CreateOrganizationInviteRequest(
            organization_id=organization_id,
            body=models.CreateOrganizationInviteCreateOrganizationInviteRequest(
                email=email,
                idempotency_key=idempotency_key,
                message=message,
            ),
        )

        req = self._build_request_async(
            method="POST",
            path="/v1beta/organizations/{organization_id}/invites",
            base_url=base_url,
            url_variables=url_variables,
            request=request,
            request_body_required=True,
            request_has_path_params=True,
            request_has_query_params=True,
            user_agent_header="user-agent",
            accept_header_value="application/json",
            http_headers=http_headers,
            security=self.sdk_configuration.security,
            get_serialized_body=lambda: utils.serialize_request_body(
                request.body,
                False,
                False,
                "json",
                models.CreateOrganizationInviteCreateOrganizationInviteRequest,
            ),
            allow_empty_value=None,
            timeout_ms=timeout_ms,
        )

        if retries == UNSET:
            if self.sdk_configuration.retry_config is not UNSET:
                retries = self.sdk_configuration.retry_config

        retry_config = None
        if isinstance(retries, utils.RetryConfig):
            retry_config = (retries, ["429", "500", "502", "503", "504"])

        http_res = await self.do_request_async(
            hook_ctx=HookContext(
                config=self.sdk_configuration,
                base_url=base_url or "",
                operation_id="createOrganizationInvite",
                oauth2_scopes=None,
                security_source=self.sdk_configuration.security,
            ),
            request=req,
            error_status_codes=["400", "401", "403", "404", "429", "4XX", "500", "5XX"],
            retry_config=retry_config,
        )

        response_data: Any = None
        if utils.match_response(http_res, "200", "application/json"):
            return models.CreateOrganizationInviteResponseResponse(
                result=unmarshal_json_response(
                    models.CreateOrganizationInviteResponse, http_res
                ),
                headers={},
            )
        if utils.match_response(
            http_res, ["400", "401", "403", "404"], "application/json"
        ):
            response_data = unmarshal_json_response(errors.ErrorResponseData, http_res)
            raise errors.ErrorResponse(response_data, http_res)
        if utils.match_response(http_res, "429", "application/json"):
            response_data = unmarshal_json_response(errors.ErrorResponseData, http_res)
            raise errors.ErrorResponse(response_data, http_res)
        if utils.match_response(http_res, "500", "application/json"):
            response_data = unmarshal_json_response(errors.ErrorResponseData, http_res)
            raise errors.ErrorResponse(response_data, http_res)
        if utils.match_response(http_res, "4XX", "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise errors.FactifyDefaultError(
                "API error occurred", http_res, http_res_text
            )
        if utils.match_response(http_res, "5XX", "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise errors.FactifyDefaultError(
                "API error occurred", http_res, http_res_text
            )

        raise errors.FactifyDefaultError("Unexpected response received", http_res)

    def accept(
        self,
        *,
        organization_id: str,
        token: str,
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> models.AcceptOrganizationInviteResponseResponse:
        r"""Accept an invitation

        Accepts the invitation and adds the authenticated user as a member of the organization. The authenticated user's verified email must match the invitation email (case-insensitive). Returns PERMISSION_DENIED if emails don't match, FAILED_PRECONDITION if the user is already a member, or NOT_FOUND if the invitation is invalid/expired.

        :param organization_id: Organization the invitation belongs to (for validation).
            Pattern: org_[0-9a-hjkmnp-tv-z]{26}
        :param token: The invitation token from the email link.
        :param retries: Override the default retry configuration for this method
        :param server_url: Override the default server URL for this method
        :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
        :param http_headers: Additional headers to set or replace on requests.
        """
        base_url = None
        url_variables = None
        if timeout_ms is None:
            timeout_ms = self.sdk_configuration.timeout_ms

        if server_url is not None:
            base_url = server_url
        else:
            base_url = self._get_url(base_url, url_variables)

        request = models.AcceptOrganizationInviteRequest(
            organization_id=organization_id,
            body=models.AcceptOrganizationInviteAcceptOrganizationInviteRequest(
                token=token,
            ),
        )

        req = self._build_request(
            method="POST",
            path="/v1beta/organizations/{organization_id}/invites/accept",
            base_url=base_url,
            url_variables=url_variables,
            request=request,
            request_body_required=True,
            request_has_path_params=True,
            request_has_query_params=True,
            user_agent_header="user-agent",
            accept_header_value="application/json",
            http_headers=http_headers,
            security=self.sdk_configuration.security,
            get_serialized_body=lambda: utils.serialize_request_body(
                request.body,
                False,
                False,
                "json",
                models.AcceptOrganizationInviteAcceptOrganizationInviteRequest,
            ),
            allow_empty_value=None,
            timeout_ms=timeout_ms,
        )

        if retries == UNSET:
            if self.sdk_configuration.retry_config is not UNSET:
                retries = self.sdk_configuration.retry_config

        retry_config = None
        if isinstance(retries, utils.RetryConfig):
            retry_config = (retries, ["429", "500", "502", "503", "504"])

        http_res = self.do_request(
            hook_ctx=HookContext(
                config=self.sdk_configuration,
                base_url=base_url or "",
                operation_id="acceptOrganizationInvite",
                oauth2_scopes=None,
                security_source=self.sdk_configuration.security,
            ),
            request=req,
            error_status_codes=["400", "401", "403", "404", "429", "4XX", "500", "5XX"],
            retry_config=retry_config,
        )

        response_data: Any = None
        if utils.match_response(http_res, "200", "application/json"):
            return models.AcceptOrganizationInviteResponseResponse(
                result=unmarshal_json_response(
                    models.AcceptOrganizationInviteResponse, http_res
                ),
                headers={},
            )
        if utils.match_response(
            http_res, ["400", "401", "403", "404"], "application/json"
        ):
            response_data = unmarshal_json_response(errors.ErrorResponseData, http_res)
            raise errors.ErrorResponse(response_data, http_res)
        if utils.match_response(http_res, "429", "application/json"):
            response_data = unmarshal_json_response(errors.ErrorResponseData, http_res)
            raise errors.ErrorResponse(response_data, http_res)
        if utils.match_response(http_res, "500", "application/json"):
            response_data = unmarshal_json_response(errors.ErrorResponseData, http_res)
            raise errors.ErrorResponse(response_data, http_res)
        if utils.match_response(http_res, "4XX", "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise errors.FactifyDefaultError(
                "API error occurred", http_res, http_res_text
            )
        if utils.match_response(http_res, "5XX", "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise errors.FactifyDefaultError(
                "API error occurred", http_res, http_res_text
            )

        raise errors.FactifyDefaultError("Unexpected response received", http_res)

    async def accept_async(
        self,
        *,
        organization_id: str,
        token: str,
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> models.AcceptOrganizationInviteResponseResponse:
        r"""Accept an invitation

        Accepts the invitation and adds the authenticated user as a member of the organization. The authenticated user's verified email must match the invitation email (case-insensitive). Returns PERMISSION_DENIED if emails don't match, FAILED_PRECONDITION if the user is already a member, or NOT_FOUND if the invitation is invalid/expired.

        :param organization_id: Organization the invitation belongs to (for validation).
            Pattern: org_[0-9a-hjkmnp-tv-z]{26}
        :param token: The invitation token from the email link.
        :param retries: Override the default retry configuration for this method
        :param server_url: Override the default server URL for this method
        :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
        :param http_headers: Additional headers to set or replace on requests.
        """
        base_url = None
        url_variables = None
        if timeout_ms is None:
            timeout_ms = self.sdk_configuration.timeout_ms

        if server_url is not None:
            base_url = server_url
        else:
            base_url = self._get_url(base_url, url_variables)

        request = models.AcceptOrganizationInviteRequest(
            organization_id=organization_id,
            body=models.AcceptOrganizationInviteAcceptOrganizationInviteRequest(
                token=token,
            ),
        )

        req = self._build_request_async(
            method="POST",
            path="/v1beta/organizations/{organization_id}/invites/accept",
            base_url=base_url,
            url_variables=url_variables,
            request=request,
            request_body_required=True,
            request_has_path_params=True,
            request_has_query_params=True,
            user_agent_header="user-agent",
            accept_header_value="application/json",
            http_headers=http_headers,
            security=self.sdk_configuration.security,
            get_serialized_body=lambda: utils.serialize_request_body(
                request.body,
                False,
                False,
                "json",
                models.AcceptOrganizationInviteAcceptOrganizationInviteRequest,
            ),
            allow_empty_value=None,
            timeout_ms=timeout_ms,
        )

        if retries == UNSET:
            if self.sdk_configuration.retry_config is not UNSET:
                retries = self.sdk_configuration.retry_config

        retry_config = None
        if isinstance(retries, utils.RetryConfig):
            retry_config = (retries, ["429", "500", "502", "503", "504"])

        http_res = await self.do_request_async(
            hook_ctx=HookContext(
                config=self.sdk_configuration,
                base_url=base_url or "",
                operation_id="acceptOrganizationInvite",
                oauth2_scopes=None,
                security_source=self.sdk_configuration.security,
            ),
            request=req,
            error_status_codes=["400", "401", "403", "404", "429", "4XX", "500", "5XX"],
            retry_config=retry_config,
        )

        response_data: Any = None
        if utils.match_response(http_res, "200", "application/json"):
            return models.AcceptOrganizationInviteResponseResponse(
                result=unmarshal_json_response(
                    models.AcceptOrganizationInviteResponse, http_res
                ),
                headers={},
            )
        if utils.match_response(
            http_res, ["400", "401", "403", "404"], "application/json"
        ):
            response_data = unmarshal_json_response(errors.ErrorResponseData, http_res)
            raise errors.ErrorResponse(response_data, http_res)
        if utils.match_response(http_res, "429", "application/json"):
            response_data = unmarshal_json_response(errors.ErrorResponseData, http_res)
            raise errors.ErrorResponse(response_data, http_res)
        if utils.match_response(http_res, "500", "application/json"):
            response_data = unmarshal_json_response(errors.ErrorResponseData, http_res)
            raise errors.ErrorResponse(response_data, http_res)
        if utils.match_response(http_res, "4XX", "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise errors.FactifyDefaultError(
                "API error occurred", http_res, http_res_text
            )
        if utils.match_response(http_res, "5XX", "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise errors.FactifyDefaultError(
                "API error occurred", http_res, http_res_text
            )

        raise errors.FactifyDefaultError("Unexpected response received", http_res)

    def resend(
        self,
        *,
        organization_id: str,
        invite_id: str,
        body: Union[
            models.ResendOrganizationInviteResendOrganizationInviteRequest,
            models.ResendOrganizationInviteResendOrganizationInviteRequestTypedDict,
        ],
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> models.ResendOrganizationInviteResponseResponse:
        r"""Resend an invitation email

        Resend an invitation email to the recipient. Useful if the original email was lost or expired. Requires permission to invite organization members.

        :param organization_id: Organization the invitation belongs to.
            Pattern: org_[0-9a-hjkmnp-tv-z]{26}
        :param invite_id: Invitation ID to resend.
            Pattern: inv_[0-9a-hjkmnp-tv-z]{26}
        :param body:
        :param retries: Override the default retry configuration for this method
        :param server_url: Override the default server URL for this method
        :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
        :param http_headers: Additional headers to set or replace on requests.
        """
        base_url = None
        url_variables = None
        if timeout_ms is None:
            timeout_ms = self.sdk_configuration.timeout_ms

        if server_url is not None:
            base_url = server_url
        else:
            base_url = self._get_url(base_url, url_variables)

        request = models.ResendOrganizationInviteRequest(
            organization_id=organization_id,
            invite_id=invite_id,
            body=utils.get_pydantic_model(
                body, models.ResendOrganizationInviteResendOrganizationInviteRequest
            ),
        )

        req = self._build_request(
            method="POST",
            path="/v1beta/organizations/{organization_id}/invites/{invite_id}/resend",
            base_url=base_url,
            url_variables=url_variables,
            request=request,
            request_body_required=True,
            request_has_path_params=True,
            request_has_query_params=True,
            user_agent_header="user-agent",
            accept_header_value="application/json",
            http_headers=http_headers,
            security=self.sdk_configuration.security,
            get_serialized_body=lambda: utils.serialize_request_body(
                request.body,
                False,
                False,
                "json",
                models.ResendOrganizationInviteResendOrganizationInviteRequest,
            ),
            allow_empty_value=None,
            timeout_ms=timeout_ms,
        )

        if retries == UNSET:
            if self.sdk_configuration.retry_config is not UNSET:
                retries = self.sdk_configuration.retry_config

        retry_config = None
        if isinstance(retries, utils.RetryConfig):
            retry_config = (retries, ["429", "500", "502", "503", "504"])

        http_res = self.do_request(
            hook_ctx=HookContext(
                config=self.sdk_configuration,
                base_url=base_url or "",
                operation_id="resendOrganizationInvite",
                oauth2_scopes=None,
                security_source=self.sdk_configuration.security,
            ),
            request=req,
            error_status_codes=["400", "401", "403", "404", "429", "4XX", "500", "5XX"],
            retry_config=retry_config,
        )

        response_data: Any = None
        if utils.match_response(http_res, "200", "application/json"):
            return models.ResendOrganizationInviteResponseResponse(
                result=unmarshal_json_response(
                    models.ResendOrganizationInviteResponse, http_res
                ),
                headers={},
            )
        if utils.match_response(
            http_res, ["400", "401", "403", "404"], "application/json"
        ):
            response_data = unmarshal_json_response(errors.ErrorResponseData, http_res)
            raise errors.ErrorResponse(response_data, http_res)
        if utils.match_response(http_res, "429", "application/json"):
            response_data = unmarshal_json_response(errors.ErrorResponseData, http_res)
            raise errors.ErrorResponse(response_data, http_res)
        if utils.match_response(http_res, "500", "application/json"):
            response_data = unmarshal_json_response(errors.ErrorResponseData, http_res)
            raise errors.ErrorResponse(response_data, http_res)
        if utils.match_response(http_res, "4XX", "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise errors.FactifyDefaultError(
                "API error occurred", http_res, http_res_text
            )
        if utils.match_response(http_res, "5XX", "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise errors.FactifyDefaultError(
                "API error occurred", http_res, http_res_text
            )

        raise errors.FactifyDefaultError("Unexpected response received", http_res)

    async def resend_async(
        self,
        *,
        organization_id: str,
        invite_id: str,
        body: Union[
            models.ResendOrganizationInviteResendOrganizationInviteRequest,
            models.ResendOrganizationInviteResendOrganizationInviteRequestTypedDict,
        ],
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> models.ResendOrganizationInviteResponseResponse:
        r"""Resend an invitation email

        Resend an invitation email to the recipient. Useful if the original email was lost or expired. Requires permission to invite organization members.

        :param organization_id: Organization the invitation belongs to.
            Pattern: org_[0-9a-hjkmnp-tv-z]{26}
        :param invite_id: Invitation ID to resend.
            Pattern: inv_[0-9a-hjkmnp-tv-z]{26}
        :param body:
        :param retries: Override the default retry configuration for this method
        :param server_url: Override the default server URL for this method
        :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
        :param http_headers: Additional headers to set or replace on requests.
        """
        base_url = None
        url_variables = None
        if timeout_ms is None:
            timeout_ms = self.sdk_configuration.timeout_ms

        if server_url is not None:
            base_url = server_url
        else:
            base_url = self._get_url(base_url, url_variables)

        request = models.ResendOrganizationInviteRequest(
            organization_id=organization_id,
            invite_id=invite_id,
            body=utils.get_pydantic_model(
                body, models.ResendOrganizationInviteResendOrganizationInviteRequest
            ),
        )

        req = self._build_request_async(
            method="POST",
            path="/v1beta/organizations/{organization_id}/invites/{invite_id}/resend",
            base_url=base_url,
            url_variables=url_variables,
            request=request,
            request_body_required=True,
            request_has_path_params=True,
            request_has_query_params=True,
            user_agent_header="user-agent",
            accept_header_value="application/json",
            http_headers=http_headers,
            security=self.sdk_configuration.security,
            get_serialized_body=lambda: utils.serialize_request_body(
                request.body,
                False,
                False,
                "json",
                models.ResendOrganizationInviteResendOrganizationInviteRequest,
            ),
            allow_empty_value=None,
            timeout_ms=timeout_ms,
        )

        if retries == UNSET:
            if self.sdk_configuration.retry_config is not UNSET:
                retries = self.sdk_configuration.retry_config

        retry_config = None
        if isinstance(retries, utils.RetryConfig):
            retry_config = (retries, ["429", "500", "502", "503", "504"])

        http_res = await self.do_request_async(
            hook_ctx=HookContext(
                config=self.sdk_configuration,
                base_url=base_url or "",
                operation_id="resendOrganizationInvite",
                oauth2_scopes=None,
                security_source=self.sdk_configuration.security,
            ),
            request=req,
            error_status_codes=["400", "401", "403", "404", "429", "4XX", "500", "5XX"],
            retry_config=retry_config,
        )

        response_data: Any = None
        if utils.match_response(http_res, "200", "application/json"):
            return models.ResendOrganizationInviteResponseResponse(
                result=unmarshal_json_response(
                    models.ResendOrganizationInviteResponse, http_res
                ),
                headers={},
            )
        if utils.match_response(
            http_res, ["400", "401", "403", "404"], "application/json"
        ):
            response_data = unmarshal_json_response(errors.ErrorResponseData, http_res)
            raise errors.ErrorResponse(response_data, http_res)
        if utils.match_response(http_res, "429", "application/json"):
            response_data = unmarshal_json_response(errors.ErrorResponseData, http_res)
            raise errors.ErrorResponse(response_data, http_res)
        if utils.match_response(http_res, "500", "application/json"):
            response_data = unmarshal_json_response(errors.ErrorResponseData, http_res)
            raise errors.ErrorResponse(response_data, http_res)
        if utils.match_response(http_res, "4XX", "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise errors.FactifyDefaultError(
                "API error occurred", http_res, http_res_text
            )
        if utils.match_response(http_res, "5XX", "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise errors.FactifyDefaultError(
                "API error occurred", http_res, http_res_text
            )

        raise errors.FactifyDefaultError("Unexpected response received", http_res)

    def revoke(
        self,
        *,
        organization_id: str,
        invite_id: str,
        body: Union[
            models.RevokeOrganizationInviteRevokeOrganizationInviteRequest,
            models.RevokeOrganizationInviteRevokeOrganizationInviteRequestTypedDict,
        ],
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> models.RevokeOrganizationInviteResponseResponse:
        r"""Revoke an invitation

        Revoke a pending invitation, preventing the recipient from joining. Requires permission to manage organization members.

        :param organization_id: Organization the invitation belongs to.
            Pattern: org_[0-9a-hjkmnp-tv-z]{26}
        :param invite_id: Invitation ID to revoke.
            Pattern: inv_[0-9a-hjkmnp-tv-z]{26}
        :param body:
        :param retries: Override the default retry configuration for this method
        :param server_url: Override the default server URL for this method
        :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
        :param http_headers: Additional headers to set or replace on requests.
        """
        base_url = None
        url_variables = None
        if timeout_ms is None:
            timeout_ms = self.sdk_configuration.timeout_ms

        if server_url is not None:
            base_url = server_url
        else:
            base_url = self._get_url(base_url, url_variables)

        request = models.RevokeOrganizationInviteRequest(
            organization_id=organization_id,
            invite_id=invite_id,
            body=utils.get_pydantic_model(
                body, models.RevokeOrganizationInviteRevokeOrganizationInviteRequest
            ),
        )

        req = self._build_request(
            method="POST",
            path="/v1beta/organizations/{organization_id}/invites/{invite_id}/revoke",
            base_url=base_url,
            url_variables=url_variables,
            request=request,
            request_body_required=True,
            request_has_path_params=True,
            request_has_query_params=True,
            user_agent_header="user-agent",
            accept_header_value="application/json",
            http_headers=http_headers,
            security=self.sdk_configuration.security,
            get_serialized_body=lambda: utils.serialize_request_body(
                request.body,
                False,
                False,
                "json",
                models.RevokeOrganizationInviteRevokeOrganizationInviteRequest,
            ),
            allow_empty_value=None,
            timeout_ms=timeout_ms,
        )

        if retries == UNSET:
            if self.sdk_configuration.retry_config is not UNSET:
                retries = self.sdk_configuration.retry_config

        retry_config = None
        if isinstance(retries, utils.RetryConfig):
            retry_config = (retries, ["429", "500", "502", "503", "504"])

        http_res = self.do_request(
            hook_ctx=HookContext(
                config=self.sdk_configuration,
                base_url=base_url or "",
                operation_id="revokeOrganizationInvite",
                oauth2_scopes=None,
                security_source=self.sdk_configuration.security,
            ),
            request=req,
            error_status_codes=["400", "401", "403", "404", "429", "4XX", "500", "5XX"],
            retry_config=retry_config,
        )

        response_data: Any = None
        if utils.match_response(http_res, "200", "application/json"):
            return models.RevokeOrganizationInviteResponseResponse(
                result=unmarshal_json_response(
                    models.RevokeOrganizationInviteResponse, http_res
                ),
                headers={},
            )
        if utils.match_response(
            http_res, ["400", "401", "403", "404"], "application/json"
        ):
            response_data = unmarshal_json_response(errors.ErrorResponseData, http_res)
            raise errors.ErrorResponse(response_data, http_res)
        if utils.match_response(http_res, "429", "application/json"):
            response_data = unmarshal_json_response(errors.ErrorResponseData, http_res)
            raise errors.ErrorResponse(response_data, http_res)
        if utils.match_response(http_res, "500", "application/json"):
            response_data = unmarshal_json_response(errors.ErrorResponseData, http_res)
            raise errors.ErrorResponse(response_data, http_res)
        if utils.match_response(http_res, "4XX", "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise errors.FactifyDefaultError(
                "API error occurred", http_res, http_res_text
            )
        if utils.match_response(http_res, "5XX", "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise errors.FactifyDefaultError(
                "API error occurred", http_res, http_res_text
            )

        raise errors.FactifyDefaultError("Unexpected response received", http_res)

    async def revoke_async(
        self,
        *,
        organization_id: str,
        invite_id: str,
        body: Union[
            models.RevokeOrganizationInviteRevokeOrganizationInviteRequest,
            models.RevokeOrganizationInviteRevokeOrganizationInviteRequestTypedDict,
        ],
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> models.RevokeOrganizationInviteResponseResponse:
        r"""Revoke an invitation

        Revoke a pending invitation, preventing the recipient from joining. Requires permission to manage organization members.

        :param organization_id: Organization the invitation belongs to.
            Pattern: org_[0-9a-hjkmnp-tv-z]{26}
        :param invite_id: Invitation ID to revoke.
            Pattern: inv_[0-9a-hjkmnp-tv-z]{26}
        :param body:
        :param retries: Override the default retry configuration for this method
        :param server_url: Override the default server URL for this method
        :param timeout_ms: Override the default request timeout configuration for this method in milliseconds
        :param http_headers: Additional headers to set or replace on requests.
        """
        base_url = None
        url_variables = None
        if timeout_ms is None:
            timeout_ms = self.sdk_configuration.timeout_ms

        if server_url is not None:
            base_url = server_url
        else:
            base_url = self._get_url(base_url, url_variables)

        request = models.RevokeOrganizationInviteRequest(
            organization_id=organization_id,
            invite_id=invite_id,
            body=utils.get_pydantic_model(
                body, models.RevokeOrganizationInviteRevokeOrganizationInviteRequest
            ),
        )

        req = self._build_request_async(
            method="POST",
            path="/v1beta/organizations/{organization_id}/invites/{invite_id}/revoke",
            base_url=base_url,
            url_variables=url_variables,
            request=request,
            request_body_required=True,
            request_has_path_params=True,
            request_has_query_params=True,
            user_agent_header="user-agent",
            accept_header_value="application/json",
            http_headers=http_headers,
            security=self.sdk_configuration.security,
            get_serialized_body=lambda: utils.serialize_request_body(
                request.body,
                False,
                False,
                "json",
                models.RevokeOrganizationInviteRevokeOrganizationInviteRequest,
            ),
            allow_empty_value=None,
            timeout_ms=timeout_ms,
        )

        if retries == UNSET:
            if self.sdk_configuration.retry_config is not UNSET:
                retries = self.sdk_configuration.retry_config

        retry_config = None
        if isinstance(retries, utils.RetryConfig):
            retry_config = (retries, ["429", "500", "502", "503", "504"])

        http_res = await self.do_request_async(
            hook_ctx=HookContext(
                config=self.sdk_configuration,
                base_url=base_url or "",
                operation_id="revokeOrganizationInvite",
                oauth2_scopes=None,
                security_source=self.sdk_configuration.security,
            ),
            request=req,
            error_status_codes=["400", "401", "403", "404", "429", "4XX", "500", "5XX"],
            retry_config=retry_config,
        )

        response_data: Any = None
        if utils.match_response(http_res, "200", "application/json"):
            return models.RevokeOrganizationInviteResponseResponse(
                result=unmarshal_json_response(
                    models.RevokeOrganizationInviteResponse, http_res
                ),
                headers={},
            )
        if utils.match_response(
            http_res, ["400", "401", "403", "404"], "application/json"
        ):
            response_data = unmarshal_json_response(errors.ErrorResponseData, http_res)
            raise errors.ErrorResponse(response_data, http_res)
        if utils.match_response(http_res, "429", "application/json"):
            response_data = unmarshal_json_response(errors.ErrorResponseData, http_res)
            raise errors.ErrorResponse(response_data, http_res)
        if utils.match_response(http_res, "500", "application/json"):
            response_data = unmarshal_json_response(errors.ErrorResponseData, http_res)
            raise errors.ErrorResponse(response_data, http_res)
        if utils.match_response(http_res, "4XX", "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise errors.FactifyDefaultError(
                "API error occurred", http_res, http_res_text
            )
        if utils.match_response(http_res, "5XX", "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise errors.FactifyDefaultError(
                "API error occurred", http_res, http_res_text
            )

        raise errors.FactifyDefaultError("Unexpected response received", http_res)
