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

from .basesdk import BaseSDK
from censys_platform import models, utils
from censys_platform._hooks import HookContext
from censys_platform.types import BaseModel, OptionalNullable, UNSET
from censys_platform.utils.unmarshal_json_response import unmarshal_json_response
from typing import Any, Mapping, Optional, Union, cast


class ThreatHunting(BaseSDK):
    r"""Endpoints related to the Threat Hunting product"""

    def get_host_observations_with_certificate(
        self,
        *,
        request: Union[
            models.V3ThreathuntingGetHostObservationsWithCertificateRequest,
            models.V3ThreathuntingGetHostObservationsWithCertificateRequestTypedDict,
        ],
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> models.V3ThreathuntingGetHostObservationsWithCertificateResponse:
        r"""Get host history for a certificate

        Retrieve the historical observations of hosts associated with a certificate. This is useful for threat hunting, detection engineering, and timeline generation. Certificate history is also visible to Threat Hunting users in the Platform UI on the [certificate timeline](https://docs.censys.com/docs/platform-threat-hunting-use-cert-history-to-build-better-detections#/).<br><br>You can define a specific time frame of interest. If you do not specify a time frame, this endpoint will search the historical dataset that is available to your account. You may also filter results by port and transport protocol.<br><br>This endpoint is available to organizations that have access to the Threat Hunting module. It costs 5 credits per page of results.

        :param request: The request object to send.
        :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)

        if not isinstance(request, BaseModel):
            request = utils.unmarshal(
                request, models.V3ThreathuntingGetHostObservationsWithCertificateRequest
            )
        request = cast(
            models.V3ThreathuntingGetHostObservationsWithCertificateRequest, request
        )

        req = self._build_request(
            method="GET",
            path="/v3/threat-hunting/certificate/{certificate_id}/observations/hosts",
            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,
            _globals=models.V3ThreathuntingGetHostObservationsWithCertificateGlobals(
                organization_id=self.sdk_configuration.globals.organization_id,
            ),
            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="v3-threathunting-get-host-observations-with-certificate",
                oauth2_scopes=None,
                security_source=self.sdk_configuration.security,
            ),
            request=req,
            error_status_codes=["401", "403", "4XX", "5XX"],
            retry_config=retry_config,
        )

        response_data: Any = None
        if utils.match_response(http_res, "200", "application/json"):
            return models.V3ThreathuntingGetHostObservationsWithCertificateResponse(
                result=unmarshal_json_response(
                    models.ResponseEnvelopeHostObservationResponse, http_res
                ),
                headers=utils.get_response_headers(http_res.headers),
            )
        if utils.match_response(http_res, "401", "application/json"):
            response_data = unmarshal_json_response(
                models.AuthenticationErrorData, http_res
            )
            raise models.AuthenticationError(response_data, http_res)
        if utils.match_response(http_res, "403", "application/problem+json"):
            response_data = unmarshal_json_response(models.ErrorModelData, http_res)
            raise models.ErrorModel(response_data, http_res)
        if utils.match_response(http_res, "4XX", "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise models.SDKError("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 models.SDKError("API error occurred", http_res, http_res_text)

        raise models.SDKError("Unexpected response received", http_res)

    async def get_host_observations_with_certificate_async(
        self,
        *,
        request: Union[
            models.V3ThreathuntingGetHostObservationsWithCertificateRequest,
            models.V3ThreathuntingGetHostObservationsWithCertificateRequestTypedDict,
        ],
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> models.V3ThreathuntingGetHostObservationsWithCertificateResponse:
        r"""Get host history for a certificate

        Retrieve the historical observations of hosts associated with a certificate. This is useful for threat hunting, detection engineering, and timeline generation. Certificate history is also visible to Threat Hunting users in the Platform UI on the [certificate timeline](https://docs.censys.com/docs/platform-threat-hunting-use-cert-history-to-build-better-detections#/).<br><br>You can define a specific time frame of interest. If you do not specify a time frame, this endpoint will search the historical dataset that is available to your account. You may also filter results by port and transport protocol.<br><br>This endpoint is available to organizations that have access to the Threat Hunting module. It costs 5 credits per page of results.

        :param request: The request object to send.
        :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)

        if not isinstance(request, BaseModel):
            request = utils.unmarshal(
                request, models.V3ThreathuntingGetHostObservationsWithCertificateRequest
            )
        request = cast(
            models.V3ThreathuntingGetHostObservationsWithCertificateRequest, request
        )

        req = self._build_request_async(
            method="GET",
            path="/v3/threat-hunting/certificate/{certificate_id}/observations/hosts",
            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,
            _globals=models.V3ThreathuntingGetHostObservationsWithCertificateGlobals(
                organization_id=self.sdk_configuration.globals.organization_id,
            ),
            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="v3-threathunting-get-host-observations-with-certificate",
                oauth2_scopes=None,
                security_source=self.sdk_configuration.security,
            ),
            request=req,
            error_status_codes=["401", "403", "4XX", "5XX"],
            retry_config=retry_config,
        )

        response_data: Any = None
        if utils.match_response(http_res, "200", "application/json"):
            return models.V3ThreathuntingGetHostObservationsWithCertificateResponse(
                result=unmarshal_json_response(
                    models.ResponseEnvelopeHostObservationResponse, http_res
                ),
                headers=utils.get_response_headers(http_res.headers),
            )
        if utils.match_response(http_res, "401", "application/json"):
            response_data = unmarshal_json_response(
                models.AuthenticationErrorData, http_res
            )
            raise models.AuthenticationError(response_data, http_res)
        if utils.match_response(http_res, "403", "application/problem+json"):
            response_data = unmarshal_json_response(models.ErrorModelData, http_res)
            raise models.ErrorModel(response_data, http_res)
        if utils.match_response(http_res, "4XX", "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise models.SDKError("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 models.SDKError("API error occurred", http_res, http_res_text)

        raise models.SDKError("Unexpected response received", http_res)

    def create_tracked_scan(
        self,
        *,
        scans_discovery_input_body: Union[
            models.ScansDiscoveryInputBody, models.ScansDiscoveryInputBodyTypedDict
        ],
        organization_id: Optional[str] = None,
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> models.V3ThreathuntingScansDiscoveryResponse:
        r"""Live Discovery: Initiate a new scan

        Initiate a scan to look for a currently unobserved service at a specific IP and port (`ip:port`) or hostname and port (`hostname:port`). This is equivalent to the [Live Discovery](https://docs.censys.com/docs/platform-threat-hunting-use-live-scan-and-rescan-to-validate-infrastructure#/) feature available in the UI, but you can also target web properties in addition to hosts.<br><br>The scan may take several minutes to complete. The response will contain a scan ID that you can use to [monitor the scan's status](https://docs.censys.com/reference/v3-threathunting-scans-get#/). After the scan completes, perform a lookup on the target asset to retrieve detailed scan information.<br><br>This endpoint is available to organizations that have access to the Threat Hunting module. It costs 15 credits to execute this endpoint.

        :param scans_discovery_input_body:
        :param organization_id: The ID of a Censys organization to associate the request with. See the [Getting Started docs](https://docs.censys.com/reference/get-started#step-3-find-and-use-your-organization-id-optional) for more information.
        :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.V3ThreathuntingScansDiscoveryRequest(
            organization_id=organization_id,
            scans_discovery_input_body=utils.get_pydantic_model(
                scans_discovery_input_body, models.ScansDiscoveryInputBody
            ),
        )

        req = self._build_request(
            method="POST",
            path="/v3/threat-hunting/scans/discovery",
            base_url=base_url,
            url_variables=url_variables,
            request=request,
            request_body_required=True,
            request_has_path_params=False,
            request_has_query_params=True,
            user_agent_header="user-agent",
            accept_header_value="application/json",
            http_headers=http_headers,
            _globals=models.V3ThreathuntingScansDiscoveryGlobals(
                organization_id=self.sdk_configuration.globals.organization_id,
            ),
            security=self.sdk_configuration.security,
            get_serialized_body=lambda: utils.serialize_request_body(
                request.scans_discovery_input_body,
                False,
                False,
                "json",
                models.ScansDiscoveryInputBody,
            ),
            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="v3-threathunting-scans-discovery",
                oauth2_scopes=None,
                security_source=self.sdk_configuration.security,
            ),
            request=req,
            error_status_codes=["401", "403", "4XX", "5XX"],
            retry_config=retry_config,
        )

        response_data: Any = None
        if utils.match_response(http_res, "200", "application/json"):
            return models.V3ThreathuntingScansDiscoveryResponse(
                result=unmarshal_json_response(
                    models.ResponseEnvelopeTrackedScan, http_res
                ),
                headers=utils.get_response_headers(http_res.headers),
            )
        if utils.match_response(http_res, "401", "application/json"):
            response_data = unmarshal_json_response(
                models.AuthenticationErrorData, http_res
            )
            raise models.AuthenticationError(response_data, http_res)
        if utils.match_response(http_res, "403", "application/problem+json"):
            response_data = unmarshal_json_response(models.ErrorModelData, http_res)
            raise models.ErrorModel(response_data, http_res)
        if utils.match_response(http_res, "4XX", "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise models.SDKError("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 models.SDKError("API error occurred", http_res, http_res_text)

        raise models.SDKError("Unexpected response received", http_res)

    async def create_tracked_scan_async(
        self,
        *,
        scans_discovery_input_body: Union[
            models.ScansDiscoveryInputBody, models.ScansDiscoveryInputBodyTypedDict
        ],
        organization_id: Optional[str] = None,
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> models.V3ThreathuntingScansDiscoveryResponse:
        r"""Live Discovery: Initiate a new scan

        Initiate a scan to look for a currently unobserved service at a specific IP and port (`ip:port`) or hostname and port (`hostname:port`). This is equivalent to the [Live Discovery](https://docs.censys.com/docs/platform-threat-hunting-use-live-scan-and-rescan-to-validate-infrastructure#/) feature available in the UI, but you can also target web properties in addition to hosts.<br><br>The scan may take several minutes to complete. The response will contain a scan ID that you can use to [monitor the scan's status](https://docs.censys.com/reference/v3-threathunting-scans-get#/). After the scan completes, perform a lookup on the target asset to retrieve detailed scan information.<br><br>This endpoint is available to organizations that have access to the Threat Hunting module. It costs 15 credits to execute this endpoint.

        :param scans_discovery_input_body:
        :param organization_id: The ID of a Censys organization to associate the request with. See the [Getting Started docs](https://docs.censys.com/reference/get-started#step-3-find-and-use-your-organization-id-optional) for more information.
        :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.V3ThreathuntingScansDiscoveryRequest(
            organization_id=organization_id,
            scans_discovery_input_body=utils.get_pydantic_model(
                scans_discovery_input_body, models.ScansDiscoveryInputBody
            ),
        )

        req = self._build_request_async(
            method="POST",
            path="/v3/threat-hunting/scans/discovery",
            base_url=base_url,
            url_variables=url_variables,
            request=request,
            request_body_required=True,
            request_has_path_params=False,
            request_has_query_params=True,
            user_agent_header="user-agent",
            accept_header_value="application/json",
            http_headers=http_headers,
            _globals=models.V3ThreathuntingScansDiscoveryGlobals(
                organization_id=self.sdk_configuration.globals.organization_id,
            ),
            security=self.sdk_configuration.security,
            get_serialized_body=lambda: utils.serialize_request_body(
                request.scans_discovery_input_body,
                False,
                False,
                "json",
                models.ScansDiscoveryInputBody,
            ),
            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="v3-threathunting-scans-discovery",
                oauth2_scopes=None,
                security_source=self.sdk_configuration.security,
            ),
            request=req,
            error_status_codes=["401", "403", "4XX", "5XX"],
            retry_config=retry_config,
        )

        response_data: Any = None
        if utils.match_response(http_res, "200", "application/json"):
            return models.V3ThreathuntingScansDiscoveryResponse(
                result=unmarshal_json_response(
                    models.ResponseEnvelopeTrackedScan, http_res
                ),
                headers=utils.get_response_headers(http_res.headers),
            )
        if utils.match_response(http_res, "401", "application/json"):
            response_data = unmarshal_json_response(
                models.AuthenticationErrorData, http_res
            )
            raise models.AuthenticationError(response_data, http_res)
        if utils.match_response(http_res, "403", "application/problem+json"):
            response_data = unmarshal_json_response(models.ErrorModelData, http_res)
            raise models.ErrorModel(response_data, http_res)
        if utils.match_response(http_res, "4XX", "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise models.SDKError("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 models.SDKError("API error occurred", http_res, http_res_text)

        raise models.SDKError("Unexpected response received", http_res)

    def get_tracked_scan_threat_hunting(
        self,
        *,
        scan_id: str,
        organization_id: Optional[str] = None,
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> models.V3ThreathuntingScansGetResponse:
        r"""Get scan status

        Retrieve the current status of a scan by its ID. This endpoint works for both [Live Discovery scans](https://docs.censys.com/reference/v3-threathunting-scans-discovery#/) and [Live Rescans](https://docs.censys.com/reference/v3-globaldata-scans-rescan#/).<br><br>If the scan was successful, perform a lookup on the target asset to retrieve detailed scan information.<br><br>This endpoint is available to all Enterprise customers. This endpoint does not cost any credits to execute.

        :param scan_id: The unique identifier of the tracked scan
        :param organization_id: The ID of a Censys organization to associate the request with. See the [Getting Started docs](https://docs.censys.com/reference/get-started#step-3-find-and-use-your-organization-id-optional) for more information.
        :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.V3ThreathuntingScansGetRequest(
            organization_id=organization_id,
            scan_id=scan_id,
        )

        req = self._build_request(
            method="GET",
            path="/v3/threat-hunting/scans/{scan_id}",
            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/vnd.censys.api.v3.trackedscan.v1+json",
            http_headers=http_headers,
            _globals=models.V3ThreathuntingScansGetGlobals(
                organization_id=self.sdk_configuration.globals.organization_id,
            ),
            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="v3-threathunting-scans-get",
                oauth2_scopes=None,
                security_source=self.sdk_configuration.security,
            ),
            request=req,
            error_status_codes=["401", "403", "404", "4XX", "5XX"],
            retry_config=retry_config,
        )

        response_data: Any = None
        if utils.match_response(
            http_res, "200", "application/vnd.censys.api.v3.trackedscan.v1+json"
        ):
            return models.V3ThreathuntingScansGetResponse(
                result=unmarshal_json_response(
                    models.ResponseEnvelopeTrackedScan, http_res
                ),
                headers=utils.get_response_headers(http_res.headers),
            )
        if utils.match_response(http_res, "401", "application/json"):
            response_data = unmarshal_json_response(
                models.AuthenticationErrorData, http_res
            )
            raise models.AuthenticationError(response_data, http_res)
        if utils.match_response(http_res, ["403", "404"], "application/problem+json"):
            response_data = unmarshal_json_response(models.ErrorModelData, http_res)
            raise models.ErrorModel(response_data, http_res)
        if utils.match_response(http_res, "4XX", "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise models.SDKError("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 models.SDKError("API error occurred", http_res, http_res_text)

        raise models.SDKError("Unexpected response received", http_res)

    async def get_tracked_scan_threat_hunting_async(
        self,
        *,
        scan_id: str,
        organization_id: Optional[str] = None,
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> models.V3ThreathuntingScansGetResponse:
        r"""Get scan status

        Retrieve the current status of a scan by its ID. This endpoint works for both [Live Discovery scans](https://docs.censys.com/reference/v3-threathunting-scans-discovery#/) and [Live Rescans](https://docs.censys.com/reference/v3-globaldata-scans-rescan#/).<br><br>If the scan was successful, perform a lookup on the target asset to retrieve detailed scan information.<br><br>This endpoint is available to all Enterprise customers. This endpoint does not cost any credits to execute.

        :param scan_id: The unique identifier of the tracked scan
        :param organization_id: The ID of a Censys organization to associate the request with. See the [Getting Started docs](https://docs.censys.com/reference/get-started#step-3-find-and-use-your-organization-id-optional) for more information.
        :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.V3ThreathuntingScansGetRequest(
            organization_id=organization_id,
            scan_id=scan_id,
        )

        req = self._build_request_async(
            method="GET",
            path="/v3/threat-hunting/scans/{scan_id}",
            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/vnd.censys.api.v3.trackedscan.v1+json",
            http_headers=http_headers,
            _globals=models.V3ThreathuntingScansGetGlobals(
                organization_id=self.sdk_configuration.globals.organization_id,
            ),
            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="v3-threathunting-scans-get",
                oauth2_scopes=None,
                security_source=self.sdk_configuration.security,
            ),
            request=req,
            error_status_codes=["401", "403", "404", "4XX", "5XX"],
            retry_config=retry_config,
        )

        response_data: Any = None
        if utils.match_response(
            http_res, "200", "application/vnd.censys.api.v3.trackedscan.v1+json"
        ):
            return models.V3ThreathuntingScansGetResponse(
                result=unmarshal_json_response(
                    models.ResponseEnvelopeTrackedScan, http_res
                ),
                headers=utils.get_response_headers(http_res.headers),
            )
        if utils.match_response(http_res, "401", "application/json"):
            response_data = unmarshal_json_response(
                models.AuthenticationErrorData, http_res
            )
            raise models.AuthenticationError(response_data, http_res)
        if utils.match_response(http_res, ["403", "404"], "application/problem+json"):
            response_data = unmarshal_json_response(models.ErrorModelData, http_res)
            raise models.ErrorModel(response_data, http_res)
        if utils.match_response(http_res, "4XX", "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise models.SDKError("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 models.SDKError("API error occurred", http_res, http_res_text)

        raise models.SDKError("Unexpected response received", http_res)

    def list_threats(
        self,
        *,
        organization_id: Optional[str] = None,
        query: Optional[str] = None,
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> models.V3ThreathuntingThreatsListResponse:
        r"""List active threats

        Retrieve a list of active threats observed by Censys by aggregating threat IDs across hosts and web properties. Threats are active if their fingerprint has been identified on hosts or web properties by Censys scans. This information is also available on the [Explore Threats page in the Platform web UI](https://platform.censys.io/threats).

        :param organization_id: The ID of a Censys organization to associate the request with. See the [Getting Started docs](https://docs.censys.com/reference/get-started#step-3-find-and-use-your-organization-id-optional) for more information.
        :param query: Optional CenQL filter to constrain threats list
        :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.V3ThreathuntingThreatsListRequest(
            organization_id=organization_id,
            query=query,
        )

        req = self._build_request(
            method="GET",
            path="/v3/threat-hunting/threats",
            base_url=base_url,
            url_variables=url_variables,
            request=request,
            request_body_required=False,
            request_has_path_params=False,
            request_has_query_params=True,
            user_agent_header="user-agent",
            accept_header_value="application/json",
            http_headers=http_headers,
            _globals=models.V3ThreathuntingThreatsListGlobals(
                organization_id=self.sdk_configuration.globals.organization_id,
            ),
            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="v3-threathunting-threats-list",
                oauth2_scopes=None,
                security_source=self.sdk_configuration.security,
            ),
            request=req,
            error_status_codes=["401", "403", "422", "4XX", "5XX"],
            retry_config=retry_config,
        )

        response_data: Any = None
        if utils.match_response(http_res, "200", "application/json"):
            return models.V3ThreathuntingThreatsListResponse(
                result=unmarshal_json_response(
                    models.ResponseEnvelopeThreatsListResponse, http_res
                ),
                headers=utils.get_response_headers(http_res.headers),
            )
        if utils.match_response(http_res, "401", "application/json"):
            response_data = unmarshal_json_response(
                models.AuthenticationErrorData, http_res
            )
            raise models.AuthenticationError(response_data, http_res)
        if utils.match_response(http_res, ["403", "422"], "application/problem+json"):
            response_data = unmarshal_json_response(models.ErrorModelData, http_res)
            raise models.ErrorModel(response_data, http_res)
        if utils.match_response(http_res, "4XX", "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise models.SDKError("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 models.SDKError("API error occurred", http_res, http_res_text)

        raise models.SDKError("Unexpected response received", http_res)

    async def list_threats_async(
        self,
        *,
        organization_id: Optional[str] = None,
        query: Optional[str] = None,
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> models.V3ThreathuntingThreatsListResponse:
        r"""List active threats

        Retrieve a list of active threats observed by Censys by aggregating threat IDs across hosts and web properties. Threats are active if their fingerprint has been identified on hosts or web properties by Censys scans. This information is also available on the [Explore Threats page in the Platform web UI](https://platform.censys.io/threats).

        :param organization_id: The ID of a Censys organization to associate the request with. See the [Getting Started docs](https://docs.censys.com/reference/get-started#step-3-find-and-use-your-organization-id-optional) for more information.
        :param query: Optional CenQL filter to constrain threats list
        :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.V3ThreathuntingThreatsListRequest(
            organization_id=organization_id,
            query=query,
        )

        req = self._build_request_async(
            method="GET",
            path="/v3/threat-hunting/threats",
            base_url=base_url,
            url_variables=url_variables,
            request=request,
            request_body_required=False,
            request_has_path_params=False,
            request_has_query_params=True,
            user_agent_header="user-agent",
            accept_header_value="application/json",
            http_headers=http_headers,
            _globals=models.V3ThreathuntingThreatsListGlobals(
                organization_id=self.sdk_configuration.globals.organization_id,
            ),
            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="v3-threathunting-threats-list",
                oauth2_scopes=None,
                security_source=self.sdk_configuration.security,
            ),
            request=req,
            error_status_codes=["401", "403", "422", "4XX", "5XX"],
            retry_config=retry_config,
        )

        response_data: Any = None
        if utils.match_response(http_res, "200", "application/json"):
            return models.V3ThreathuntingThreatsListResponse(
                result=unmarshal_json_response(
                    models.ResponseEnvelopeThreatsListResponse, http_res
                ),
                headers=utils.get_response_headers(http_res.headers),
            )
        if utils.match_response(http_res, "401", "application/json"):
            response_data = unmarshal_json_response(
                models.AuthenticationErrorData, http_res
            )
            raise models.AuthenticationError(response_data, http_res)
        if utils.match_response(http_res, ["403", "422"], "application/problem+json"):
            response_data = unmarshal_json_response(models.ErrorModelData, http_res)
            raise models.ErrorModel(response_data, http_res)
        if utils.match_response(http_res, "4XX", "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise models.SDKError("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 models.SDKError("API error occurred", http_res, http_res_text)

        raise models.SDKError("Unexpected response received", http_res)

    def value_counts(
        self,
        *,
        search_value_counts_input_body: Union[
            models.SearchValueCountsInputBody,
            models.SearchValueCountsInputBodyTypedDict,
        ],
        organization_id: Optional[str] = None,
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> models.V3ThreathuntingValueCountsResponse:
        r"""CensEye: Retrieve value counts to discover pivots

        Get counts of web assets for specific field-value pairs and combinations of field-value pairs. This is similar to the [CensEye functionality](https://docs.censys.com/docs/platform-threat-hunting-use-censeye-to-build-detections#/) available in the Platform web UI, but it allows you to define specific fields of interest rather than the [default fields](https://docs.censys.com/docs/platform-threat-hunting-use-censeye-to-build-detections#default-pivot-fields) leveraged by the tool in the UI.<br><br>Each array can only target fields within the same nested object. For example, you can combine `host.services.port=80` and `host.services.protocol=SSH` in the same array, but you cannot combine `host.services.port=80` and `host.location.country=”United States”` in the same array. You can input multiple arrays of objects in each API call.<br><br>To use this endpoint, your organization must have access to the Threat Hunting Module. This endpoint costs 1 credit per count condition (array of objects) included in the API call.

        :param search_value_counts_input_body:
        :param organization_id: The ID of a Censys organization to associate the request with. See the [Getting Started docs](https://docs.censys.com/reference/get-started#step-3-find-and-use-your-organization-id-optional) for more information.
        :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.V3ThreathuntingValueCountsRequest(
            organization_id=organization_id,
            search_value_counts_input_body=utils.get_pydantic_model(
                search_value_counts_input_body, models.SearchValueCountsInputBody
            ),
        )

        req = self._build_request(
            method="POST",
            path="/v3/threat-hunting/value-counts",
            base_url=base_url,
            url_variables=url_variables,
            request=request,
            request_body_required=True,
            request_has_path_params=False,
            request_has_query_params=True,
            user_agent_header="user-agent",
            accept_header_value="application/json",
            http_headers=http_headers,
            _globals=models.V3ThreathuntingValueCountsGlobals(
                organization_id=self.sdk_configuration.globals.organization_id,
            ),
            security=self.sdk_configuration.security,
            get_serialized_body=lambda: utils.serialize_request_body(
                request.search_value_counts_input_body,
                False,
                False,
                "json",
                models.SearchValueCountsInputBody,
            ),
            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="v3-threathunting-value-counts",
                oauth2_scopes=None,
                security_source=self.sdk_configuration.security,
            ),
            request=req,
            error_status_codes=["401", "403", "4XX", "5XX"],
            retry_config=retry_config,
        )

        response_data: Any = None
        if utils.match_response(http_res, "200", "application/json"):
            return models.V3ThreathuntingValueCountsResponse(
                result=unmarshal_json_response(
                    models.ResponseEnvelopeValueCountsResponse, http_res
                ),
                headers=utils.get_response_headers(http_res.headers),
            )
        if utils.match_response(http_res, "401", "application/json"):
            response_data = unmarshal_json_response(
                models.AuthenticationErrorData, http_res
            )
            raise models.AuthenticationError(response_data, http_res)
        if utils.match_response(http_res, "403", "application/problem+json"):
            response_data = unmarshal_json_response(models.ErrorModelData, http_res)
            raise models.ErrorModel(response_data, http_res)
        if utils.match_response(http_res, "4XX", "*"):
            http_res_text = utils.stream_to_text(http_res)
            raise models.SDKError("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 models.SDKError("API error occurred", http_res, http_res_text)

        raise models.SDKError("Unexpected response received", http_res)

    async def value_counts_async(
        self,
        *,
        search_value_counts_input_body: Union[
            models.SearchValueCountsInputBody,
            models.SearchValueCountsInputBodyTypedDict,
        ],
        organization_id: Optional[str] = None,
        retries: OptionalNullable[utils.RetryConfig] = UNSET,
        server_url: Optional[str] = None,
        timeout_ms: Optional[int] = None,
        http_headers: Optional[Mapping[str, str]] = None,
    ) -> models.V3ThreathuntingValueCountsResponse:
        r"""CensEye: Retrieve value counts to discover pivots

        Get counts of web assets for specific field-value pairs and combinations of field-value pairs. This is similar to the [CensEye functionality](https://docs.censys.com/docs/platform-threat-hunting-use-censeye-to-build-detections#/) available in the Platform web UI, but it allows you to define specific fields of interest rather than the [default fields](https://docs.censys.com/docs/platform-threat-hunting-use-censeye-to-build-detections#default-pivot-fields) leveraged by the tool in the UI.<br><br>Each array can only target fields within the same nested object. For example, you can combine `host.services.port=80` and `host.services.protocol=SSH` in the same array, but you cannot combine `host.services.port=80` and `host.location.country=”United States”` in the same array. You can input multiple arrays of objects in each API call.<br><br>To use this endpoint, your organization must have access to the Threat Hunting Module. This endpoint costs 1 credit per count condition (array of objects) included in the API call.

        :param search_value_counts_input_body:
        :param organization_id: The ID of a Censys organization to associate the request with. See the [Getting Started docs](https://docs.censys.com/reference/get-started#step-3-find-and-use-your-organization-id-optional) for more information.
        :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.V3ThreathuntingValueCountsRequest(
            organization_id=organization_id,
            search_value_counts_input_body=utils.get_pydantic_model(
                search_value_counts_input_body, models.SearchValueCountsInputBody
            ),
        )

        req = self._build_request_async(
            method="POST",
            path="/v3/threat-hunting/value-counts",
            base_url=base_url,
            url_variables=url_variables,
            request=request,
            request_body_required=True,
            request_has_path_params=False,
            request_has_query_params=True,
            user_agent_header="user-agent",
            accept_header_value="application/json",
            http_headers=http_headers,
            _globals=models.V3ThreathuntingValueCountsGlobals(
                organization_id=self.sdk_configuration.globals.organization_id,
            ),
            security=self.sdk_configuration.security,
            get_serialized_body=lambda: utils.serialize_request_body(
                request.search_value_counts_input_body,
                False,
                False,
                "json",
                models.SearchValueCountsInputBody,
            ),
            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="v3-threathunting-value-counts",
                oauth2_scopes=None,
                security_source=self.sdk_configuration.security,
            ),
            request=req,
            error_status_codes=["401", "403", "4XX", "5XX"],
            retry_config=retry_config,
        )

        response_data: Any = None
        if utils.match_response(http_res, "200", "application/json"):
            return models.V3ThreathuntingValueCountsResponse(
                result=unmarshal_json_response(
                    models.ResponseEnvelopeValueCountsResponse, http_res
                ),
                headers=utils.get_response_headers(http_res.headers),
            )
        if utils.match_response(http_res, "401", "application/json"):
            response_data = unmarshal_json_response(
                models.AuthenticationErrorData, http_res
            )
            raise models.AuthenticationError(response_data, http_res)
        if utils.match_response(http_res, "403", "application/problem+json"):
            response_data = unmarshal_json_response(models.ErrorModelData, http_res)
            raise models.ErrorModel(response_data, http_res)
        if utils.match_response(http_res, "4XX", "*"):
            http_res_text = await utils.stream_to_text_async(http_res)
            raise models.SDKError("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 models.SDKError("API error occurred", http_res, http_res_text)

        raise models.SDKError("Unexpected response received", http_res)
