Source code for wxc_sdk.telephony.virtual_extensions

from collections.abc import Generator
from typing import Optional

from pydantic import Field

from wxc_sdk.api_child import ApiChild
from wxc_sdk.base import ApiModel, enum_str
from wxc_sdk.base import SafeEnum as Enum

__all__ = [
    'VirtualExtensionsApi',
    'VirtualExtension',
    'VirtualExtensionMode',
    'VirtualExtensionLevel',
    'VirtualExtensionRange',
    'VirtualExtensionRangeAction',
    'ValidateVirtualExtensionStatus',
    'VirtualExtensionValidationStatus',
    'VirtualExtensionRangeValidationResult',
    'ValidateVirtualExtensionRange',
    'PhoneNumberStatus',
    'ValidatePhoneNumber',
]


[docs] class VirtualExtensionLevel(str, Enum): location = 'LOCATION' organization = 'ORGANIZATION'
[docs] class VirtualExtension(ApiModel): #: ID of the virtual extension. id: Optional[str] = None #: Extension of the virtual extension. extension: Optional[str] = None #: Routing prefix of the virtual extension's location. routing_prefix: Optional[str] = None #: ESN of the virtual extension. esn: Optional[str] = None #: Directory number of the virtual extension. phone_number: Optional[str] = None #: First name of the person at the virtual extension. first_name: Optional[str] = None #: Last name of the person at the virtual extension. last_name: Optional[str] = None #: Level of the virtual extension. It can be either `ORGANIZATION` or `LOCATION`. level: Optional[VirtualExtensionLevel] = None #: ID of the location to which the virtual extension is assigned. The location ID is a unique identifier for the #: location in Webex Calling. location_id: Optional[str] = None #: Name of the location to which the virtual extension is assigned. location_name: Optional[str] = None #: Display name of the person at the virtual extension. display_name: Optional[str] = None
[docs] class VirtualExtensionMode(str, Enum): standard = 'STANDARD' enhanced = 'ENHANCED'
[docs] class VirtualExtensionRange(ApiModel): #: ID of the virtual extension range. id: Optional[str] = None #: Name of the virtual extension range. This is a unique name for the virtual extension range. name: Optional[str] = None #: Prefix used for a virtual extension range. Prefix works in Standard and Enhanced modes. In Standard mode, it #: must be E.164 and it must be unique. In Enhanced mode, it can be E.164 or non-E.164. prefix: Optional[str] = None #: Level of the virtual extension range. It can be either `ORGANIZATION` or `LOCATION`. level: Optional[VirtualExtensionLevel] = None #: List of virtual extension patterns. The maximum number of patterns supported at a time is 100. Extension #: patterns can include one or more right-justified wildcards “X” matching any digit. patterns: Optional[list[str]] = None #: ID of the location to which the virtual extension range is assigned. This is set only for virtual extension #: ranges at the location level. location_id: Optional[str] = None #: Name of the location to which the virtual extension range is assigned. This is set only for virtual extension #: ranges at the location level location_name: Optional[str] = None
[docs] class VirtualExtensionRangeAction(str, Enum): #: Add new patterns to the existing virtual extension range. add = 'ADD' #: Remove existing patterns from the virtual extension range. remove = 'REMOVE' #: Replace existing patterns with new patterns in the virtual extension range. replace = 'REPLACE'
[docs] class ValidateVirtualExtensionStatus(str, Enum): #: Validation is successful. ok = 'OK' #: Validation failed. errors = 'ERRORS'
[docs] class VirtualExtensionValidationStatus(str, Enum): #: Validation is successful. valid = 'VALID' #: Duplicate patterns for virtual extension range. duplicate = 'DUPLICATE' #: Duplicate routing number in the pattern list. duplicate_in_list = 'DUPLICATE_IN_LIST' #: Invalid prefix length. invalid = 'INVALID' #: Exceeding pattern limit of 100 in the request. limit_exceeded = 'LIMIT_EXCEEDED'
[docs] class VirtualExtensionRangeValidationResult(ApiModel): #: Name used for virtual extension range validation. name: Optional[str] = None #: Prefix used for a virtual extension range validation. prefix: Optional[str] = None #: Pattern used for a virtual extension range validation. pattern: Optional[str] = None #: Error code for the virtual extension range validation. error_code: Optional[int] = None #: Error message for the virtual extension range validation. message: Optional[str] = None #: Virtual extension range validation status. status: Optional[VirtualExtensionValidationStatus] = None
[docs] class ValidateVirtualExtensionRange(ApiModel): #: Virtual extension range validation status. status: Optional[ValidateVirtualExtensionStatus] = None #: Array of virtual extension range validation status. This is set only when the `status` is `ERRORS`. validation_status: Optional[list[VirtualExtensionRangeValidationResult]] = Field( alias='virtualExtensionRangeValidationStatus', default=None )
[docs] class PhoneNumberStatus(ApiModel): phone_number: Optional[str] = None state: Optional[VirtualExtensionValidationStatus] = None error_code: Optional[int] = None message: Optional[str] = None
[docs] class ValidatePhoneNumber(ApiModel): status: Optional[ValidateVirtualExtensionStatus] = None phone_number_status: Optional[list[PhoneNumberStatus]] = Field(default_factory=list)
[docs] class VirtualExtensionsApi(ApiChild, base='telephony/config'): """ Features: Virtual Extensions Features: Virtual Extensions allow assigning extensions to frequently called external numbers for simplified dialing within Webex Calling. Viewing these read-only organization settings requires a full or read-only administrator auth token with a scope of `spark-admin:telephony_config_read`. Modifying these organization settings requires a full administrator auth token with a scope of `spark-admin:telephony_config_write`. A partner administrator can retrieve or change settings in a customer's organization using the optional `orgId` query parameter. """
[docs] def list_range( self, order: str = None, name: str = None, prefix: str = None, location_id: str = None, org_level_only: bool = None, org_id: str = None, **params, ) -> Generator[VirtualExtensionRange, None, None]: """ Get a list of a Virtual Extension Range Retrieves the list of Virtual Extension Ranges. Virtual extension ranges integrate remote workers on a separate telephony system into Webex Calling and enable extension dialing. Using these ranges, you can define patterns that can be used to route calls at a location level or an organization level. You are allowed to define virtual extensions ranges in addition to individual virtual extensions. This works in both Standard and Enhanced modes Retrieving a virtual extension range requires a full or read-only administrator auth token with a scope of `spark-admin:telephony_config_read`. :param order: Sort the list of virtual extension ranges by name or prefix, either ASC or DSC. Default sort order is ASC. :type order: str :param name: Filter the list of virtual extension ranges by name. :type name: str :param prefix: Filter the list of virtual extension ranges by prefix. :type prefix: str :param location_id: Filter the list of virtual extension ranges by location ID. Only one of the `locationId` and `OrgLevelOnly` query parameters is allowed at the same time. :type location_id: str :param org_level_only: Filter the list of virtual extension ranges by organization level. If `orgLevelOnly` is true, return only the organization level virtual extension ranges. :type org_level_only: bool :param org_id: Unique identifier for the organization. :type org_id: str :return: Generator yielding :class:`GetVirtualExtensionRangeListObject` instances """ if org_id is not None: params['orgId'] = org_id if order is not None: params['order'] = order if name is not None: params['name'] = name if prefix is not None: params['prefix'] = prefix if location_id is not None: params['locationId'] = location_id if org_level_only is not None: params['orgLevelOnly'] = str(org_level_only).lower() url = self.ep('virtualExtensionRanges') return self.session.follow_pagination( url=url, model=VirtualExtensionRange, item_key='virtualExtensionRanges', params=params )
[docs] def create_range( self, name: str, prefix: str, patterns: list[str] = None, location_id: str = None, org_id: str = None ) -> str: """ Create a Virtual Extension Range Create a new Virtual Extension Range for the given organization or location. Virtual extension ranges integrate remote workers on a separate telephony system into Webex Calling and enable extension dialing. Using these ranges, you can define patterns that can be used to route calls at a location level or an organization level. You are allowed to define virtual extensions ranges in addition to individual virtual extensions. This works in both Standard and Enhanced modes Virtual extension range can be set up at the organization or location level. Creating a virtual extension range requires a full administrator or location administrator auth token with a scope of `spark-admin:telephony_config_write`. :param name: Name of the virtual extension range. This is a unique name for the virtual extension range. :type name: str :param prefix: Prefix used for a virtual extension range. Prefix works in Standard and Enhanced modes. In Standard mode, it must be E.164 and unique. In Enhanced mode, it can be E.164 or non-E.164. :type prefix: str :param patterns: List of virtual extension patterns. You can add up to 100 patterns at a time. Extension patterns can include one or more right-justified wildcards “X” matching any digit. :type patterns: list[str] :param location_id: ID of the location to which the virtual extension range is assigned. The location ID is a unique identifier for the location in Webex Calling. This is set only when location level virtual extension range is added. :type location_id: str :param org_id: Unique identifier for the organization. :type org_id: str :rtype: str """ params = {} if org_id is not None: params['orgId'] = org_id body = dict() body['name'] = name body['prefix'] = prefix if patterns is not None: body['patterns'] = patterns if location_id is not None: body['locationId'] = location_id url = self.ep('virtualExtensionRanges') data = super().post(url, params=params, json=body) r = data['id'] return r
[docs] def validate_range( self, location_id: str = None, name: str = None, prefix: str = None, patterns: list[str] = None, range_id: str = None, org_id: str = None, ) -> ValidateVirtualExtensionRange: """ Validate the prefix and extension pattern for a Virtual Extension Range. Virtual extension ranges integrate remote workers on a separate telephony system into Webex Calling and enable extension dialing. Using these ranges, you can define patterns that can be used to route calls at a location level or an organization level. You are allowed to define virtual extensions ranges in addition to individual virtual extensions. This works in both Standard and Enhanced modes Validating a prefix and extension pattern for a Virtual Extension Range requires a full administrator or location administrator auth token with a scope of `spark-admin:telephony_config_write`. :param location_id: ID of the location to which the virtual extension range is assigned. The location ID is a unique identifier for the location in Webex Calling. :type location_id: str :param name: Name of the virtual extension range. This is a unique name for the virtual extension range. :type name: str :param prefix: Prefix used for a virtual extension range. :type prefix: str :param patterns: List of virtual extension patterns. The maximum number of patterns supported at a time is 100. :type patterns: list[str] :param range_id: ID of the virtual extension range. This is mandatory when validating for an existing virtual extension range, not present when validating a new virtual extension range before adding it. :type range_id: str :param org_id: Unique identifier for the organization. :type org_id: str :rtype: :class:`ValidateVirtualExtensionRange` """ params = {} if org_id is not None: params['orgId'] = org_id body = dict() if location_id is not None: body['locationId'] = location_id if name is not None: body['name'] = name if prefix is not None: body['prefix'] = prefix if patterns is not None: body['patterns'] = patterns if range_id is not None: body['rangeId'] = range_id url = self.ep('virtualExtensionRanges/actions/validate/invoke') data = super().post(url, params=params, json=body) r = ValidateVirtualExtensionRange.model_validate(data) return r
[docs] def delete_range(self, extension_range_id: str, org_id: str = None): """ Delete a Virtual Extension Range Delete a virtual extension range for the given extension range ID. Virtual extension ranges integrate remote workers on a separate telephony system into Webex Calling and enable extension dialing. Using these ranges, you can define patterns that can be used to route calls at a location level or an organization level. You are allowed to define virtual extensions ranges in addition to individual virtual extensions. This works in both Standard and Enhanced modes Deleting a virtual extension range requires a full administrator or location administrator auth token with a scope of `spark-admin:telephony_config_write`. :param extension_range_id: ID of the virtual extension range. :type extension_range_id: str :param org_id: Unique identifier for the organization. :type org_id: str :rtype: None """ params = {} if org_id is not None: params['orgId'] = org_id url = self.ep(f'virtualExtensionRanges/{extension_range_id}') super().delete(url, params=params)
[docs] def details_range(self, extension_range_id: str, org_id: str = None) -> VirtualExtensionRange: """ Get details of a Virtual Extension Range Retrieve virtual extension range details for the given extension range ID. Virtual extension ranges integrate remote workers on a separate telephony system into Webex Calling and enable extension dialing. Using these ranges, you can define patterns that can be used to route calls at a location level or an organization level. You are allowed to define virtual extensions ranges in addition to individual virtual extensions. This works in both Standard and Enhanced modes Retrieving a virtual extension range requires a full or read-only administrator auth token with a scope of `spark-admin:telephony_config_read`. :param extension_range_id: ID of the virtual extension range. :type extension_range_id: str :param org_id: Unique identifier for the organization. :type org_id: str :rtype: :class:`VirtualExtensionRange` """ params = {} if org_id is not None: params['orgId'] = org_id url = self.ep(f'virtualExtensionRanges/{extension_range_id}') data = super().get(url, params=params) r = VirtualExtensionRange.model_validate(data) return r
[docs] def modify_range( self, extension_range_id: str, name: str = None, prefix: str = None, patterns: list[str] = None, action: VirtualExtensionRangeAction = None, org_id: str = None, ): """ Modify Virtual Extension Range Modify virtual extension range for the given extension range ID. Virtual extension ranges integrate remote workers on a separate telephony system into Webex Calling and enable extension dialing. Using these ranges, you can define patterns that can be used to route calls at a location level or an organization level. You are allowed to define virtual extensions ranges in addition to individual virtual extensions. This works in both Standard and Enhanced modes Modifying a virtual extension range requires a full administrator or location administrator auth token with a scope of `spark-admin:telephony_config_write`. :param extension_range_id: ID of the virtual extension range. :type extension_range_id: str :param name: Name of the virtual extension range. This is a unique name for the virtual extension range. :type name: str :param prefix: Prefix used for a virtual extension range. :type prefix: str :param patterns: The pattern to be added, replaced, or removed from a virtual extension range. The maximum number of patterns supported at a time is 100. :type patterns: list[str] :param action: Action to be performed on the virtual extension range. It can be either `ADD`, `REMOVE` or `REPLACE`. This is mandatory when `patterns` are provided. :type action: VirtualExtensionRangeAction :param org_id: Unique identifier for the organization. :type org_id: str :rtype: None """ params = {} if org_id is not None: params['orgId'] = org_id body = dict() if name is not None: body['name'] = name if prefix is not None: body['prefix'] = prefix if patterns is not None: body['patterns'] = patterns if action is not None: body['action'] = enum_str(action) url = self.ep(f'virtualExtensionRanges/{extension_range_id}') super().put(url, params=params, json=body)
[docs] def list_extensions( self, order: str = None, extension: str = None, phone_number: str = None, name: str = None, location_name: str = None, location_id: str = None, org_level_only: bool = None, org_id: str = None, **params, ) -> Generator[VirtualExtension, None, None]: """ Read the List of Virtual Extensions Retrieve virtual extensions associated with a specific customer. The GET Virtual Extensions API allows administrators to retrieve a list of virtual extensions configured within their organization. Virtual extensions enable users to dial extension numbers that route to external phone numbers, such as those of remote workers or frequently contacted clients. This API returns key information including the extension, associated phone number (in E.164 format), display name, and the location to which the virtual extension belongs The API supports filtering by various parameters, such as extension number, phone number, and location name. The results can be paginated using the `max` and `start` parameters, and the order of the results can be specified using the `order` parameter. Retrieving a Virtual Extension requires a full or read-only administrator auth token with a scope of `spark-admin:telephony_config_read`. :param order: Order the list of virtual extensions in ascending or descending order. Default is ascending. :type order: str :param extension: Filter the list of virtual extensions by extension number. :type extension: str :param phone_number: Filter the list of virtual extensions by phone number. :type phone_number: str :param name: Filter the list of virtual extensions by name. This can be either first name or last name. :type name: str :param location_name: Filter the list of virtual extensions by location name.(Only one of the locationName, locationId, and OrgLevelOnly query parameters is allowed at the same time.) :type location_name: str :param location_id: Filter the list of virtual extensions by location ID. :type location_id: str :param org_level_only: Filter the list of virtual extensions by organization level. If orgLevelOnly is true, return only the organization level virtual extensions. :type org_level_only: bool :param org_id: Unique identifier for the organization. :type org_id: str :return: Generator yielding :class:`GetVirtualExtensionObject` instances """ if org_id is not None: params['orgId'] = org_id if order is not None: params['order'] = order if extension is not None: params['extension'] = extension if phone_number is not None: params['phoneNumber'] = phone_number if name is not None: params['name'] = name if location_name is not None: params['locationName'] = location_name if location_id is not None: params['locationId'] = location_id if org_level_only is not None: params['orgLevelOnly'] = str(org_level_only).lower() url = self.ep('virtualExtensions') return self.session.follow_pagination( url=url, model=VirtualExtension, item_key='virtualExtensions', params=params )
[docs] def create_extension( self, display_name: str, phone_number: str, extension: str, first_name: str = None, last_name: str = None, location_id: str = None, org_id: str = None, ) -> str: """ Create a Virtual Extension Create new Virtual Extension for the given organization or location. You can set up virtual extensions at the organization or location level. The organization level enables everyone across your organization to dial the same extension number to reach someone. You can use the location level virtual extension like any other extension assigned to the specific location. Users at the specific location can dial the extension. However, users at other locations can reach the virtual extension by dialing the ESN. Creating a virtual extension requires a full administrator or location administrator auth token with a scope of `spark-admin:telephony_config_write` and `identity:contacts_rw`. :param display_name: Display name of the person at the virtual extension. :type display_name: str :param phone_number: Directory number of the virtual extension. :type phone_number: str :param extension: Extension of the virtual extension. :type extension: str :param first_name: First name of the person at the virtual extension. :type first_name: str :param last_name: Last name of the person at the virtual extension. :type last_name: str :param location_id: ID of the location to which the virtual extension is assigned. The location ID is a unique identifier for the location in Webex Calling. :type location_id: str :param org_id: Unique identifier for the organization. :type org_id: str :rtype: str """ params = {} if org_id is not None: params['orgId'] = org_id body = dict() if first_name is not None: body['firstName'] = first_name if last_name is not None: body['lastName'] = last_name body['displayName'] = display_name body['phoneNumber'] = phone_number body['extension'] = extension if location_id is not None: body['locationId'] = location_id url = self.ep('virtualExtensions') data = super().post(url, params=params, json=body) r = data['id'] return r
[docs] def validate_external_phone_number(self, phone_numbers: list[str], org_id: str = None) -> ValidatePhoneNumber: """ Validate an external phone number Validate external phone number for the given organization. This API is designed to validate external phone numbers before they are assigned as virtual extensions for a customer. It ensures that the provided numbers are properly formatted, eligible for use, and not already in use within the system. This validation is typically part of a pre-check process during provisioning or number assignment workflows, helping administrators or systems prevent conflicts or errors related to number reuse or format issues. Creating a virtual extension requires a full administrator or location administrator auth token with a scope of `spark-admin:telephony_config_write`. :param phone_numbers: List of external phone numbers to be validated. :type phone_numbers: list[str] :param org_id: Unique identifier for the organization. :type org_id: str :rtype: ValidatePhoneNumber """ params = {} if org_id is not None: params['orgId'] = org_id body = dict() body['phoneNumbers'] = phone_numbers url = self.ep('virtualExtensions/actions/validateNumbers/invoke') data = super().post(url, params=params, json=body) r = ValidatePhoneNumber.model_validate(data) return r
[docs] def get_extension_settings(self, org_id: str = None) -> VirtualExtensionMode: """ Get Virtual extension settings Retrieve Virtual Extension settings for the given Org. This API retrieves the virtual extension mode settings configured for a given organization. Virtual extensions can operate in two modes: STANDARD and ENHANCED. The selected mode determines how the system handles routing and signaling for virtual extensions. By default, the virtual extensions that you create use the Standard mode. Another mode, enhanced signaling mode, is available to all customers, however, virtual extensions won't function properly in this mode unless your PSTN provider supports special network signaling extensions and there aren't many PSTN providers that do. Retrieving a Virtual Extension settings requires a full or read-only administrator auth token with a scope of `spark-admin:telephony_config_read`. :param org_id: Unique identifier for the organization. :type org_id: str :rtype: VirtualExtensionMode """ params = {} if org_id is not None: params['orgId'] = org_id url = self.ep('virtualExtensions/settings') data = super().get(url, params=params) r = VirtualExtensionMode.model_validate(data['mode']) return r
[docs] def modify_extension_settings(self, mode: VirtualExtensionMode, org_id: str = None): """ Modify Virtual Extension Settings Update Virtual Extension details for the given extension ID. This endpoint updates the virtual extension settings for an organization. It is primarily used to configure the operating mode for virtual extensions. Modes determine how virtual extensions are assigned or managed within the system. Updating a Virtual Extension requires a full administrator or location administrator auth token with a scope of `spark-admin:telephony_config_write`. :param mode: Mode of the virtual extension. It can be either `STANDARD` or `ENHANCED`. + `STANDARD` - Standard Virtual extension mode in which virtual extensions must be associated with a valid E.164 number, but this requires no enhanced signaling support from the PSTN provider. + `ENHANCED` - Enhanced signaling mode: only a few PSTN providers support this special network signaling extension. :type mode: VirtualExtensionMode :param org_id: Unique identifier for the organization. :type org_id: str :rtype: None """ params = {} if org_id is not None: params['orgId'] = org_id body = dict() body['mode'] = enum_str(mode) url = self.ep('virtualExtensions/settings') super().put(url, params=params, json=body)
[docs] def delete_extension(self, extension_id: str, org_id: str = None): """ Delete a Virtual Extension Delete Virtual Extension using the extension ID. This API permanently deletes a virtual extension from the organization. Once deleted, the extension will no longer route calls to the external phone number, and users won’t be able to reach it via the assigned extension. Deleting a Virtual Extension requires a full administrator or location administrator auth token with a scope of `spark-admin:telephony_config_write` and `identity:contacts_rw`. :param extension_id: ID of the virtual extension. :type extension_id: str :param org_id: Unique identifier for the organization. :type org_id: str :rtype: None """ params = {} if org_id is not None: params['orgId'] = org_id url = self.ep(f'virtualExtensions/{extension_id}') super().delete(url, params=params)
[docs] def details_extension(self, extension_id: str, org_id: str = None) -> VirtualExtension: """ Get a Virtual Extension Retrieve Virtual Extension details for the given extension ID. Virtual extensions integrate remote workers on separate telephony systems into Webex Calling, enabling users to reach them via extension dialing. This endpoint allows administrators to retrieve configuration details for a specific virtual extension, ensuring visibility into the mapping between extensions and external phone numbers. Retrieving a Virtual Extension requires a full or read-only administrator auth token with a scope of `spark-admin:telephony_config_read`. :param extension_id: ID of the virtual extension. :type extension_id: str :param org_id: Unique identifier for the organization. :type org_id: str :rtype: :class:`VirtualExtension` """ params = {} if org_id is not None: params['orgId'] = org_id url = self.ep(f'virtualExtensions/{extension_id}') data = super().get(url, params=params) r = VirtualExtension.model_validate(data) return r
[docs] def update_extension( self, extension_id: str, first_name: str = None, last_name: str = None, display_name: str = None, phone_number: str = None, extension: str = None, org_id: str = None, ): """ Update a Virtual Extension Update Virtual Extension details for the given extension ID. This API updates the configuration of an existing virtual extension identified by its unique extension ID. Administrators can modify fields such as the extension, associated phone number (in E.164 format), display name, and location etc. Updating a Virtual Extension requires a full administrator or location administrator auth token with a scope of `spark-admin:telephony_config_write` and `identity:contacts_rw`. :param extension_id: ID of the virtual extension. :type extension_id: str :param first_name: First name of the person at the virtual extension. :type first_name: str :param last_name: Last name of the person at the virtual extension. :type last_name: str :param display_name: Display name of the person at the virtual extension. :type display_name: str :param phone_number: Directory number of the virtual extension. :type phone_number: str :param extension: Extension of the virtual extension. :type extension: str :param org_id: Unique identifier for the organization. :type org_id: str :rtype: None """ params = {} if org_id is not None: params['orgId'] = org_id body = dict() if first_name is not None: body['firstName'] = first_name if last_name is not None: body['lastName'] = last_name if display_name is not None: body['displayName'] = display_name if phone_number is not None: body['phoneNumber'] = phone_number if extension is not None: body['extension'] = extension url = self.ep(f'virtualExtensions/{extension_id}') super().put(url, params=params, json=body)