"""Camera API endpoints.

This file is automatically @generated from the Meraki API specification.
Do not edit this file manually.

"""

from __future__ import annotations

import urllib.parse
from typing import TYPE_CHECKING, Any, Literal

from meraki_client.schemas import (
    CreateNetworkCameraQualityRetentionProfileResponse,
    CreateNetworkCameraQualityRetentionProfileSmartRetention,
    CreateNetworkCameraQualityRetentionProfileVideoSettings,
    CreateNetworkCameraWirelessProfileIdentity,
    CreateNetworkCameraWirelessProfileResponse,
    CreateNetworkCameraWirelessProfileSsid,
    CreateOrganizationCameraCustomAnalyticsArtifactResponse,
    CreateOrganizationCameraRoleAppliedOnDevicesItem,
    CreateOrganizationCameraRoleAppliedOnNetworksItem,
    CreateOrganizationCameraRoleAppliedOrgWideItem,
    CreateOrganizationCameraRoleResponse,
    DictResponse,
    GenerateDeviceCameraSnapshotResponse,
    GetDeviceCameraAnalyticsLiveResponse,
    GetDeviceCameraAnalyticsOverviewResponseItem,
    GetDeviceCameraAnalyticsRecentResponseItem,
    GetDeviceCameraAnalyticsZoneHistoryResponseItem,
    GetDeviceCameraAnalyticsZonesResponseItem,
    GetDeviceCameraCustomAnalyticsResponse,
    GetDeviceCameraSenseObjectDetectionModelsResponse,
    GetDeviceCameraVideoSettingsResponse,
    GetNetworkCameraQualityRetentionProfileResponse,
    GetNetworkCameraQualityRetentionProfilesResponseItem,
    GetNetworkCameraSchedulesResponseItem,
    GetNetworkCameraWirelessProfileResponse,
    GetNetworkCameraWirelessProfilesResponseItem,
    GetOrganizationCameraBoundariesAreasByDeviceResponseItem,
    GetOrganizationCameraBoundariesLinesByDeviceResponseItem,
    GetOrganizationCameraCustomAnalyticsArtifactResponse,
    GetOrganizationCameraCustomAnalyticsArtifactsResponseItem,
    GetOrganizationCameraDetectionsHistoryByBoundaryByIntervalResponseItem,
    GetOrganizationCameraOnboardingStatusesResponse,
    GetOrganizationCameraPermissionResponse,
    GetOrganizationCameraPermissionsResponseItem,
    GetOrganizationCameraRoleResponse,
    GetOrganizationCameraRolesResponseItem,
    UpdateDeviceCameraCustomAnalyticsParametersItem,
    UpdateDeviceCameraCustomAnalyticsResponse,
    UpdateDeviceCameraSenseAudioDetection,
    UpdateDeviceCameraVideoSettingsResponse,
    UpdateDeviceCameraWirelessProfilesIds,
    UpdateNetworkCameraQualityRetentionProfileResponse,
    UpdateNetworkCameraQualityRetentionProfileSmartRetention,
    UpdateNetworkCameraQualityRetentionProfileVideoSettings,
    UpdateNetworkCameraWirelessProfileIdentity,
    UpdateNetworkCameraWirelessProfileResponse,
    UpdateNetworkCameraWirelessProfileSsid,
    UpdateOrganizationCameraRoleAppliedOnDevicesItem,
    UpdateOrganizationCameraRoleAppliedOnNetworksItem,
    UpdateOrganizationCameraRoleAppliedOrgWideItem,
    UpdateOrganizationCameraRoleResponse,
)
from meraki_client.types import (
    GetDeviceCameraAnalyticsOverviewObjectType,
    GetDeviceCameraAnalyticsRecentObjectType,
    GetDeviceCameraAnalyticsZoneHistoryObjectType,
    GetOrganizationCameraDetectionsHistoryByBoundaryByIntervalBoundaryTypes,
    UpdateDeviceCameraQualityAndRetentionMotionDetectorVersion,
    UpdateDeviceCameraQualityAndRetentionQuality,
    UpdateDeviceCameraQualityAndRetentionResolution,
)

if TYPE_CHECKING:
    from meraki_client._session import PaginatedResponse, Session


class Camera:
    """Camera class."""

    def __init__(self, session: Session) -> None:
        self._session = session

    def get_device_camera_analytics_live(self, serial: str) -> GetDeviceCameraAnalyticsLiveResponse:
        """Returns live state from camera analytics zones.

        [API documentation: getDeviceCameraAnalyticsLive](https://developer.cisco.com/meraki/api-v1/#!get-device-camera-analytics-live)

        Args:
            serial: Serial.

        Returns:
            Successful operation.

        Example API response:
            ```json
            {
              "ts": "2018-08-15T18:32:38.123Z",
              "zones": {
                "zoneId": {
                  "person": 0
                }
              }
            }
            ```

        """
        serial = urllib.parse.quote(str(serial), safe="")
        path = f"/devices/{serial}/camera/analytics/live"

        return self._session.get(
            scope="camera",
            operation_id="getDeviceCameraAnalyticsLive",
            path=path,
            response_schema=GetDeviceCameraAnalyticsLiveResponse,
        )

    def get_device_camera_analytics_overview(
        self,
        serial: str,
        *,
        t0: str | None = None,
        t1: str | None = None,
        timespan: float | None = None,
        object_type: GetDeviceCameraAnalyticsOverviewObjectType | None = None,
    ) -> PaginatedResponse[GetDeviceCameraAnalyticsOverviewResponseItem]:
        """Returns an overview of aggregate analytics data for a timespan.

        [API documentation: getDeviceCameraAnalyticsOverview](https://developer.cisco.com/meraki/api-v1/#!get-device-camera-analytics-overview)

        Args:
            serial: Serial.
            t0: The beginning of the timespan for the data. The maximum lookback period is 365 days
                from today.
            t1: The end of the timespan for the data. t1 can be a maximum of 7 days after t0.
            timespan: The timespan for which the information will be fetched. If specifying
                timespan, do not specify parameters t0 and t1. The value must be in
                seconds and be less than or equal to 7 days. The default is 1 hour.
            object_type: [optional] The object type for which analytics will be retrieved. The
                default object type is person. The available types are [person,
                vehicle].

        Returns:
            Successful operation.

        Note:
            Returns a lazy PaginatedResponse
            that can be iterated or collected with `.collect()`.
            Page metadata is available on `.meta` and `.meta_pages`.

        Example API response:
            ```json
            [
              {
                "startTs": "2018-08-15T18:32:38.123Z",
                "endTs": "2018-08-15T18:33:38.123Z",
                "zoneId": 0,
                "entrances": 254,
                "averageCount": 5.0
              }
            ]
            ```

        """
        serial = urllib.parse.quote(str(serial), safe="")
        path = f"/devices/{serial}/camera/analytics/overview"

        params: dict[str, Any] = {}
        if t0 is not None:
            params["t0"] = t0
        if t1 is not None:
            params["t1"] = t1
        if timespan is not None:
            params["timespan"] = timespan
        if object_type is not None:
            params["objectType"] = object_type

        return self._session.get_pages(
            scope="camera",
            operation_id="getDeviceCameraAnalyticsOverview",
            path=path,
            params=params,
            item_schema=GetDeviceCameraAnalyticsOverviewResponseItem,
        )

    def get_device_camera_analytics_recent(
        self, serial: str, *, object_type: GetDeviceCameraAnalyticsRecentObjectType | None = None
    ) -> PaginatedResponse[GetDeviceCameraAnalyticsRecentResponseItem]:
        """Returns most recent record for analytics zones.

        [API documentation: getDeviceCameraAnalyticsRecent](https://developer.cisco.com/meraki/api-v1/#!get-device-camera-analytics-recent)

        Args:
            serial: Serial.
            object_type: [optional] The object type for which analytics will be retrieved. The
                default object type is person. The available types are [person,
                vehicle].

        Returns:
            Successful operation.

        Note:
            Returns a lazy PaginatedResponse
            that can be iterated or collected with `.collect()`.
            Page metadata is available on `.meta` and `.meta_pages`.

        Example API response:
            ```json
            [
              {
                "startTs": "2018-08-15T18:32:38.123Z",
                "endTs": "2018-08-15T18:33:38.123Z",
                "zoneId": 0,
                "entrances": 10,
                "averageCount": 2.54
              }
            ]
            ```

        """
        serial = urllib.parse.quote(str(serial), safe="")
        path = f"/devices/{serial}/camera/analytics/recent"

        params: dict[str, Any] = {}
        if object_type is not None:
            params["objectType"] = object_type

        return self._session.get_pages(
            scope="camera",
            operation_id="getDeviceCameraAnalyticsRecent",
            path=path,
            params=params,
            item_schema=GetDeviceCameraAnalyticsRecentResponseItem,
        )

    def get_device_camera_analytics_zones(
        self, serial: str
    ) -> PaginatedResponse[GetDeviceCameraAnalyticsZonesResponseItem]:
        """Returns all configured analytic zones for this camera.

        [API documentation: getDeviceCameraAnalyticsZones](https://developer.cisco.com/meraki/api-v1/#!get-device-camera-analytics-zones)

        Args:
            serial: Serial.

        Returns:
            Successful operation.

        Note:
            Returns a lazy PaginatedResponse
            that can be iterated or collected with `.collect()`.
            Page metadata is available on `.meta` and `.meta_pages`.

        Example API response:
            ```json
            [
              {
                "id": "0",
                "type": "occupancy",
                "label": "Full Frame",
                "regionOfInterest": {
                  "x0": "0.00",
                  "y0": "0.00",
                  "x1": "1.00",
                  "y1": "1.00"
                }
              }
            ]
            ```

        """
        serial = urllib.parse.quote(str(serial), safe="")
        path = f"/devices/{serial}/camera/analytics/zones"

        return self._session.get_pages(
            scope="camera",
            operation_id="getDeviceCameraAnalyticsZones",
            path=path,
            item_schema=GetDeviceCameraAnalyticsZonesResponseItem,
        )

    def get_device_camera_analytics_zone_history(
        self,
        *,
        serial: str,
        zone_id: str,
        t0: str | None = None,
        t1: str | None = None,
        timespan: float | None = None,
        resolution: int | None = None,
        object_type: GetDeviceCameraAnalyticsZoneHistoryObjectType | None = None,
    ) -> PaginatedResponse[GetDeviceCameraAnalyticsZoneHistoryResponseItem]:
        """Return historical records for analytic zones.

        [API documentation: getDeviceCameraAnalyticsZoneHistory](https://developer.cisco.com/meraki/api-v1/#!get-device-camera-analytics-zone-history)

        Args:
            serial: Serial.
            zone_id: Zone ID.
            t0: The beginning of the timespan for the data. The maximum lookback period is 365 days
                from today.
            t1: The end of the timespan for the data. t1 can be a maximum of 14 hours after t0.
            timespan: The timespan for which the information will be fetched. If specifying
                timespan, do not specify parameters t0 and t1. The value must be in
                seconds and be less than or equal to 14 hours. The default is 1 hour.
            resolution: The time resolution in seconds for returned data. The valid resolutions are:
                60. The default is 60.
            object_type: [optional] The object type for which analytics will be retrieved. The
                default object type is person. The available types are [person,
                vehicle].

        Returns:
            Successful operation.

        Note:
            Returns a lazy PaginatedResponse
            that can be iterated or collected with `.collect()`.
            Page metadata is available on `.meta` and `.meta_pages`.

        Example API response:
            ```json
            [
              {
                "startTs": "2018-08-15T18:32:38.123Z",
                "endTs": "2018-08-15T18:33:38.123Z",
                "entrances": 5,
                "averageCount": 1.5
              }
            ]
            ```

        """
        serial = urllib.parse.quote(str(serial), safe="")
        zone_id = urllib.parse.quote(str(zone_id), safe="")
        path = f"/devices/{serial}/camera/analytics/zones/{zone_id}/history"

        params: dict[str, Any] = {}
        if t0 is not None:
            params["t0"] = t0
        if t1 is not None:
            params["t1"] = t1
        if timespan is not None:
            params["timespan"] = timespan
        if resolution is not None:
            params["resolution"] = resolution
        if object_type is not None:
            params["objectType"] = object_type

        return self._session.get_pages(
            scope="camera",
            operation_id="getDeviceCameraAnalyticsZoneHistory",
            path=path,
            params=params,
            item_schema=GetDeviceCameraAnalyticsZoneHistoryResponseItem,
        )

    def get_device_camera_custom_analytics(
        self, serial: str
    ) -> GetDeviceCameraCustomAnalyticsResponse:
        """Return custom analytics settings for a camera.

        [API documentation: getDeviceCameraCustomAnalytics](https://developer.cisco.com/meraki/api-v1/#!get-device-camera-custom-analytics)

        Args:
            serial: Serial.

        Returns:
            Successful operation.

        Example API response:
            ```json
            {
              "enabled": true,
              "artifactId": "1",
              "parameters": [
                {
                  "name": "detection_threshold",
                  "value": 0.5
                }
              ]
            }
            ```

        """
        serial = urllib.parse.quote(str(serial), safe="")
        path = f"/devices/{serial}/camera/customAnalytics"

        return self._session.get(
            scope="camera",
            operation_id="getDeviceCameraCustomAnalytics",
            path=path,
            response_schema=GetDeviceCameraCustomAnalyticsResponse,
        )

    def update_device_camera_custom_analytics(
        self,
        serial: str,
        *,
        enabled: bool | None = None,
        artifact_id: str | None = None,
        parameters: list[UpdateDeviceCameraCustomAnalyticsParametersItem] | None = None,
    ) -> UpdateDeviceCameraCustomAnalyticsResponse:
        """Update custom analytics settings for a camera.

        [API documentation: updateDeviceCameraCustomAnalytics](https://developer.cisco.com/meraki/api-v1/#!update-device-camera-custom-analytics)

        Args:
            serial: Serial.
            enabled: Enable custom analytics.
            artifact_id: The ID of the custom analytics artifact.
            parameters: Parameters for the custom analytics workload.

        Returns:
            Successful operation.

        Example API response:
            ```json
            {
              "enabled": true,
              "artifactId": "1",
              "parameters": [
                {
                  "name": "detection_threshold",
                  "value": 0.5
                }
              ]
            }
            ```

        """
        serial = urllib.parse.quote(str(serial), safe="")
        path = f"/devices/{serial}/camera/customAnalytics"

        payload: dict[str, Any] = {}
        if enabled is not None:
            payload["enabled"] = enabled
        if artifact_id is not None:
            payload["artifactId"] = artifact_id
        if parameters is not None:
            payload["parameters"] = [
                item.model_dump(by_alias=True, exclude_none=True) for item in parameters
            ]

        return self._session.put(
            scope="camera",
            operation_id="updateDeviceCameraCustomAnalytics",
            path=path,
            json=payload,
            response_schema=UpdateDeviceCameraCustomAnalyticsResponse,
        )

    def generate_device_camera_snapshot(
        self, serial: str, *, timestamp: str | None = None, fullframe: bool | None = None
    ) -> GenerateDeviceCameraSnapshotResponse:
        """Generate a snapshot of what the camera sees at the specified time and return a link to that image.

        [API documentation: generateDeviceCameraSnapshot](https://developer.cisco.com/meraki/api-v1/#!generate-device-camera-snapshot)

        Args:
            serial: Serial.
            timestamp: [optional] The snapshot will be taken from this time on the camera. The
                timestamp is expected to be in ISO 8601 format. If no timestamp is
                specified, we will assume current time.
            fullframe: [optional] If set to "true" the snapshot will be taken at full sensor
                resolution. This will error if used with timestamp.

        Returns:
            Successful operation.

        Example API response:
            ```json
            {
              "url": "https://spn4.meraki.com/stream/jpeg/snapshot/b2d123asdf423qd22d2",
              "expiry": "Access to the image will expire at 2018-12-11T03:12:39Z."
            }
            ```

        """
        serial = urllib.parse.quote(str(serial), safe="")
        path = f"/devices/{serial}/camera/generateSnapshot"

        payload: dict[str, Any] = {}
        if timestamp is not None:
            payload["timestamp"] = timestamp
        if fullframe is not None:
            payload["fullframe"] = fullframe

        return self._session.post(
            scope="camera",
            operation_id="generateDeviceCameraSnapshot",
            path=path,
            json=payload,
            response_schema=GenerateDeviceCameraSnapshotResponse,
        )

    def get_device_camera_quality_and_retention(self, serial: str) -> DictResponse:
        """Returns quality and retention settings for the given camera.

        [API documentation: getDeviceCameraQualityAndRetention](https://developer.cisco.com/meraki/api-v1/#!get-device-camera-quality-and-retention)

        Args:
            serial: Serial.

        Returns:
            Successful operation.

        Example API response:
            ```json
            {
              "motionBasedRetentionEnabled": false,
              "audioRecordingEnabled": false,
              "restrictedBandwidthModeEnabled": false,
              "profileId": "1234",
              "quality": "Standard",
              "motionDetectorVersion": 2,
              "resolution": "1280x720"
            }
            ```

        """
        serial = urllib.parse.quote(str(serial), safe="")
        path = f"/devices/{serial}/camera/qualityAndRetention"

        return self._session.get(
            scope="camera",
            operation_id="getDeviceCameraQualityAndRetention",
            path=path,
            response_schema=DictResponse,
        )

    def update_device_camera_quality_and_retention(
        self,
        serial: str,
        *,
        profile_id: str | None = None,
        motion_based_retention_enabled: bool | None = None,
        audio_recording_enabled: bool | None = None,
        restricted_bandwidth_mode_enabled: bool | None = None,
        quality: UpdateDeviceCameraQualityAndRetentionQuality | None = None,
        resolution: UpdateDeviceCameraQualityAndRetentionResolution | None = None,
        motion_detector_version: UpdateDeviceCameraQualityAndRetentionMotionDetectorVersion
        | None = None,
    ) -> DictResponse:
        """Update quality and retention settings for the given camera.

        [API documentation: updateDeviceCameraQualityAndRetention](https://developer.cisco.com/meraki/api-v1/#!update-device-camera-quality-and-retention)

        Args:
            serial: Serial.
            profile_id: The ID of a quality and retention profile to assign to the camera. The
                profile's settings will override all of the per-camera quality and
                retention settings. If the value of this parameter is null, any existing
                profile will be unassigned from the camera.
            motion_based_retention_enabled: Boolean indicating if motion-based retention is
                enabled(true) or disabled(false) on the camera.
            audio_recording_enabled: Boolean indicating if audio recording is enabled(true) or
                disabled(false) on the camera.
            restricted_bandwidth_mode_enabled: Boolean indicating if restricted bandwidth is
                enabled(true) or disabled(false) on the camera. This setting does not
                apply to MV2 cameras.
            quality: Quality of the camera. Can be one of 'Standard', 'High', 'Enhanced' or 'Ultra'.
                Not all qualities are supported by every camera model.
            resolution: Resolution of the camera. Can be one of '1280x720', '1920x1080',
                '1080x1080', '2112x2112', '2880x2880', '2688x1512' or '3840x2160'.Not
                all resolutions are supported by every camera model.
            motion_detector_version: The version of the motion detector that will be used by the
                camera. Only applies to Gen 2 cameras. Defaults to v2.

        Returns:
            Successful operation.

        Example API response:
            ```json
            {
              "motionBasedRetentionEnabled": false,
              "audioRecordingEnabled": false,
              "restrictedBandwidthModeEnabled": false,
              "profileId": "1234",
              "quality": "Standard",
              "motionDetectorVersion": 2,
              "resolution": "1280x720"
            }
            ```

        """
        serial = urllib.parse.quote(str(serial), safe="")
        path = f"/devices/{serial}/camera/qualityAndRetention"

        payload: dict[str, Any] = {}
        if profile_id is not None:
            payload["profileId"] = profile_id
        if motion_based_retention_enabled is not None:
            payload["motionBasedRetentionEnabled"] = motion_based_retention_enabled
        if audio_recording_enabled is not None:
            payload["audioRecordingEnabled"] = audio_recording_enabled
        if restricted_bandwidth_mode_enabled is not None:
            payload["restrictedBandwidthModeEnabled"] = restricted_bandwidth_mode_enabled
        if quality is not None:
            payload["quality"] = quality
        if resolution is not None:
            payload["resolution"] = resolution
        if motion_detector_version is not None:
            payload["motionDetectorVersion"] = motion_detector_version

        return self._session.put(
            scope="camera",
            operation_id="updateDeviceCameraQualityAndRetention",
            path=path,
            json=payload,
            response_schema=DictResponse,
        )

    def get_device_camera_sense(self, serial: str) -> DictResponse:
        """Returns sense settings for a given camera.

        [API documentation: getDeviceCameraSense](https://developer.cisco.com/meraki/api-v1/#!get-device-camera-sense)

        Args:
            serial: Serial.

        Returns:
            Successful operation.

        Example API response:
            ```json
            {
              "senseEnabled": true,
              "audioDetection": {
                "enabled": false
              },
              "mqttBrokerId": "1234",
              "mqttTopics": [
                "/merakimv/Q2AA-AAAA-1111/raw_detections",
                "/merakimv/Q2AA-AAAA-1111/light"
              ]
            }
            ```

        """
        serial = urllib.parse.quote(str(serial), safe="")
        path = f"/devices/{serial}/camera/sense"

        return self._session.get(
            scope="camera",
            operation_id="getDeviceCameraSense",
            path=path,
            response_schema=DictResponse,
        )

    def update_device_camera_sense(
        self,
        serial: str,
        *,
        sense_enabled: bool | None = None,
        mqtt_broker_id: str | None = None,
        audio_detection: UpdateDeviceCameraSenseAudioDetection | None = None,
        detection_model_id: str | None = None,
    ) -> DictResponse:
        """Update sense settings for the given camera.

        [API documentation: updateDeviceCameraSense](https://developer.cisco.com/meraki/api-v1/#!update-device-camera-sense)

        Args:
            serial: Serial.
            sense_enabled: Boolean indicating if sense(license) is enabled(true) or disabled(false)
                on the camera.
            mqtt_broker_id: The ID of the MQTT broker to be enabled on the camera. A value of null
                will disable MQTT on the camera.
            audio_detection: The details of the audio detection config.
            detection_model_id: The ID of the object detection model.

        Returns:
            Successful operation.

        Example API response:
            ```json
            {
              "senseEnabled": true,
              "audioDetection": {
                "enabled": false
              },
              "mqttBrokerId": "1234",
              "mqttTopics": [
                "/merakimv/Q2AA-AAAA-1111/raw_detections",
                "/merakimv/Q2AA-AAAA-1111/light"
              ]
            }
            ```

        """
        serial = urllib.parse.quote(str(serial), safe="")
        path = f"/devices/{serial}/camera/sense"

        payload: dict[str, Any] = {}
        if sense_enabled is not None:
            payload["senseEnabled"] = sense_enabled
        if mqtt_broker_id is not None:
            payload["mqttBrokerId"] = mqtt_broker_id
        if audio_detection is not None:
            payload["audioDetection"] = audio_detection.model_dump(by_alias=True, exclude_none=True)
        if detection_model_id is not None:
            payload["detectionModelId"] = detection_model_id

        return self._session.put(
            scope="camera",
            operation_id="updateDeviceCameraSense",
            path=path,
            json=payload,
            response_schema=DictResponse,
        )

    def get_device_camera_sense_object_detection_models(
        self, serial: str
    ) -> PaginatedResponse[GetDeviceCameraSenseObjectDetectionModelsResponse]:
        """Returns the MV Sense object detection model list for the given camera.

        [API documentation: getDeviceCameraSenseObjectDetectionModels](https://developer.cisco.com/meraki/api-v1/#!get-device-camera-sense-object-detection-models)

        Args:
            serial: Serial.

        Returns:
            Successful operation.

        Note:
            Returns a lazy PaginatedResponse
            that can be iterated or collected with `.collect()`.
            Page metadata is available on `.meta` and `.meta_pages`.

        Example API response:
            ```json
            [
              {
                "id": "0",
                "description": "Model A"
              }
            ]
            ```

        """
        serial = urllib.parse.quote(str(serial), safe="")
        path = f"/devices/{serial}/camera/sense/objectDetectionModels"

        return self._session.get_pages(
            scope="camera",
            operation_id="getDeviceCameraSenseObjectDetectionModels",
            path=path,
            item_schema=GetDeviceCameraSenseObjectDetectionModelsResponse,
        )

    def get_device_camera_video_settings(self, serial: str) -> GetDeviceCameraVideoSettingsResponse:
        """Returns video settings for the given camera.

        [API documentation: getDeviceCameraVideoSettings](https://developer.cisco.com/meraki/api-v1/#!get-device-camera-video-settings)

        Args:
            serial: Serial.

        Returns:
            Successful operation.

        Example API response:
            ```json
            {
              "externalRtspEnabled": true,
              "rtspUrl": "rtsp://10.0.0.1:9000/live"
            }
            ```

        """
        serial = urllib.parse.quote(str(serial), safe="")
        path = f"/devices/{serial}/camera/video/settings"

        return self._session.get(
            scope="camera",
            operation_id="getDeviceCameraVideoSettings",
            path=path,
            response_schema=GetDeviceCameraVideoSettingsResponse,
        )

    def update_device_camera_video_settings(
        self, serial: str, *, external_rtsp_enabled: bool | None = None
    ) -> UpdateDeviceCameraVideoSettingsResponse:
        """Update video settings for the given camera.

        [API documentation: updateDeviceCameraVideoSettings](https://developer.cisco.com/meraki/api-v1/#!update-device-camera-video-settings)

        Args:
            serial: Serial.
            external_rtsp_enabled: Boolean indicating if external rtsp stream is exposed.

        Returns:
            Successful operation.

        Example API response:
            ```json
            {
              "externalRtspEnabled": true,
              "rtspUrl": "rtsp://10.0.0.1:9000/live"
            }
            ```

        """
        serial = urllib.parse.quote(str(serial), safe="")
        path = f"/devices/{serial}/camera/video/settings"

        payload: dict[str, Any] = {}
        if external_rtsp_enabled is not None:
            payload["externalRtspEnabled"] = external_rtsp_enabled

        return self._session.put(
            scope="camera",
            operation_id="updateDeviceCameraVideoSettings",
            path=path,
            json=payload,
            response_schema=UpdateDeviceCameraVideoSettingsResponse,
        )

    def get_device_camera_video_link(
        self, serial: str, *, timestamp: str | None = None
    ) -> DictResponse:
        """Returns video link to the specified camera.

        [API documentation: getDeviceCameraVideoLink](https://developer.cisco.com/meraki/api-v1/#!get-device-camera-video-link)

        Args:
            serial: Serial.
            timestamp: [optional] The video link will start at this time. The timestamp should be a
                string in ISO8601 format. If no timestamp is specified, we will assume
                current time.

        Returns:
            Successful operation.

        Example API response:
            ```json
            {
              "url": "https://nxx.meraki.com/office-cameras/n/bs0a1k/manage/nodes/new_list/29048243992402?timestamp=1535732570077",
              "visionUrl": "https://vision.meraki.com/n/6482158978508419/cameras/29048243992402?ts=1535732570077"
            }
            ```

        """
        serial = urllib.parse.quote(str(serial), safe="")
        path = f"/devices/{serial}/camera/videoLink"

        params: dict[str, Any] = {}
        if timestamp is not None:
            params["timestamp"] = timestamp

        return self._session.get(
            scope="camera",
            operation_id="getDeviceCameraVideoLink",
            path=path,
            params=params,
            response_schema=DictResponse,
        )

    def get_device_camera_wireless_profiles(self, serial: str) -> DictResponse:
        """Returns wireless profile assigned to the given camera.

        [API documentation: getDeviceCameraWirelessProfiles](https://developer.cisco.com/meraki/api-v1/#!get-device-camera-wireless-profiles)

        Args:
            serial: Serial.

        Returns:
            Successful operation.

        Example API response:
            ```json
            {
              "ids": {
                "primary": "3",
                "secondary": "2",
                "backup": "1"
              }
            }
            ```

        """
        serial = urllib.parse.quote(str(serial), safe="")
        path = f"/devices/{serial}/camera/wirelessProfiles"

        return self._session.get(
            scope="camera",
            operation_id="getDeviceCameraWirelessProfiles",
            path=path,
            response_schema=DictResponse,
        )

    def update_device_camera_wireless_profiles(
        self, *, serial: str, ids: UpdateDeviceCameraWirelessProfilesIds
    ) -> DictResponse:
        """Assign wireless profiles to the given camera.

        [API documentation: updateDeviceCameraWirelessProfiles](https://developer.cisco.com/meraki/api-v1/#!update-device-camera-wireless-profiles)

        Args:
            serial: Serial.
            ids: The ids of the wireless profile to assign to the given camera.

        Returns:
            Successful operation.

        Example API response:
            ```json
            {
              "ids": {
                "primary": "3",
                "secondary": "2",
                "backup": "1"
              }
            }
            ```

        """
        serial = urllib.parse.quote(str(serial), safe="")
        path = f"/devices/{serial}/camera/wirelessProfiles"

        payload: dict[str, Any] = {}
        if ids is not None:
            payload["ids"] = ids.model_dump(by_alias=True, exclude_none=True)

        return self._session.put(
            scope="camera",
            operation_id="updateDeviceCameraWirelessProfiles",
            path=path,
            json=payload,
            response_schema=DictResponse,
        )

    def get_network_camera_quality_retention_profiles(
        self, network_id: str
    ) -> PaginatedResponse[GetNetworkCameraQualityRetentionProfilesResponseItem]:
        """List the quality retention profiles for this network.

        [API documentation: getNetworkCameraQualityRetentionProfiles](https://developer.cisco.com/meraki/api-v1/#!get-network-camera-quality-retention-profiles)

        Args:
            network_id: Network ID.

        Returns:
            Successful operation.

        Note:
            Returns a lazy PaginatedResponse
            that can be iterated or collected with `.collect()`.
            Page metadata is available on `.meta` and `.meta_pages`.

        Example API response:
            ```json
            [
              {
                "id": "1234",
                "networkId": "N_24329156",
                "name": "Sample quality retention profile",
                "restrictedBandwidthModeEnabled": true,
                "motionBasedRetentionEnabled": false,
                "audioRecordingEnabled": false,
                "cloudArchiveEnabled": false,
                "maxRetentionDays": 7,
                "scheduleId": "1234",
                "motionDetectorVersion": 2,
                "smartRetention": {
                  "enabled": true
                },
                "videoSettings": {
                  "MV32": {
                    "quality": "Enhanced",
                    "resolution": "1080x1080"
                  }
                }
              }
            ]
            ```

        """
        network_id = urllib.parse.quote(str(network_id), safe="")
        path = f"/networks/{network_id}/camera/qualityRetentionProfiles"

        return self._session.get_pages(
            scope="camera",
            operation_id="getNetworkCameraQualityRetentionProfiles",
            path=path,
            item_schema=GetNetworkCameraQualityRetentionProfilesResponseItem,
        )

    def create_network_camera_quality_retention_profile(
        self,
        *,
        network_id: str,
        name: str,
        motion_based_retention_enabled: bool | None = None,
        restricted_bandwidth_mode_enabled: bool | None = None,
        audio_recording_enabled: bool | None = None,
        cloud_archive_enabled: bool | None = None,
        motion_detector_version: int | None = None,
        smart_retention: CreateNetworkCameraQualityRetentionProfileSmartRetention | None = None,
        schedule_id: str | None = None,
        max_retention_days: int | None = None,
        video_settings: CreateNetworkCameraQualityRetentionProfileVideoSettings | None = None,
    ) -> CreateNetworkCameraQualityRetentionProfileResponse:
        """Creates new quality retention profile for this network.

        [API documentation: createNetworkCameraQualityRetentionProfile](https://developer.cisco.com/meraki/api-v1/#!create-network-camera-quality-retention-profile)

        Args:
            network_id: Network ID.
            name: The name of the new profile. Must be unique. This parameter is required.
            motion_based_retention_enabled: Deletes footage older than 3 days in which no motion was
                detected. Can be either true or false. Defaults to false. This setting
                does not apply to MV2 cameras.
            restricted_bandwidth_mode_enabled: Disable features that require additional bandwidth
                such as Motion Recap. Can be either true or false. Defaults to false.
                This setting does not apply to MV2 cameras.
            audio_recording_enabled: Whether or not to record audio. Can be either true or false.
                Defaults to false.
            cloud_archive_enabled: Create redundant video backup using Cloud Archive. Can be either
                true or false. Defaults to false.
            motion_detector_version: The version of the motion detector that will be used by the
                camera. Only applies to Gen 2 cameras. Defaults to v2.
            smart_retention: Smart Retention records footage in two qualities and intelligently
                retains higher quality when motion, people or vehicles are detected.
            schedule_id: Schedule for which this camera will record video, or 'null' to always
                record.
            max_retention_days: The maximum number of days for which the data will be stored, or
                'null' to keep data until storage space runs out. If the former, it can
                be in the range of one to ninety days.
            video_settings: Video quality and resolution settings for all the camera models.

        Returns:
            Successful operation.

        Example API response:
            ```json
            {
              "id": "1234",
              "networkId": "N_24329156",
              "name": "Sample quality retention profile",
              "restrictedBandwidthModeEnabled": true,
              "motionBasedRetentionEnabled": false,
              "audioRecordingEnabled": false,
              "cloudArchiveEnabled": false,
              "maxRetentionDays": 7,
              "scheduleId": "1234",
              "motionDetectorVersion": 2,
              "smartRetention": {
                "enabled": true
              },
              "videoSettings": {
                "MV32": {
                  "quality": "Enhanced",
                  "resolution": "1080x1080"
                }
              }
            }
            ```

        """
        network_id = urllib.parse.quote(str(network_id), safe="")
        path = f"/networks/{network_id}/camera/qualityRetentionProfiles"

        payload: dict[str, Any] = {}
        if name is not None:
            payload["name"] = name
        if motion_based_retention_enabled is not None:
            payload["motionBasedRetentionEnabled"] = motion_based_retention_enabled
        if restricted_bandwidth_mode_enabled is not None:
            payload["restrictedBandwidthModeEnabled"] = restricted_bandwidth_mode_enabled
        if audio_recording_enabled is not None:
            payload["audioRecordingEnabled"] = audio_recording_enabled
        if cloud_archive_enabled is not None:
            payload["cloudArchiveEnabled"] = cloud_archive_enabled
        if motion_detector_version is not None:
            payload["motionDetectorVersion"] = motion_detector_version
        if smart_retention is not None:
            payload["smartRetention"] = smart_retention.model_dump(by_alias=True, exclude_none=True)
        if schedule_id is not None:
            payload["scheduleId"] = schedule_id
        if max_retention_days is not None:
            payload["maxRetentionDays"] = max_retention_days
        if video_settings is not None:
            payload["videoSettings"] = video_settings.model_dump(by_alias=True, exclude_none=True)

        return self._session.post(
            scope="camera",
            operation_id="createNetworkCameraQualityRetentionProfile",
            path=path,
            json=payload,
            response_schema=CreateNetworkCameraQualityRetentionProfileResponse,
        )

    def get_network_camera_quality_retention_profile(
        self, *, network_id: str, quality_retention_profile_id: str
    ) -> GetNetworkCameraQualityRetentionProfileResponse:
        """Retrieve a single quality retention profile.

        [API documentation: getNetworkCameraQualityRetentionProfile](https://developer.cisco.com/meraki/api-v1/#!get-network-camera-quality-retention-profile)

        Args:
            network_id: Network ID.
            quality_retention_profile_id: Quality retention profile ID.

        Returns:
            Successful operation.

        Example API response:
            ```json
            {
              "id": "1234",
              "networkId": "N_24329156",
              "name": "Sample quality retention profile",
              "restrictedBandwidthModeEnabled": true,
              "motionBasedRetentionEnabled": false,
              "audioRecordingEnabled": false,
              "cloudArchiveEnabled": false,
              "maxRetentionDays": 7,
              "scheduleId": "1234",
              "motionDetectorVersion": 2,
              "smartRetention": {
                "enabled": true
              },
              "videoSettings": {
                "MV32": {
                  "quality": "Enhanced",
                  "resolution": "1080x1080"
                }
              }
            }
            ```

        """
        network_id = urllib.parse.quote(str(network_id), safe="")
        quality_retention_profile_id = urllib.parse.quote(
            str(quality_retention_profile_id), safe=""
        )
        path = (
            f"/networks/{network_id}/camera/qualityRetentionProfiles/{quality_retention_profile_id}"
        )

        return self._session.get(
            scope="camera",
            operation_id="getNetworkCameraQualityRetentionProfile",
            path=path,
            response_schema=GetNetworkCameraQualityRetentionProfileResponse,
        )

    def update_network_camera_quality_retention_profile(
        self,
        *,
        network_id: str,
        quality_retention_profile_id: str,
        name: str | None = None,
        motion_based_retention_enabled: bool | None = None,
        restricted_bandwidth_mode_enabled: bool | None = None,
        audio_recording_enabled: bool | None = None,
        cloud_archive_enabled: bool | None = None,
        motion_detector_version: int | None = None,
        smart_retention: UpdateNetworkCameraQualityRetentionProfileSmartRetention | None = None,
        schedule_id: str | None = None,
        max_retention_days: int | None = None,
        video_settings: UpdateNetworkCameraQualityRetentionProfileVideoSettings | None = None,
    ) -> UpdateNetworkCameraQualityRetentionProfileResponse:
        """Update an existing quality retention profile for this network.

        [API documentation: updateNetworkCameraQualityRetentionProfile](https://developer.cisco.com/meraki/api-v1/#!update-network-camera-quality-retention-profile)

        Args:
            network_id: Network ID.
            quality_retention_profile_id: Quality retention profile ID.
            name: The name of the new profile. Must be unique.
            motion_based_retention_enabled: Deletes footage older than 3 days in which no motion was
                detected. Can be either true or false. Defaults to false. This setting
                does not apply to MV2 cameras.
            restricted_bandwidth_mode_enabled: Disable features that require additional bandwidth
                such as Motion Recap. Can be either true or false. Defaults to false.
                This setting does not apply to MV2 cameras.
            audio_recording_enabled: Whether or not to record audio. Can be either true or false.
                Defaults to false.
            cloud_archive_enabled: Create redundant video backup using Cloud Archive. Can be either
                true or false. Defaults to false.
            motion_detector_version: The version of the motion detector that will be used by the
                camera. Only applies to Gen 2 cameras. Defaults to v2.
            smart_retention: Smart Retention records footage in two qualities and intelligently
                retains higher quality when motion, people or vehicles are detected.
            schedule_id: Schedule for which this camera will record video, or 'null' to always
                record.
            max_retention_days: The maximum number of days for which the data will be stored, or
                'null' to keep data until storage space runs out. If the former, it can
                be in the range of one to ninety days.
            video_settings: Video quality and resolution settings for all the camera models.

        Returns:
            Successful operation.

        Example API response:
            ```json
            {
              "id": "1234",
              "networkId": "N_24329156",
              "name": "Sample quality retention profile",
              "restrictedBandwidthModeEnabled": true,
              "motionBasedRetentionEnabled": false,
              "audioRecordingEnabled": false,
              "cloudArchiveEnabled": false,
              "maxRetentionDays": 7,
              "scheduleId": "1234",
              "motionDetectorVersion": 2,
              "smartRetention": {
                "enabled": true
              },
              "videoSettings": {
                "MV32": {
                  "quality": "Enhanced",
                  "resolution": "1080x1080"
                }
              }
            }
            ```

        """
        network_id = urllib.parse.quote(str(network_id), safe="")
        quality_retention_profile_id = urllib.parse.quote(
            str(quality_retention_profile_id), safe=""
        )
        path = (
            f"/networks/{network_id}/camera/qualityRetentionProfiles/{quality_retention_profile_id}"
        )

        payload: dict[str, Any] = {}
        if name is not None:
            payload["name"] = name
        if motion_based_retention_enabled is not None:
            payload["motionBasedRetentionEnabled"] = motion_based_retention_enabled
        if restricted_bandwidth_mode_enabled is not None:
            payload["restrictedBandwidthModeEnabled"] = restricted_bandwidth_mode_enabled
        if audio_recording_enabled is not None:
            payload["audioRecordingEnabled"] = audio_recording_enabled
        if cloud_archive_enabled is not None:
            payload["cloudArchiveEnabled"] = cloud_archive_enabled
        if motion_detector_version is not None:
            payload["motionDetectorVersion"] = motion_detector_version
        if smart_retention is not None:
            payload["smartRetention"] = smart_retention.model_dump(by_alias=True, exclude_none=True)
        if schedule_id is not None:
            payload["scheduleId"] = schedule_id
        if max_retention_days is not None:
            payload["maxRetentionDays"] = max_retention_days
        if video_settings is not None:
            payload["videoSettings"] = video_settings.model_dump(by_alias=True, exclude_none=True)

        return self._session.put(
            scope="camera",
            operation_id="updateNetworkCameraQualityRetentionProfile",
            path=path,
            json=payload,
            response_schema=UpdateNetworkCameraQualityRetentionProfileResponse,
        )

    def delete_network_camera_quality_retention_profile(
        self, *, network_id: str, quality_retention_profile_id: str
    ) -> None:
        """Delete an existing quality retention profile for this network.

        [API documentation: deleteNetworkCameraQualityRetentionProfile](https://developer.cisco.com/meraki/api-v1/#!delete-network-camera-quality-retention-profile)

        Args:
            network_id: Network ID.
            quality_retention_profile_id: Quality retention profile ID.

        Returns:
            Successful operation.

        """
        network_id = urllib.parse.quote(str(network_id), safe="")
        quality_retention_profile_id = urllib.parse.quote(
            str(quality_retention_profile_id), safe=""
        )
        path = (
            f"/networks/{network_id}/camera/qualityRetentionProfiles/{quality_retention_profile_id}"
        )

        return self._session.delete(
            scope="camera", operation_id="deleteNetworkCameraQualityRetentionProfile", path=path
        )

    def get_network_camera_schedules(
        self, network_id: str
    ) -> PaginatedResponse[GetNetworkCameraSchedulesResponseItem]:
        """Returns a list of all camera recording schedules.

        [API documentation: getNetworkCameraSchedules](https://developer.cisco.com/meraki/api-v1/#!get-network-camera-schedules)

        Args:
            network_id: Network ID.

        Returns:
            Successful operation.

        Note:
            Returns a lazy PaginatedResponse
            that can be iterated or collected with `.collect()`.
            Page metadata is available on `.meta` and `.meta_pages`.

        Example API response:
            ```json
            [
              {
                "id": "123",
                "name": "Weekday schedule"
              }
            ]
            ```

        """
        network_id = urllib.parse.quote(str(network_id), safe="")
        path = f"/networks/{network_id}/camera/schedules"

        return self._session.get_pages(
            scope="camera",
            operation_id="getNetworkCameraSchedules",
            path=path,
            item_schema=GetNetworkCameraSchedulesResponseItem,
        )

    def get_network_camera_wireless_profiles(
        self, network_id: str
    ) -> PaginatedResponse[GetNetworkCameraWirelessProfilesResponseItem]:
        """List the camera wireless profiles for this network.

        [API documentation: getNetworkCameraWirelessProfiles](https://developer.cisco.com/meraki/api-v1/#!get-network-camera-wireless-profiles)

        Args:
            network_id: Network ID.

        Returns:
            Successful operation.

        Note:
            Returns a lazy PaginatedResponse
            that can be iterated or collected with `.collect()`.
            Page metadata is available on `.meta` and `.meta_pages`.

        Example API response:
            ```json
            [
              {
                "id": "152",
                "name": "wireless profile A",
                "appliedDeviceCount": 0,
                "ssid": {
                  "name": "ssid test",
                  "authMode": "8021x-radius",
                  "encryptionMode": "wpa-eap",
                  "psk": "sampleKey"
                },
                "identity": {
                  "username": "identityname",
                  "password": "password123"
                }
              }
            ]
            ```

        """
        network_id = urllib.parse.quote(str(network_id), safe="")
        path = f"/networks/{network_id}/camera/wirelessProfiles"

        return self._session.get_pages(
            scope="camera",
            operation_id="getNetworkCameraWirelessProfiles",
            path=path,
            item_schema=GetNetworkCameraWirelessProfilesResponseItem,
        )

    def create_network_camera_wireless_profile(
        self,
        *,
        network_id: str,
        name: str,
        ssid: CreateNetworkCameraWirelessProfileSsid,
        identity: CreateNetworkCameraWirelessProfileIdentity | None = None,
    ) -> CreateNetworkCameraWirelessProfileResponse:
        """Creates a new camera wireless profile for this network.

        [API documentation: createNetworkCameraWirelessProfile](https://developer.cisco.com/meraki/api-v1/#!create-network-camera-wireless-profile)

        Args:
            network_id: Network ID.
            name: The name of the camera wireless profile. This parameter is required.
            ssid: The details of the SSID config.
            identity: The identity of the wireless profile. Required for creating wireless profiles
                in 8021x-radius auth mode.

        Returns:
            Successful operation.

        Example API response:
            ```json
            {
              "id": "152",
              "name": "wireless profile A",
              "appliedDeviceCount": 0,
              "ssid": {
                "name": "ssid test",
                "authMode": "8021x-radius",
                "encryptionMode": "wpa-eap",
                "psk": "sampleKey"
              },
              "identity": {
                "username": "identityname",
                "password": "password123"
              }
            }
            ```

        """
        network_id = urllib.parse.quote(str(network_id), safe="")
        path = f"/networks/{network_id}/camera/wirelessProfiles"

        payload: dict[str, Any] = {}
        if name is not None:
            payload["name"] = name
        if ssid is not None:
            payload["ssid"] = ssid.model_dump(by_alias=True, exclude_none=True)
        if identity is not None:
            payload["identity"] = identity.model_dump(by_alias=True, exclude_none=True)

        return self._session.post(
            scope="camera",
            operation_id="createNetworkCameraWirelessProfile",
            path=path,
            json=payload,
            response_schema=CreateNetworkCameraWirelessProfileResponse,
        )

    def get_network_camera_wireless_profile(
        self, *, network_id: str, wireless_profile_id: str
    ) -> GetNetworkCameraWirelessProfileResponse:
        """Retrieve a single camera wireless profile.

        [API documentation: getNetworkCameraWirelessProfile](https://developer.cisco.com/meraki/api-v1/#!get-network-camera-wireless-profile)

        Args:
            network_id: Network ID.
            wireless_profile_id: Wireless profile ID.

        Returns:
            Successful operation.

        Example API response:
            ```json
            {
              "id": "152",
              "name": "wireless profile A",
              "appliedDeviceCount": 0,
              "ssid": {
                "name": "ssid test",
                "authMode": "8021x-radius",
                "encryptionMode": "wpa-eap",
                "psk": "sampleKey"
              },
              "identity": {
                "username": "identityname",
                "password": "password123"
              }
            }
            ```

        """
        network_id = urllib.parse.quote(str(network_id), safe="")
        wireless_profile_id = urllib.parse.quote(str(wireless_profile_id), safe="")
        path = f"/networks/{network_id}/camera/wirelessProfiles/{wireless_profile_id}"

        return self._session.get(
            scope="camera",
            operation_id="getNetworkCameraWirelessProfile",
            path=path,
            response_schema=GetNetworkCameraWirelessProfileResponse,
        )

    def update_network_camera_wireless_profile(
        self,
        *,
        network_id: str,
        wireless_profile_id: str,
        name: str | None = None,
        ssid: UpdateNetworkCameraWirelessProfileSsid | None = None,
        identity: UpdateNetworkCameraWirelessProfileIdentity | None = None,
    ) -> UpdateNetworkCameraWirelessProfileResponse:
        """Update an existing camera wireless profile in this network.

        [API documentation: updateNetworkCameraWirelessProfile](https://developer.cisco.com/meraki/api-v1/#!update-network-camera-wireless-profile)

        Args:
            network_id: Network ID.
            wireless_profile_id: Wireless profile ID.
            name: The name of the camera wireless profile.
            ssid: The details of the SSID config.
            identity: The identity of the wireless profile. Required for creating wireless profiles
                in 8021x-radius auth mode.

        Returns:
            Successful operation.

        Example API response:
            ```json
            {
              "id": "152",
              "name": "wireless profile A",
              "appliedDeviceCount": 0,
              "ssid": {
                "name": "ssid test",
                "authMode": "8021x-radius",
                "encryptionMode": "wpa-eap",
                "psk": "sampleKey"
              },
              "identity": {
                "username": "identityname",
                "password": "password123"
              }
            }
            ```

        """
        network_id = urllib.parse.quote(str(network_id), safe="")
        wireless_profile_id = urllib.parse.quote(str(wireless_profile_id), safe="")
        path = f"/networks/{network_id}/camera/wirelessProfiles/{wireless_profile_id}"

        payload: dict[str, Any] = {}
        if name is not None:
            payload["name"] = name
        if ssid is not None:
            payload["ssid"] = ssid.model_dump(by_alias=True, exclude_none=True)
        if identity is not None:
            payload["identity"] = identity.model_dump(by_alias=True, exclude_none=True)

        return self._session.put(
            scope="camera",
            operation_id="updateNetworkCameraWirelessProfile",
            path=path,
            json=payload,
            response_schema=UpdateNetworkCameraWirelessProfileResponse,
        )

    def delete_network_camera_wireless_profile(
        self, *, network_id: str, wireless_profile_id: str
    ) -> None:
        """Delete an existing camera wireless profile for this network.

        [API documentation: deleteNetworkCameraWirelessProfile](https://developer.cisco.com/meraki/api-v1/#!delete-network-camera-wireless-profile)

        Args:
            network_id: Network ID.
            wireless_profile_id: Wireless profile ID.

        Returns:
            Successful operation.

        """
        network_id = urllib.parse.quote(str(network_id), safe="")
        wireless_profile_id = urllib.parse.quote(str(wireless_profile_id), safe="")
        path = f"/networks/{network_id}/camera/wirelessProfiles/{wireless_profile_id}"

        return self._session.delete(
            scope="camera", operation_id="deleteNetworkCameraWirelessProfile", path=path
        )

    def get_organization_camera_boundaries_areas_by_device(
        self, organization_id: str, *, serials: list[str] | None = None
    ) -> PaginatedResponse[GetOrganizationCameraBoundariesAreasByDeviceResponseItem]:
        """Returns all configured area boundaries of cameras.

        [API documentation: getOrganizationCameraBoundariesAreasByDevice](https://developer.cisco.com/meraki/api-v1/#!get-organization-camera-boundaries-areas-by-device)

        Args:
            organization_id: Organization ID.
            serials: A list of serial numbers. The returned cameras will be filtered to only include
                these serials.

        Returns:
            Successful operation.

        Note:
            Returns a lazy PaginatedResponse
            that can be iterated or collected with `.collect()`.
            Page metadata is available on `.meta` and `.meta_pages`.

        Example API response:
            ```json
            [
              {
                "networkId": "N_24329156",
                "serial": "Q234-ABCD-5678",
                "boundaries": {
                  "id": "k74272e",
                  "type": "area",
                  "name": "myarea",
                  "vertices": [
                    {
                      "x": 0.1,
                      "y": 0.1
                    }
                  ]
                }
              }
            ]
            ```

        """
        organization_id = urllib.parse.quote(str(organization_id), safe="")
        path = f"/organizations/{organization_id}/camera/boundaries/areas/byDevice"

        params: dict[str, Any] = {}
        if serials is not None:
            params["serials[]"] = serials

        return self._session.get_pages(
            scope="camera",
            operation_id="getOrganizationCameraBoundariesAreasByDevice",
            path=path,
            params=params,
            item_schema=GetOrganizationCameraBoundariesAreasByDeviceResponseItem,
        )

    def get_organization_camera_boundaries_lines_by_device(
        self, organization_id: str, *, serials: list[str] | None = None
    ) -> PaginatedResponse[GetOrganizationCameraBoundariesLinesByDeviceResponseItem]:
        """Returns all configured crossingline boundaries of cameras.

        [API documentation: getOrganizationCameraBoundariesLinesByDevice](https://developer.cisco.com/meraki/api-v1/#!get-organization-camera-boundaries-lines-by-device)

        Args:
            organization_id: Organization ID.
            serials: A list of serial numbers. The returned cameras will be filtered to only include
                these serials.

        Returns:
            Successful operation.

        Note:
            Returns a lazy PaginatedResponse
            that can be iterated or collected with `.collect()`.
            Page metadata is available on `.meta` and `.meta_pages`.

        Example API response:
            ```json
            [
              {
                "networkId": "N_24329156",
                "serial": "Q234-ABCD-5678",
                "boundaries": {
                  "id": "k74272e",
                  "type": "line",
                  "name": "mycline",
                  "vertices": [
                    {
                      "x": 0.375,
                      "y": 0.5
                    }
                  ],
                  "directionVertex": {
                    "x": 0.5,
                    "y": 0.54
                  }
                }
              }
            ]
            ```

        """
        organization_id = urllib.parse.quote(str(organization_id), safe="")
        path = f"/organizations/{organization_id}/camera/boundaries/lines/byDevice"

        params: dict[str, Any] = {}
        if serials is not None:
            params["serials[]"] = serials

        return self._session.get_pages(
            scope="camera",
            operation_id="getOrganizationCameraBoundariesLinesByDevice",
            path=path,
            params=params,
            item_schema=GetOrganizationCameraBoundariesLinesByDeviceResponseItem,
        )

    def get_organization_camera_custom_analytics_artifacts(
        self, organization_id: str
    ) -> PaginatedResponse[GetOrganizationCameraCustomAnalyticsArtifactsResponseItem]:
        """List Custom Analytics Artifacts.

        [API documentation: getOrganizationCameraCustomAnalyticsArtifacts](https://developer.cisco.com/meraki/api-v1/#!get-organization-camera-custom-analytics-artifacts)

        Args:
            organization_id: Organization ID.

        Returns:
            Successful operation.

        Note:
            Returns a lazy PaginatedResponse
            that can be iterated or collected with `.collect()`.
            Page metadata is available on `.meta` and `.meta_pages`.

        Example API response:
            ```json
            [
              {
                "artifactId": "1",
                "organizationId": "2",
                "name": "example",
                "status": {
                  "type": "pending",
                  "message": "sample message"
                }
              }
            ]
            ```

        """
        organization_id = urllib.parse.quote(str(organization_id), safe="")
        path = f"/organizations/{organization_id}/camera/customAnalytics/artifacts"

        return self._session.get_pages(
            scope="camera",
            operation_id="getOrganizationCameraCustomAnalyticsArtifacts",
            path=path,
            item_schema=GetOrganizationCameraCustomAnalyticsArtifactsResponseItem,
        )

    def create_organization_camera_custom_analytics_artifact(
        self, organization_id: str, *, name: str | None = None
    ) -> CreateOrganizationCameraCustomAnalyticsArtifactResponse:
        """Create custom analytics artifact.

        [API documentation: createOrganizationCameraCustomAnalyticsArtifact](https://developer.cisco.com/meraki/api-v1/#!create-organization-camera-custom-analytics-artifact)

        Args:
            organization_id: Organization ID.
            name: Unique name of the artifact.

        Returns:
            Successful operation.

        Example API response:
            ```json
            {
              "artifactId": "1",
              "organizationId": "2",
              "name": "example",
              "status": {
                "type": "pending",
                "message": "sample message"
              },
              "uploadId": "00112233445566778899aabbccddeeff",
              "uploadUrl": "https://meraki_custom_cv_upload_url",
              "uploadUrlExpiry": "2022-01-23T01:23:45.123456+00:00"
            }
            ```

        """
        organization_id = urllib.parse.quote(str(organization_id), safe="")
        path = f"/organizations/{organization_id}/camera/customAnalytics/artifacts"

        payload: dict[str, Any] = {}
        if name is not None:
            payload["name"] = name

        return self._session.post(
            scope="camera",
            operation_id="createOrganizationCameraCustomAnalyticsArtifact",
            path=path,
            json=payload,
            response_schema=CreateOrganizationCameraCustomAnalyticsArtifactResponse,
        )

    def get_organization_camera_custom_analytics_artifact(
        self, *, organization_id: str, artifact_id: str
    ) -> GetOrganizationCameraCustomAnalyticsArtifactResponse:
        """Get Custom Analytics Artifact.

        [API documentation: getOrganizationCameraCustomAnalyticsArtifact](https://developer.cisco.com/meraki/api-v1/#!get-organization-camera-custom-analytics-artifact)

        Args:
            organization_id: Organization ID.
            artifact_id: Artifact ID.

        Returns:
            Successful operation.

        Example API response:
            ```json
            {
              "artifactId": "1",
              "organizationId": "2",
              "name": "example",
              "status": {
                "type": "pending",
                "message": "sample message"
              }
            }
            ```

        """
        organization_id = urllib.parse.quote(str(organization_id), safe="")
        artifact_id = urllib.parse.quote(str(artifact_id), safe="")
        path = f"/organizations/{organization_id}/camera/customAnalytics/artifacts/{artifact_id}"

        return self._session.get(
            scope="camera",
            operation_id="getOrganizationCameraCustomAnalyticsArtifact",
            path=path,
            response_schema=GetOrganizationCameraCustomAnalyticsArtifactResponse,
        )

    def delete_organization_camera_custom_analytics_artifact(
        self, *, organization_id: str, artifact_id: str
    ) -> None:
        """Delete Custom Analytics Artifact.

        [API documentation: deleteOrganizationCameraCustomAnalyticsArtifact](https://developer.cisco.com/meraki/api-v1/#!delete-organization-camera-custom-analytics-artifact)

        Args:
            organization_id: Organization ID.
            artifact_id: Artifact ID.

        Returns:
            Successful operation.

        """
        organization_id = urllib.parse.quote(str(organization_id), safe="")
        artifact_id = urllib.parse.quote(str(artifact_id), safe="")
        path = f"/organizations/{organization_id}/camera/customAnalytics/artifacts/{artifact_id}"

        return self._session.delete(
            scope="camera",
            operation_id="deleteOrganizationCameraCustomAnalyticsArtifact",
            path=path,
        )

    def get_organization_camera_detections_history_by_boundary_by_interval(
        self,
        *,
        organization_id: str,
        boundary_ids: list[str],
        ranges: list[dict[str, Any]],
        duration: int | None = None,
        per_page: int | None = None,
        boundary_types: GetOrganizationCameraDetectionsHistoryByBoundaryByIntervalBoundaryTypes
        | None = None,
        total_pages: int | Literal["all"] = "all",
        direction: Literal["prev", "next"] = "next",
    ) -> PaginatedResponse[GetOrganizationCameraDetectionsHistoryByBoundaryByIntervalResponseItem]:
        """Returns analytics data for timespans.

        [API documentation: getOrganizationCameraDetectionsHistoryByBoundaryByInterval](https://developer.cisco.com/meraki/api-v1/#!get-organization-camera-detections-history-by-boundary-by-interval)

        Args:
            organization_id: Organization ID.
            boundary_ids: A list of boundary ids. The returned cameras will be filtered to only
                include these ids.
            ranges: A list of time ranges with intervals.
            duration: The minimum time, in seconds, that the person or car remains in the area to be
                counted. Defaults to boundary configuration or 60.
            per_page: The number of entries per page returned. Acceptable range is 1 - 1000.
                Defaults to 1000.
            boundary_types: The detection types. Defaults to 'person'.
            total_pages: use with per_page to get total results up to total_pages * per_page; -1 or
                "all" for all pages.
            direction: direction to paginate, either "next" (default) or "prev" page.

        Returns:
            Successful operation.

        Note:
            Returns a lazy PaginatedResponse
            that can be iterated or collected with `.collect()`.
            Page metadata is available on `.meta` and `.meta_pages`.

        Example API response:
            ```json
            [
              {
                "boundaryId": "k74272e",
                "type": "line",
                "results": {
                  "startTime": "2018-02-11T00:00:00Z",
                  "endTime": "2018-05-12T00:00:00Z",
                  "objectType": "person",
                  "in": 22,
                  "out": 13
                }
              }
            ]
            ```

        """
        organization_id = urllib.parse.quote(str(organization_id), safe="")
        path = f"/organizations/{organization_id}/camera/detections/history/byBoundary/byInterval"

        params: dict[str, Any] = {}
        if boundary_ids is not None:
            params["boundaryIds[]"] = boundary_ids
        if ranges is not None:
            params["ranges[]"] = ranges
        if duration is not None:
            params["duration"] = duration
        if per_page is not None:
            params["perPage"] = per_page
        if boundary_types is not None:
            params["boundaryTypes[]"] = boundary_types

        return self._session.get_pages(
            scope="camera",
            operation_id="getOrganizationCameraDetectionsHistoryByBoundaryByInterval",
            path=path,
            params=params,
            total_pages=total_pages,
            direction=direction,
            item_schema=GetOrganizationCameraDetectionsHistoryByBoundaryByIntervalResponseItem,
        )

    def get_organization_camera_onboarding_statuses(
        self,
        organization_id: str,
        *,
        serials: list[str] | None = None,
        network_ids: list[str] | None = None,
    ) -> PaginatedResponse[GetOrganizationCameraOnboardingStatusesResponse]:
        """Fetch onboarding status of cameras.

        [API documentation: getOrganizationCameraOnboardingStatuses](https://developer.cisco.com/meraki/api-v1/#!get-organization-camera-onboarding-statuses)

        Args:
            organization_id: Organization ID.
            serials: A list of serial numbers. The returned cameras will be filtered to only include
                these serials.
            network_ids: A list of network IDs. The returned cameras will be filtered to only
                include these networks.

        Returns:
            Successful operation.

        Note:
            Returns a lazy PaginatedResponse
            that can be iterated or collected with `.collect()`.
            Page metadata is available on `.meta` and `.meta_pages`.

        Example API response:
            ```json
            [
              {
                "networkId": "N_12345",
                "serial": "Q2AB-CDEF-GHIJ",
                "status": "pending onboarding",
                "updatedAt": "2021/03/24 15:23:47.101068 -0700"
              }
            ]
            ```

        """
        organization_id = urllib.parse.quote(str(organization_id), safe="")
        path = f"/organizations/{organization_id}/camera/onboarding/statuses"

        params: dict[str, Any] = {}
        if serials is not None:
            params["serials[]"] = serials
        if network_ids is not None:
            params["networkIds[]"] = network_ids

        return self._session.get_pages(
            scope="camera",
            operation_id="getOrganizationCameraOnboardingStatuses",
            path=path,
            params=params,
            item_schema=GetOrganizationCameraOnboardingStatusesResponse,
        )

    def update_organization_camera_onboarding_statuses(
        self,
        organization_id: str,
        *,
        serial: str | None = None,
        wireless_credentials_sent: bool | None = None,
    ) -> DictResponse:
        """Notify that credential handoff to camera has completed.

        [API documentation: updateOrganizationCameraOnboardingStatuses](https://developer.cisco.com/meraki/api-v1/#!update-organization-camera-onboarding-statuses)

        Args:
            organization_id: Organization ID.
            serial: Serial of camera.
            wireless_credentials_sent: Note whether credentials were sent successfully.

        Returns:
            Successful operation.

        Example API response:
            ```json
            {
              "success": true
            }
            ```

        """
        organization_id = urllib.parse.quote(str(organization_id), safe="")
        path = f"/organizations/{organization_id}/camera/onboarding/statuses"

        payload: dict[str, Any] = {}
        if serial is not None:
            payload["serial"] = serial
        if wireless_credentials_sent is not None:
            payload["wirelessCredentialsSent"] = wireless_credentials_sent

        return self._session.put(
            scope="camera",
            operation_id="updateOrganizationCameraOnboardingStatuses",
            path=path,
            json=payload,
            response_schema=DictResponse,
        )

    def get_organization_camera_permissions(
        self, organization_id: str
    ) -> PaginatedResponse[GetOrganizationCameraPermissionsResponseItem]:
        """List the permissions scopes for this organization.

        [API documentation: getOrganizationCameraPermissions](https://developer.cisco.com/meraki/api-v1/#!get-organization-camera-permissions)

        Args:
            organization_id: Organization ID.

        Returns:
            Successful operation.

        Note:
            Returns a lazy PaginatedResponse
            that can be iterated or collected with `.collect()`.
            Page metadata is available on `.meta` and `.meta_pages`.

        Example API response:
            ```json
            [
              {
                "id": "1234",
                "name": "camera_video",
                "level": "live_video"
              }
            ]
            ```

        """
        organization_id = urllib.parse.quote(str(organization_id), safe="")
        path = f"/organizations/{organization_id}/camera/permissions"

        return self._session.get_pages(
            scope="camera",
            operation_id="getOrganizationCameraPermissions",
            path=path,
            item_schema=GetOrganizationCameraPermissionsResponseItem,
        )

    def get_organization_camera_permission(
        self, *, organization_id: str, permission_scope_id: str
    ) -> GetOrganizationCameraPermissionResponse:
        """Retrieve a single permission scope.

        [API documentation: getOrganizationCameraPermission](https://developer.cisco.com/meraki/api-v1/#!get-organization-camera-permission)

        Args:
            organization_id: Organization ID.
            permission_scope_id: Permission scope ID.

        Returns:
            Successful operation.

        Example API response:
            ```json
            {
              "id": "1234",
              "name": "camera_video",
              "level": "live_video"
            }
            ```

        """
        organization_id = urllib.parse.quote(str(organization_id), safe="")
        permission_scope_id = urllib.parse.quote(str(permission_scope_id), safe="")
        path = f"/organizations/{organization_id}/camera/permissions/{permission_scope_id}"

        return self._session.get(
            scope="camera",
            operation_id="getOrganizationCameraPermission",
            path=path,
            response_schema=GetOrganizationCameraPermissionResponse,
        )

    def get_organization_camera_roles(
        self, organization_id: str
    ) -> PaginatedResponse[GetOrganizationCameraRolesResponseItem]:
        """List all the roles in this organization.

        [API documentation: getOrganizationCameraRoles](https://developer.cisco.com/meraki/api-v1/#!get-organization-camera-roles)

        Args:
            organization_id: Organization ID.

        Returns:
            Successful operation.

        Note:
            Returns a lazy PaginatedResponse
            that can be iterated or collected with `.collect()`.
            Page metadata is available on `.meta` and `.meta_pages`.

        Example API response:
            ```json
            [
              {
                "name": "Security_Guard",
                "appliedOnDevices": [
                  {
                    "tag": "reception-desk",
                    "id": "",
                    "permissionScopeId": "1",
                    "permissionScope": "camera-video",
                    "permissionLevel": "view_and_export"
                  }
                ],
                "appliedOnNetworks": [
                  {
                    "tag": "",
                    "id": "2568",
                    "permissionScopeId": "2",
                    "permissionScope": "camera-video",
                    "permissionLevel": "view"
                  }
                ],
                "appliedOrgWide": [
                  {
                    "tag": "building-a",
                    "permissionScopeId": "2",
                    "permissionScope": "camera_video",
                    "permissionLevel": "view_live"
                  }
                ]
              }
            ]
            ```

        """
        organization_id = urllib.parse.quote(str(organization_id), safe="")
        path = f"/organizations/{organization_id}/camera/roles"

        return self._session.get_pages(
            scope="camera",
            operation_id="getOrganizationCameraRoles",
            path=path,
            item_schema=GetOrganizationCameraRolesResponseItem,
        )

    def create_organization_camera_role(
        self,
        *,
        organization_id: str,
        name: str,
        applied_on_devices: list[CreateOrganizationCameraRoleAppliedOnDevicesItem] | None = None,
        applied_on_networks: list[CreateOrganizationCameraRoleAppliedOnNetworksItem] | None = None,
        applied_org_wide: list[CreateOrganizationCameraRoleAppliedOrgWideItem] | None = None,
    ) -> CreateOrganizationCameraRoleResponse:
        """Creates new role for this organization.

        [API documentation: createOrganizationCameraRole](https://developer.cisco.com/meraki/api-v1/#!create-organization-camera-role)

        Args:
            organization_id: Organization ID.
            name: The name of the new role. Must be unique. This parameter is required.
            applied_on_devices: Device tag on which this specified permission is applied.
            applied_on_networks: Network tag on which this specified permission is applied.
            applied_org_wide: Permissions to be applied org wide.

        Returns:
            Successful operation.

        Example API response:
            ```json
            {
              "name": "Security_Guard",
              "appliedOnDevices": [
                {
                  "tag": "reception-desk",
                  "id": "",
                  "permissionScopeId": "1",
                  "permissionScope": "camera-video",
                  "permissionLevel": "view_and_export"
                }
              ],
              "appliedOnNetworks": [
                {
                  "tag": "",
                  "id": "2568",
                  "permissionScopeId": "2",
                  "permissionScope": "camera-video",
                  "permissionLevel": "view"
                }
              ],
              "appliedOrgWide": [
                {
                  "tag": "building-a",
                  "permissionScopeId": "2",
                  "permissionScope": "camera_video",
                  "permissionLevel": "view_live"
                }
              ]
            }
            ```

        """
        organization_id = urllib.parse.quote(str(organization_id), safe="")
        path = f"/organizations/{organization_id}/camera/roles"

        payload: dict[str, Any] = {}
        if name is not None:
            payload["name"] = name
        if applied_on_devices is not None:
            payload["appliedOnDevices"] = [
                item.model_dump(by_alias=True, exclude_none=True) for item in applied_on_devices
            ]
        if applied_on_networks is not None:
            payload["appliedOnNetworks"] = [
                item.model_dump(by_alias=True, exclude_none=True) for item in applied_on_networks
            ]
        if applied_org_wide is not None:
            payload["appliedOrgWide"] = [
                item.model_dump(by_alias=True, exclude_none=True) for item in applied_org_wide
            ]

        return self._session.post(
            scope="camera",
            operation_id="createOrganizationCameraRole",
            path=path,
            json=payload,
            response_schema=CreateOrganizationCameraRoleResponse,
        )

    def get_organization_camera_role(
        self, *, organization_id: str, role_id: str
    ) -> GetOrganizationCameraRoleResponse:
        """Retrieve a single role.

        [API documentation: getOrganizationCameraRole](https://developer.cisco.com/meraki/api-v1/#!get-organization-camera-role)

        Args:
            organization_id: Organization ID.
            role_id: Role ID.

        Returns:
            Successful operation.

        Example API response:
            ```json
            {
              "name": "Security_Guard",
              "appliedOnDevices": [
                {
                  "tag": "reception-desk",
                  "id": "",
                  "permissionScopeId": "1",
                  "permissionScope": "camera-video",
                  "permissionLevel": "view_and_export"
                }
              ],
              "appliedOnNetworks": [
                {
                  "tag": "",
                  "id": "2568",
                  "permissionScopeId": "2",
                  "permissionScope": "camera-video",
                  "permissionLevel": "view"
                }
              ],
              "appliedOrgWide": [
                {
                  "tag": "building-a",
                  "permissionScopeId": "2",
                  "permissionScope": "camera_video",
                  "permissionLevel": "view_live"
                }
              ]
            }
            ```

        """
        organization_id = urllib.parse.quote(str(organization_id), safe="")
        role_id = urllib.parse.quote(str(role_id), safe="")
        path = f"/organizations/{organization_id}/camera/roles/{role_id}"

        return self._session.get(
            scope="camera",
            operation_id="getOrganizationCameraRole",
            path=path,
            response_schema=GetOrganizationCameraRoleResponse,
        )

    def update_organization_camera_role(
        self,
        *,
        organization_id: str,
        role_id: str,
        name: str | None = None,
        applied_on_devices: list[UpdateOrganizationCameraRoleAppliedOnDevicesItem] | None = None,
        applied_on_networks: list[UpdateOrganizationCameraRoleAppliedOnNetworksItem] | None = None,
        applied_org_wide: list[UpdateOrganizationCameraRoleAppliedOrgWideItem] | None = None,
    ) -> UpdateOrganizationCameraRoleResponse:
        """Update an existing role in this organization.

        [API documentation: updateOrganizationCameraRole](https://developer.cisco.com/meraki/api-v1/#!update-organization-camera-role)

        Args:
            organization_id: Organization ID.
            role_id: Role ID.
            name: The name of the new role. Must be unique.
            applied_on_devices: Device tag on which this specified permission is applied.
            applied_on_networks: Network tag on which this specified permission is applied.
            applied_org_wide: Permissions to be applied org wide.

        Returns:
            Successful operation.

        Example API response:
            ```json
            {
              "name": "Security_Guard",
              "appliedOnDevices": [
                {
                  "tag": "reception-desk",
                  "id": "",
                  "permissionScopeId": "1",
                  "permissionScope": "camera-video",
                  "permissionLevel": "view_and_export"
                }
              ],
              "appliedOnNetworks": [
                {
                  "tag": "",
                  "id": "2568",
                  "permissionScopeId": "2",
                  "permissionScope": "camera-video",
                  "permissionLevel": "view"
                }
              ],
              "appliedOrgWide": [
                {
                  "tag": "building-a",
                  "permissionScopeId": "2",
                  "permissionScope": "camera_video",
                  "permissionLevel": "view_live"
                }
              ]
            }
            ```

        """
        organization_id = urllib.parse.quote(str(organization_id), safe="")
        role_id = urllib.parse.quote(str(role_id), safe="")
        path = f"/organizations/{organization_id}/camera/roles/{role_id}"

        payload: dict[str, Any] = {}
        if name is not None:
            payload["name"] = name
        if applied_on_devices is not None:
            payload["appliedOnDevices"] = [
                item.model_dump(by_alias=True, exclude_none=True) for item in applied_on_devices
            ]
        if applied_on_networks is not None:
            payload["appliedOnNetworks"] = [
                item.model_dump(by_alias=True, exclude_none=True) for item in applied_on_networks
            ]
        if applied_org_wide is not None:
            payload["appliedOrgWide"] = [
                item.model_dump(by_alias=True, exclude_none=True) for item in applied_org_wide
            ]

        return self._session.put(
            scope="camera",
            operation_id="updateOrganizationCameraRole",
            path=path,
            json=payload,
            response_schema=UpdateOrganizationCameraRoleResponse,
        )

    def delete_organization_camera_role(self, *, organization_id: str, role_id: str) -> None:
        """Delete an existing role for this organization.

        [API documentation: deleteOrganizationCameraRole](https://developer.cisco.com/meraki/api-v1/#!delete-organization-camera-role)

        Args:
            organization_id: Organization ID.
            role_id: Role ID.

        Returns:
            Successful operation.

        """
        organization_id = urllib.parse.quote(str(organization_id), safe="")
        role_id = urllib.parse.quote(str(role_id), safe="")
        path = f"/organizations/{organization_id}/camera/roles/{role_id}"

        return self._session.delete(
            scope="camera", operation_id="deleteOrganizationCameraRole", path=path
        )
