import builtins
import mimetypes
import os
from collections.abc import Generator
from datetime import datetime
from typing import Any, Optional
from pydantic import Field, TypeAdapter
from requests_toolbelt import MultipartEncoder
from wxc_sdk.api_child import ApiChild
from wxc_sdk.base import ApiModel
from wxc_sdk.base import SafeEnum as Enum
from wxc_sdk.common import AlternateNumber, AnnAudioFile, DirectLineCallerIdNameSelection, Greeting, IdAndName
from wxc_sdk.person_settings.available_numbers import AvailableNumber
__all__ = [
'AIReceptionistApi',
'AiAgent',
'AiEngine',
'AiEngineName',
'AiReceptionist',
'AIRIntent',
'AIRTemplate',
'DefaultAction',
'AIRDirectLineCallerIdName',
'IntentTransferTo',
'TransferToContactType',
'TransferTo',
'KnowledgeBaseDocument',
'KnowledgeBaseDocumentDetails',
'KnowledgeBaseDocumentKnowledgeType',
'KnowledgeBaseDocumentStatus',
'KnowledgeBaseMappedBot',
'KnowledgeBase',
'MessageMetadata',
'MessageText',
'AIRSessionsMeta',
'SessionObject',
'AIRSessionState',
'AIRSessions',
'ToolInvocation',
'TranscriptObject',
'TranscriptObjectUserType',
'TranscriptsResponse',
'AiGuidelines',
'AiVoice',
'DefaultActionType',
'Voice',
'VoiceGender',
]
[docs]
class DefaultActionType(str, Enum):
play_message_and_disconnect = 'PLAY_MESSAGE_AND_DISCONNECT'
transfer_to_operator = 'TRANSFER_TO_OPERATOR'
[docs]
class TransferTo(ApiModel):
#: Contact type.
#: - PEOPLE - A person in the organization.
#: - RESOURCE_GROUP - A group resource such as a call queue or hunt group.
#: - CONTACT - An organization contact.
#: - PHONE_NUMBER - A raw phone number or extension.
contact_type: Optional[TransferToContactType] = None
#: Unique identifier for the transfer destination, encoded using the resource type indicated by contactType
#: (PEOPLE, RESOURCE_GROUP, or CONTACT). Not required when contactType is PHONE_NUMBER.
contact_id: Optional[str] = None
#: Phone number for intent transfer.
phone_number: Optional[str] = None
[docs]
class DefaultAction(ApiModel):
#: Default action to be performed when a call is received:
#:
#: - `PLAY_MESSAGE_AND_DISCONNECT` - Play an audio message and disconnect the call.
#: - `TRANSFER_TO_OPERATOR` - Transfer the call to an operator.
action_type: Optional[DefaultActionType] = None
#: Announcement type to be played. Mandatory if actionType is `PLAY_MESSAGE_AND_DISCONNECT`:
#:
#: - `DEFAULT` - Use the system default audio message.
#: - `CUSTOM` - Use a custom uploaded audio file.
audio_message_selection: Optional[Greeting] = None
#: Audio file details. Mandatory if audioMessageSelection is CUSTOM.
audio_file: Optional[AnnAudioFile] = None
#: Transfer to number. Mandatory if actionType is `TRANSFER_TO_OPERATOR`.
transfer_to_number: Optional[str] = None
#: Transfer target configuration. Alternative to transferToNumber
transfer_to: Optional[TransferTo] = None
def update(self) -> dict[str, Any]:
"""
data for update
:meta private:
:return:
"""
data = self.model_dump(mode='json', by_alias=True, exclude={'audio_file': True})
if self.audio_file:
data['audio_file_id'] = self.audio_file.id
return data
[docs]
class AIRDirectLineCallerIdName(ApiModel):
#: Field to indicate the option chosen to represent the Caller ID:
#:
#: - `DISPLAY_NAME` - Use the AI Receptionist display name as the caller ID.
#: - `CUSTOM_NAME` - Use a custom name as the caller ID.
direct_line_caller_id_name_selection: Optional[DirectLineCallerIdNameSelection] = None
#: Carries the customized name when "CUSTOM_NAME" is the chosen option. It can be empty if it's not configured.
custom_name: Optional[str] = None
[docs]
class AiEngineName(str, Enum):
pro = 'PRO'
pro_us = 'PRO_US'
[docs]
class AiVoice(ApiModel):
#: AI engine name.
#:
#: - `PRO` — Available in all supported countries.
#: - `PRO_US` — Available in the United States only.
ai_engine: Optional[AiEngineName] = None
#: Display name of the AI Receptionist voice.
display_name: Optional[str] = None
#: Voice language name
language: Optional[str] = None
#: Voice language locale in BCP 47 format
language_code: Optional[str] = None
[docs]
class AiGuidelines(ApiModel):
#: Goal of the AI Receptionist. The combined length of `goal` and `guideline` must not exceed 5096 characters.
goal: Optional[str] = None
#: Welcome message to be played before the call handling.
welcome_message: Optional[str] = None
#: Guidelines to AI Receptionist to follow. This includes information like Identity, role definition, context,
#: behavior etc.. The combined length of `goal` and `guideline` must not exceed 5096 characters.
guideline: Optional[str] = None
[docs]
class AiAgent(ApiModel):
#: AI Agent ID from Webex AI Agent Studio
agent_id: Optional[str] = None
#: Voice configuration for the AI Agent
voice: Optional[AiVoice] = None
#: Unique identifier for the Knowledge Base used by the AI Agent to answer caller queries.
knowledge_base_id: Optional[str] = None
#: AI Agent guidelines
guidelines: Optional[AiGuidelines] = None
def update(self) -> dict[str, Any]:
"""
data for update
:meta private:
:return:
"""
data = self.model_dump(mode='json', by_alias=True, exclude={'agent_id': True})
return data
[docs]
class AiReceptionist(ApiModel):
#: Unique identifier for the AI receptionist.
id: Optional[str] = None
#: Name of the AI receptionist. Must be unique within a location.
name: Optional[str] = None
#: Phone number of the AI receptionist in E.164 format.
phone_number: Optional[str] = None
#: Extension of the AI Receptionist.
extension: Optional[str] = None
#: Routing prefix of location.
routing_prefix: Optional[str] = None
#: Routing prefix + extension of the AI Receptionist. If the location has no routing prefix, this will only be the
#: extension. If the AI Receptionist has no extension, this field will not be present.
esn: Optional[str] = None
#: Location of the AI Receptionist.
location: Optional[IdAndName] = None
#: Flag to indicate AI receptionist is enabled or not. When disabled, incoming calls to this AI receptionist will
#: not be answered.
enabled: Optional[bool] = None
#: List of alternate phone numbers assigned to the AI Receptionist.
alternate_numbers: Optional[list[AlternateNumber]] = None
#: Direct line caller ID name configuration
direct_line_caller_id_name: Optional[AIRDirectLineCallerIdName] = None
#: A dial by name used for AI Receptionist name dialing. Characters of `%`, `+`, `\`, `"` and Unicode characters
#: are not allowed.
dial_by_name: Optional[str] = None
#: Default action configuration for the AI Receptionist
default_action: Optional[DefaultAction] = None
#: AI Agent configuration
ai_agent: Optional[AiAgent] = None
#: Number of intents configured for this AI Receptionist
intent_count: Optional[int] = None
def update(self) -> dict[str, Any]:
"""
data for update
:meta private:
"""
data = self.model_dump(
mode='json',
by_alias=True,
exclude_unset=True,
exclude={
'id': True,
'routing_prefix': True,
'esn': True,
'location': True,
'alternate_numbers': {'__all__': {'toll_free_number': True}},
'default_action': {'audio_file': True},
'ai_agent': {'agent_id': True},
},
)
if self.default_action and self.default_action.audio_file:
data['default_action']['audio_file_id'] = self.default_action.audio_file.id
return data
[docs]
class AIRTemplate(ApiModel):
#: Unique identifier for the AI receptionist template.
id: Optional[str] = None
#: Name of the AI Receptionist template.
name: Optional[str] = None
#: Goal of the AI Receptionist.
goal: Optional[str] = None
#: Welcome message to be played before the call handling.
welcome_message: Optional[str] = None
#: Guidelines for the AI receptionist to follow. This includes information like identity, role definition, context,
#: behavior, etc.
guideline: Optional[str] = None
[docs]
class IntentTransferTo(ApiModel):
#: Type of transfer destination.
#: - PEOPLE - A person in the organization.
#: - RESOURCE_GROUP - A group resource such as a call queue or hunt group.
#: - CONTACT - An organization contact.
#: - PHONE_NUMBER - A raw phone number or extension.
contact_type: Optional[TransferToContactType] = None
#: Unique identifier for the transfer destination, encoded using the resource type indicated by contactType
#: (PEOPLE, RESOURCE_GROUP, or CONTACT). Not required when contactType is PHONE_NUMBER.
contact_id: Optional[str] = None
#: Name of the calling service or contact.
name: Optional[str] = None
#: Phone number of calling service or contact.
phone_number: Optional[str] = None
[docs]
class AIRIntent(ApiModel):
#: Unique identifier of the intent.
id: Optional[str] = None
#: Name of the intent.
name: Optional[str] = None
#: Description of the intent (Action).
description: Optional[str] = None
#: Transfer destination for the intent.
transfer_to: Optional[IntentTransferTo] = None
def update(self) -> dict[str, Any]:
""" "
data for update
:meta private:
"""
data = self.model_dump(mode='json', by_alias=True, exclude={'id': True})
return data
[docs]
class VoiceGender(str, Enum):
male = 'MALE'
female = 'FEMALE'
[docs]
class Voice(ApiModel):
#: Voice language.
language: Optional[str] = None
#: Voice locale code.
language_code: Optional[str] = None
#: Voice display name.
display_name: Optional[str] = None
#: Field to indicate default voice.
is_default: Optional[bool] = None
#: Voice gender.
#: - MALE — Male voice.
#: - FEMALE — Female voice.
gender: Optional[VoiceGender] = None
[docs]
class AiEngine(ApiModel):
#: AI engine name.
#: - PRO — Available in all supported countries.
#: - PRO_US — Available in the United States only.
name: Optional[AiEngineName] = None
#: List of available voices for this AI engine.
voices: Optional[list[Voice]] = None
[docs]
class KnowledgeBaseMappedBot(ApiModel):
#: Unique identifier for the AI Receptionist.
id: Optional[str] = None
#: Timestamp indicating when the Knowledge Base was associated with the AI Receptionist, in ISO 8601 format.
connected_at: Optional[datetime] = None
#: Unique identifier for the AI agent associated with this receptionist.
agent_id: Optional[str] = None
#: Name of the AI Receptionist (Bot).
name: Optional[str] = None
[docs]
class KnowledgeBase(ApiModel):
#: Unique identifier of the Knowledge Base.
id: Optional[str] = None
#: The display name assigned to the Knowledge Base. Used to identify the KB across the platform.
name: Optional[str] = None
#: A human-readable description providing additional context about the purpose or contents of the Knowledge Base.
description: Optional[str] = None
#: The total count of documents that have been uploaded or indexed into the Knowledge Base.
documents_count: Optional[int] = None
#: The total count of files that have been uploaded to the Knowledge Base.
files_count: Optional[int] = None
#: The cumulative size (in bytes) of all files stored in the Knowledge Base.
files_size: Optional[int] = None
#: Timestamp indicating when the Knowledge Base was originally created, in ISO 8601 format.
created_at: Optional[datetime] = None
#: Timestamp indicating when the Knowledge Base was last modified, in ISO 8601 format.
updated_at: Optional[datetime] = None
#: List of AI Receptionists that are currently associated with this Knowledge Base.
mapped_bots: Optional[list[KnowledgeBaseMappedBot]] = None
[docs]
class KnowledgeBaseDocument(ApiModel):
#: Unique identifier of the knowledge base document.
id: Optional[str] = None
#: Name or filename of the knowledge base document.
name: Optional[str] = None
#: Relevance score of the document.
score: Optional[int] = None
#: Extracted text content from the document.
text: Optional[str] = None
[docs]
class KnowledgeBaseDocumentKnowledgeType(str, Enum):
article = 'ARTICLE'
file = 'FILE'
[docs]
class KnowledgeBaseDocumentStatus(str, Enum):
pending = 'pending'
processing = 'processing'
success = 'success'
failed = 'failed'
[docs]
class KnowledgeBaseDocumentDetails(ApiModel):
#: Unique identifier for the document.
id: Optional[str] = None
#: Unique identifier for the Knowledge Base this document belongs to.
knowledge_base_id: Optional[str] = None
#: Name of the document.
name: Optional[str] = None
#: Content of the document.
content: Optional[str] = None
#: Description of the document.
description: Optional[str] = None
#: Original file name if the document was uploaded as a file.
file_name: Optional[str] = None
#: Size of the document in bytes.
file_size: Optional[int] = None
#: Type of knowledge content.
#: - `article` - Text-based content created directly via API.
#: - `file` - Content uploaded as a document file.
knowledge_type: Optional[KnowledgeBaseDocumentKnowledgeType] = None
#: Processing status of the document.
#: - `pending` - Document is waiting to be processed.
#: - `processing` - Document is currently being indexed.
#: - `success` - Document has been successfully indexed and is available for queries.
#: - `failed` - Document processing failed.
status: Optional[KnowledgeBaseDocumentStatus] = None
#: Timestamp indicating when the document was created, in ISO 8601 format.
created_at: Optional[datetime] = None
#: Timestamp indicating when the document was last modified, in ISO 8601 format.
updated_at: Optional[datetime] = None
[docs]
class AIRSessionState(str, Enum):
open = 'open'
closed = 'closed'
[docs]
class SessionObject(ApiModel):
#: Unique session identifier. Use as `sessionId` in the transcripts API.
id: Optional[str] = None
#: Unique call identifier (This is same as call correlation ID in Control Hub troubleshooting).
interaction_id: Optional[str] = Field(alias='interaction_id', default=None)
#: State of the session.
state: Optional[AIRSessionState] = None
#: Creation timestamp in epoch milliseconds.
created_at: Optional[int] = Field(alias='created_at', default=None)
#: Last-updated timestamp in epoch milliseconds.
updated_at: Optional[int] = Field(alias='updated_at', default=None)
#: Indicates a test invocation. Always `false` for AI Receptionist.
is_test: Optional[bool] = Field(alias='is_test', default=None)
[docs]
class AIRSessions(ApiModel):
#: Pagination metadata for the response.
meta: Optional[AIRSessionsMeta] = None
#: List of session objects.
objects: Optional[list[SessionObject]] = None
#: Unique identifier for this API transaction.
transaction_id: Optional[str] = Field(alias='transaction_id', default=None)
[docs]
class MessageText(ApiModel):
#: Utterance text.
text: Optional[str] = None
[docs]
class TranscriptObjectUserType(str, Enum):
human = 'human'
bot = 'bot'
[docs]
class TranscriptObject(ApiModel):
#: Unique identifier of the transcript message.
id: Optional[str] = None
#: Transaction identifier grouping related messages.
transaction_id: Optional[str] = Field(alias='transaction_id', default=None)
#: Indicates whether the message is from the caller (human) or the AI Receptionist (bot).
user_type: Optional[TranscriptObjectUserType] = Field(alias='user_type', default=None)
#: Message content. For human messages this is a string; for bot messages it is an array of text objects.
message: Optional[str | list[MessageText]] = None
#: Additional metadata for the message.
metadata: Optional[MessageMetadata] = None
#: Indicates whether an error occurred while processing this message.
error: Optional[bool] = None
#: Creation timestamp in epoch milliseconds.
created_at: Optional[int] = Field(alias='created_at', default=None)
#: Last-updated timestamp in epoch milliseconds.
updated_at: Optional[int] = Field(alias='updated_at', default=None)
[docs]
class TranscriptsResponse(ApiModel):
#: Pagination metadata for the response.
meta: Optional[AIRSessionsMeta] = None
#: List of transcript message objects.
objects: Optional[list[TranscriptObject]] = None
#: Unique identifier for this API transaction.
transaction_id: Optional[str] = Field(alias='transaction_id', default=None)
[docs]
class AIReceptionistApi(ApiChild, base=''):
"""
AI Receptionist
AI Receptionist for Webex Calling allows administrators to configure and manage AI-powered receptionists that
handle incoming calls. This includes validating countries and AI receptionist names, listing available phone
numbers, managing templates, and retrieving intents.
Viewing these settings requires a full or read-only administrator auth token with a scope of
`spark-admin:telephony_config_read`.
Modifying these 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 another organization using the optional `orgId` query
parameter.
"""
[docs]
def sessions(
self, ai_receptionist_id: str, interaction_id: str = None, limit: int = None, offset: int = None
) -> AIRSessions:
"""
List AI Receptionist Sessions
List the AI Receptionist sessions for the given `aiReceptionistId`.
A session represents a single conversation between a caller and the AI Receptionist. You can optionally filter
sessions by `interaction_id` (which corresponds to the call correlation ID retrievable from the Webex Control
Hub troubleshooting page) to locate the session associated with a specific call.
This API requires a full administrator auth token with a CI role of `id_full_admin`.
:param ai_receptionist_id: Unique identifier of the AI Receptionist. AI Receptionist ID from the response of
List AI Receptionists API.
:type ai_receptionist_id: str
:param interaction_id: Filter sessions by the call correlation ID retrieved from Webex Control Hub
troubleshooting page.
:type interaction_id: str
:param limit: Maximum number of sessions to return in a single page. Must be between `1` and `100`.
:type limit: int
:param offset: Pagination offset. Starting index of the result set.
:type offset: int
:rtype: :class:`AIRSessions`
"""
params: dict[str, Any] = dict()
if interaction_id is not None:
params['interaction_id'] = interaction_id
if limit is not None:
params['limit'] = limit
if offset is not None:
params['offset'] = offset
url = self.ep(f'aiReceptionists/{ai_receptionist_id}/sessions')
data = super().get(url, params=params)
r = AIRSessions.model_validate(data)
return r
[docs]
def session_transcripts(
self, ai_receptionist_id: str, session_id: str, limit: int = None, offset: int = None
) -> TranscriptsResponse:
"""
Get AI Receptionist Session Transcripts
Retrieve the transcript (messages exchanged between the caller and the AI Receptionist) for a specific session.
Each message represents a single utterance, identified by `user_type` (`human` or `bot`). For bot messages, the
message is an array of text objects; for human messages, it is a plain string. Additional metadata may include
tool invocations, knowledge-base lookups, and latency information useful for debugging.
This API requires a full administrator auth token with a CI role of `id_full_admin`.
:param ai_receptionist_id: Unique identifier of the AI Receptionist. AI Receptionist ID from the response of
List AI Receptionists API.
:type ai_receptionist_id: str
:param session_id: Identifier of the session returned by the List AI Receptionist Sessions API.
:type session_id: str
:param limit: Maximum number of messages to return in a single page. Must be between `1` and `1000`.
:type limit: int
:param offset: Pagination offset. Starting index of the result set.
:type offset: int
:rtype: :class:`TranscriptsResponse`
"""
params: dict[str, Any] = dict()
if limit is not None:
params['limit'] = limit
if offset is not None:
params['offset'] = offset
url = self.ep(f'aiReceptionists/{ai_receptionist_id}/sessions/{session_id}/transcripts')
data = super().get(url, params=params)
r = TranscriptsResponse.model_validate(data)
return r
[docs]
def list(
self, location_id: str = None, name: str = None, phone_number: str = None, org_id: str = None, **params: Any
) -> Generator[AiReceptionist, None, None]:
"""
List AI Receptionists
Get list of AI Receptionists.
AI Receptionist is a Webex Calling feature that uses AI to greet callers and intelligently route calls to
people or services. These APIs let administrators manage AI receptionist resources across organizations and
locations.
This API requires a full or read-only administrator auth token with a scope of
`spark-admin:telephony_config_read`.
:param location_id: Location identifier. If not specified, returns AI receptionists from all locations.
:type location_id: str
:param name: Search AI receptionists by name (contains match).
:type name: str
:param phone_number: Search (Contains) based on number or extension. Search cannot be performed based on esn.
:type phone_number: str
:param org_id: Optional target organization identifier. Defaults to token's organization if not provided.
:type org_id: str
:return: Generator yielding :class:`AiReceptionist` instances
"""
if org_id is not None:
params['orgId'] = org_id
if location_id is not None:
params['locationId'] = location_id
if name is not None:
params['name'] = name
if phone_number is not None:
params['phoneNumber'] = phone_number
url = self.ep('telephony/config/aiReceptionists')
return self.session.follow_pagination(url=url, model=AiReceptionist, item_key='aiReceptionists', params=params)
[docs]
def validate_country(self, country_code: str, location_id: str = None, org_id: str = None) -> None:
"""
Validate Country for AI Receptionist
Validates if country passed in the request supports AI Receptionist.
AI Receptionist is a Webex Calling feature that uses AI to greet callers and intelligently route calls.
This API requires a full administrator auth token with a scope of `spark-admin:telephony_config_write`.
:param country_code: Two letter country code of the location for which AI Receptionist needs to be validated.
:type country_code: str
:param location_id: Location associated with the AI Receptionist.
:type location_id: str
:param org_id: Optional; target organization ID, otherwise defaults to token's org.
:type org_id: str
:rtype: None
"""
params: dict[str, Any] = dict()
if org_id is not None:
params['orgId'] = org_id
body: dict[str, Any] = dict()
body['countryCode'] = country_code
if location_id is not None:
body['locationId'] = location_id
url = self.ep('telephony/config/aiReceptionists/actions/validateCountry/invoke')
super().post(url, params=params, json=body)
[docs]
def templates(self, org_id: str = None) -> builtins.list[IdAndName]:
"""
List AI Receptionist Templates
Get AI Receptionist template list.
AI Receptionist is a Webex Calling feature that uses AI to greet callers and intelligently route calls.
Templates help standardize greetings, goals, and guidelines.
Returns all templates in a single response.
This API requires a full or read-only administrator auth token with a scope of
`spark-admin:telephony_config_read`.
:param org_id: Optional target organization identifier. Defaults to token's organization if not provided.
:type org_id: str
:rtype: list[AiReceptionistLocation]
"""
params: dict[str, Any] = dict()
if org_id is not None:
params['orgId'] = org_id
url = self.ep('telephony/config/aiReceptionists/templates')
data = super().get(url, params=params)
r = TypeAdapter(list[IdAndName]).validate_python(data['templates'])
return r
[docs]
def get_template(self, template_id: str, org_id: str = None) -> AIRTemplate:
"""
Get AI Receptionist template details.
AI Receptionist is a Webex Calling feature that uses AI to greet callers and intelligently route calls. Use
templates to define goals, messages, and guidelines.
This API requires a full or read-only administrator auth token with a scope of
`spark-admin:telephony_config_read`.
:param template_id: Template Id.
:type template_id: str
:param org_id: Optional target organization identifier. Defaults to token's organization if not provided.
:type org_id: str
:rtype: :class:`AIRTemplate`
"""
params: dict[str, Any] = dict()
if org_id is not None:
params['orgId'] = org_id
url = self.ep(f'telephony/config/aiReceptionists/templates/{template_id}')
data = super().get(url, params=params)
r = AIRTemplate.model_validate(data)
return r
[docs]
def knowledge_bases(
self, name: str = None, org_id: str = None, **params: Any
) -> Generator[KnowledgeBase, None, None]:
"""
List Knowledge Bases
Get list of Knowledge Bases for an organization.
Knowledge Bases are repositories of information that AI Receptionists use to answer caller queries. This API
returns all knowledge bases available in the organization.
This API requires a full or read-only administrator auth token with a scope of
`spark-admin:telephony_config_read`.
:param name: Search knowledge bases by name (contains match).
:type name: str
:param org_id: Optional target organization identifier. Defaults to token's organization if not provided.
:type org_id: str
:return: Generator yielding :class:`KnowledgeBaseSummary` instances
"""
if org_id is not None:
params['orgId'] = org_id
if name is not None:
params['name'] = name
url = self.ep('telephony/config/knowledgeBases')
return self.session.follow_pagination(url=url, model=KnowledgeBase, item_key='knowledgeBases', params=params)
[docs]
def create_knowledge_base(self, name: str, description: str = None, org_id: str = None) -> str:
"""
Create a Knowledge Base
Create a new Knowledge Base for an organization.
Knowledge Bases are repositories of information that AI Receptionists use to answer caller queries.
This API requires a full administrator auth token with a scope of `spark-admin:telephony_config_write`.
:param name: The display name assigned to the Knowledge Base. Used to identify the KB across the platform.
:type name: str
:param description: A human-readable description providing additional context about the purpose or contents of
the Knowledge Base.
:type description: str
:param org_id: Optional target organization identifier. Defaults to token's organization if not provided.
:type org_id: str
:rtype: str
"""
params: dict[str, Any] = dict()
if org_id is not None:
params['orgId'] = org_id
body: dict[str, Any] = dict()
body['name'] = name
if description is not None:
body['description'] = description
url = self.ep('telephony/config/knowledgeBases')
data = super().post(url, params=params, json=body)
r = data['id']
return r
[docs]
def delete_knowledge_base(self, knowledge_base_id: str, org_id: str = None) -> None:
"""
Delete a Knowledge Base.
Knowledge Bases are repositories of information that AI Receptionists use to answer caller queries.
This API requires a full administrator auth token with a scope of `spark-admin:telephony_config_write`.
:param knowledge_base_id: Unique identifier for the Knowledge Base.
:type knowledge_base_id: str
:param org_id: Optional target organization identifier. Defaults to token's organization if not provided.
:type org_id: str
:rtype: None
"""
params: dict[str, Any] = dict()
if org_id is not None:
params['orgId'] = org_id
url = self.ep(f'telephony/config/knowledgeBases/{knowledge_base_id}')
super().delete(url, params=params)
[docs]
def get_knowledge_base(self, knowledge_base_id: str, org_id: str = None) -> KnowledgeBase:
"""
Get Knowledge Base Details
Get details of a specific Knowledge Base.
Knowledge Bases are repositories of information that AI Receptionists use to answer caller queries.
This API requires a full or read-only administrator auth token with a scope of
`spark-admin:telephony_config_read`.
:param knowledge_base_id: Unique identifier for the Knowledge Base.
:type knowledge_base_id: str
:param org_id: Optional target organization identifier. Defaults to token's organization if not provided.
:type org_id: str
:rtype: :class:`KnowledgeBase`
"""
params: dict[str, Any] = dict()
if org_id is not None:
params['orgId'] = org_id
url = self.ep(f'telephony/config/knowledgeBases/{knowledge_base_id}')
data = super().get(url, params=params)
r = KnowledgeBase.model_validate(data)
return r
[docs]
def update_knowledge_base(
self, knowledge_base_id: str, name: str = None, description: str = None, org_id: str = None
) -> None:
"""
Modify a Knowledge Base
Modify an existing Knowledge Base.
Knowledge Bases are repositories of information that AI Receptionists use to answer caller queries.
This API requires a full administrator auth token with a scope of `spark-admin:telephony_config_write`.
:param knowledge_base_id: Unique identifier for the Knowledge Base.
:type knowledge_base_id: str
:param name: The display name assigned to the Knowledge Base. Used to identify the KB across the platform.
:type name: str
:param description: A human-readable description providing additional context about the purpose or contents of
the Knowledge Base.
:type description: str
:param org_id: Optional target organization identifier. Defaults to token's organization if not provided.
:type org_id: str
:rtype: None
"""
params: dict[str, Any] = dict()
if org_id is not None:
params['orgId'] = org_id
body: dict[str, Any] = dict()
if name is not None:
body['name'] = name
if description is not None:
body['description'] = description
url = self.ep(f'telephony/config/knowledgeBases/{knowledge_base_id}')
super().put(url, params=params, json=body)
[docs]
def list_knowledge_base_documents(
self, knowledge_base_id: str, org_id: str = None, **params: Any
) -> Generator[KnowledgeBaseDocumentDetails, None, None]:
"""
List Knowledge Base Documents
Get list of documents in a Knowledge Base.
Documents are files uploaded to a Knowledge Base that AI Receptionists use to answer caller queries.
This API requires a full or read-only administrator auth token with a scope of
`spark-admin:telephony_config_read`.
:param knowledge_base_id: Unique identifier for the Knowledge Base.
:type knowledge_base_id: str
:param org_id: Optional target organization identifier. Defaults to token's organization if not provided.
:type org_id: str
:return: Generator yielding :class:`KnowledgeBaseDocumentDetails` instances
"""
if org_id is not None:
params['orgId'] = org_id
url = self.ep(f'telephony/config/knowledgeBases/{knowledge_base_id}/documents')
return self.session.follow_pagination(
url=url, model=KnowledgeBaseDocumentDetails, item_key='documents', params=params
)
[docs]
def create_knowledge_base_document(
self, knowledge_base_id: str, name: str, content: str, org_id: str = None
) -> str:
"""
Create Knowledge Base Document
Create a new document in a Knowledge Base.
Documents are content entries in a Knowledge Base that AI Receptionists use to answer caller queries. This API
creates a document with specified name and content.
This API requires a full administrator auth token with a scope of `spark-admin:telephony_config_write`.
:param knowledge_base_id: Unique identifier for the Knowledge Base.
:type knowledge_base_id: str
:param name: The display name assigned to the Knowledge Base document. Used to identify the document across the
platform.
:type name: str
:param content: The content of the document.
:type content: str
:param org_id: Optional target organization identifier. Defaults to token's organization if not provided.
:type org_id: str
:rtype: str
"""
params: dict[str, Any] = dict()
if org_id is not None:
params['orgId'] = org_id
body: dict[str, Any] = dict()
body['name'] = name
body['content'] = content
url = self.ep(f'telephony/config/knowledgeBases/{knowledge_base_id}/documents')
data = super().post(url, params=params, json=body)
r = data['id']
return r
[docs]
def upload_knowledge_base_document(self, knowledge_base_id: str, file: str, org_id: str = None) -> str:
"""
Upload Knowledge Base Document
Upload a document to a Knowledge Base.
Documents are files uploaded to a Knowledge Base that AI Receptionists use to answer caller queries. Supported
file types include PDF, TXT, DOCX, XLSX, XLS, and CSV.
This API requires a full administrator auth token with a scope of `spark-admin:telephony_config_write`.
:param knowledge_base_id: Unique identifier for the Knowledge Base.
:type knowledge_base_id: str
:param file: The document file to upload. Supported file types: PDF, TXT, DOCX, XLSX, XLS, CSV. Maximum file
size: 10MB.
:type file: str
:param org_id: Optional target organization identifier. Defaults to token's organization if not provided.
:type org_id: str
:rtype: str
"""
params: dict[str, Any] = dict()
if org_id is not None:
params['orgId'] = org_id
upload_as = os.path.basename(file)
content_type, _ = mimetypes.guess_type(upload_as)
if content_type is None:
raise ValueError(f'Could not determine content type for {upload_as!r}')
with open(file, mode='rb') as content:
encoder = MultipartEncoder({'file': (upload_as, content, content_type)})
url = self.ep(f'telephony/config/knowledgeBases/{knowledge_base_id}/documents/actions/upload/invoke')
data = super().post(url, params=params, data=encoder, headers={'Content-Type': encoder.content_type})
r = data['id']
return r
[docs]
def delete_knowledge_base_document(self, knowledge_base_id: str, document_id: str, org_id: str = None) -> None:
"""
Delete Knowledge Base Document
Delete a document from a Knowledge Base.
Documents are files uploaded to a Knowledge Base that AI Receptionists use to answer caller queries.
This API requires a full administrator auth token with a scope of `spark-admin:telephony_config_write`.
:param knowledge_base_id: Unique identifier for the Knowledge Base.
:type knowledge_base_id: str
:param document_id: Unique identifier for the document.
:type document_id: str
:param org_id: Optional target organization identifier. Defaults to token's organization if not provided.
:type org_id: str
:rtype: None
"""
params: dict[str, Any] = dict()
if org_id is not None:
params['orgId'] = org_id
url = self.ep(f'telephony/config/knowledgeBases/{knowledge_base_id}/documents/{document_id}')
super().delete(url, params=params)
[docs]
def get_knowledge_base_document(
self, knowledge_base_id: str, document_id: str, org_id: str = None
) -> KnowledgeBaseDocumentDetails:
"""
Get Knowledge Base Document Details
Get details of a specific document in a Knowledge Base.
Documents are content entries in a Knowledge Base that AI Receptionists use to answer caller queries. This API
returns document metadata including name, content, status, and timestamps.
This API requires a full or read-only administrator auth token with a scope of
`spark-admin:telephony_config_read`.
:param knowledge_base_id: Unique identifier for the Knowledge Base.
:type knowledge_base_id: str
:param document_id: Unique identifier for the document.
:type document_id: str
:param org_id: Optional target organization identifier. Defaults to token's organization if not provided.
:type org_id: str
:rtype: :class:`KnowledgeBaseDocumentDetails`
"""
params: dict[str, Any] = dict()
if org_id is not None:
params['orgId'] = org_id
url = self.ep(f'telephony/config/knowledgeBases/{knowledge_base_id}/documents/{document_id}')
data = super().get(url, params=params)
r = KnowledgeBaseDocumentDetails.model_validate(data)
return r
[docs]
def update_knowledge_base_document(
self, knowledge_base_id: str, document_id: str, name: str = None, content: str = None, org_id: str = None
) -> None:
"""
Modify Knowledge Base Document
Modify a document in a Knowledge Base.
Documents are content entries in a Knowledge Base that AI Receptionists use to answer caller queries. This API
allows updating the name and content of an existing document.
This API requires a full administrator auth token with a scope of `spark-admin:telephony_config_write`.
:param knowledge_base_id: Unique identifier for the Knowledge Base.
:type knowledge_base_id: str
:param document_id: Unique identifier for the document.
:type document_id: str
:param name: The display name assigned to the Knowledge Base document. Used to identify the document across the
platform.
:type name: str
:param content: The content of the document.
:type content: str
:param org_id: Optional target organization identifier. Defaults to token's organization if not provided.
:type org_id: str
:rtype: None
"""
params: dict[str, Any] = dict()
if org_id is not None:
params['orgId'] = org_id
body: dict[str, Any] = dict()
if name is not None:
body['name'] = name
if content is not None:
body['content'] = content
url = self.ep(f'telephony/config/knowledgeBases/{knowledge_base_id}/documents/{document_id}')
super().put(url, params=params, json=body)
[docs]
def download_knowledge_base_document(self, knowledge_base_id: str, document_id: str, org_id: str = None) -> str:
"""
Download Knowledge Base Document
Download a document from a Knowledge Base.
Documents are files uploaded to a Knowledge Base that AI Receptionists use to answer caller queries. The
response contains the file content with appropriate Content-Type and Content-Disposition headers.
This API requires a full or read-only administrator auth token with a scope of
`spark-admin:telephony_config_read`.
**WARNING:** This API is not callable using the developer portal web interface due to the lack of support for
binary file downloads. This API can be utilized using other tools that support binary responses, such as
Postman or curl.
:param knowledge_base_id: Unique identifier for the Knowledge Base.
:type knowledge_base_id: str
:param document_id: Unique identifier for the document.
:type document_id: str
:param org_id: Optional target organization identifier. Defaults to token's organization if not provided.
:type org_id: str
:rtype: str
"""
params: dict[str, Any] = dict()
if org_id is not None:
params['orgId'] = org_id
url = self.ep(
f'telephony/config/knowledgeBases/{knowledge_base_id}/documents/{document_id}/actions/download/invoke'
)
data = super().post(url, params=params)
return data # type: ignore[return-value]
[docs]
def create(
self,
location_id: str,
name: str,
enabled: bool,
default_action: DefaultAction,
ai_agent: AiAgent,
phone_number: str = None,
extension: str = None,
direct_line_caller_id_name: AIRDirectLineCallerIdName = None,
dial_by_name: str = None,
org_id: str = None,
) -> str:
"""
Create an AI Receptionist
Create a new AI Receptionist for a location.
AI Receptionist is a Webex Calling feature that uses AI to greet callers and intelligently route calls to
people or services.
This API requires a full administrator auth token with a scope of `spark-admin:telephony_config_write`.
:param location_id: Location ID.
:type location_id: str
:param name: Name of the AI Receptionist. This has to be unique across location.
:type name: str
:param enabled: Flag to indicate AI receptionist is enabled or not. When disabled, incoming calls to this AI
receptionist will not be answered.
:type enabled: bool
:param default_action: Default action configuration for the AI Receptionist
:type default_action: DefaultAction
:param ai_agent: AI Agent configuration
:type ai_agent: AiAgent
:param phone_number: Phone number of the AI Receptionist. Either phoneNumber or extension is mandatory. At
least one is required.
:type phone_number: str
:param extension: Extension of the AI Receptionist. Either phoneNumber or extension is mandatory. At least one
is required.
:type extension: str
:param direct_line_caller_id_name: Direct line caller ID name configuration
:type direct_line_caller_id_name: AIRDirectLineCallerIdName
:param dial_by_name: A dial by name used for AI Receptionist name dialing. Characters of `%`, `+`, `\\`, `"`
and Unicode characters are not allowed.
:type dial_by_name: str
:param org_id: Optional target organization identifier. Defaults to token's organization if not provided.
:type org_id: str
:rtype: str
"""
params: dict[str, Any] = dict()
if org_id is not None:
params['orgId'] = org_id
body: dict[str, Any] = dict()
body['name'] = name
body['enabled'] = enabled
if phone_number is not None:
body['phoneNumber'] = phone_number
if extension is not None:
body['extension'] = extension
if direct_line_caller_id_name is not None:
body['directLineCallerIdName'] = direct_line_caller_id_name.model_dump(
mode='json', by_alias=True, exclude_none=True
)
if dial_by_name is not None:
body['dialByName'] = dial_by_name
body['defaultAction'] = default_action.update()
body['aiAgent'] = ai_agent.update()
url = self.ep(f'telephony/config/locations/{location_id}/aiReceptionists')
data = super().post(url, params=params, json=body)
r = data['id']
return r
[docs]
def validate(self, location_id: str, name: str, org_id: str = None) -> None:
"""
Validate AI Receptionist
Validates AI Receptionist name at location level and max limit at org level.
AI Receptionist is a Webex Calling feature that uses AI to greet callers and intelligently route calls.
This API requires a full administrator auth token with a scope of `spark-admin:telephony_config_write`.
:param location_id: Location ID.
:type location_id: str
:param name: Name of the AI Receptionist.
:type name: str
:param org_id: Optional target organization identifier, defaults to the token's org if not provided.
:type org_id: str
:rtype: None
"""
params: dict[str, Any] = dict()
if org_id is not None:
params['orgId'] = org_id
body: dict[str, Any] = dict()
body['name'] = name
url = self.ep(f'telephony/config/locations/{location_id}/aiReceptionists/actions/validate/invoke')
super().post(url, params=params, json=body)
[docs]
def available_numbers(
self, location_id: str, phone_number: str = None, org_id: str = None, **params: Any
) -> Generator[AvailableNumber, None, None]:
"""
List Available Numbers for AI Receptionist
List and search numbers that can be assigned as AI Receptionist number.
AI Receptionist is a Webex Calling feature that uses AI to greet callers and intelligently route calls. Numbers
listed here can be assigned to an AI receptionist at a location.
This API requires a full or read-only administrator auth token with a scope of
`spark-admin:telephony_config_read`.
:param location_id: Location ID.
:type location_id: str
:param phone_number: Search (Contains) based on number or extension. Search cannot be performed based on esn.
:type phone_number: str
:param org_id: Optional target organization identifier. Defaults to the token's org Id if not provided.
:type org_id: str
:return: Generator yielding :class:`AvailableNumber` instances
"""
if org_id is not None:
params['orgId'] = org_id
if phone_number is not None:
params['phoneNumber'] = phone_number
url = self.ep(f'telephony/config/locations/{location_id}/aiReceptionists/availableNumbers')
return self.session.follow_pagination(url=url, model=AvailableNumber, item_key='phoneNumbers', params=params)
[docs]
def voices(self, location_id: str, org_id: str = None) -> builtins.list[AiEngine]:
"""
Get AI Receptionist Voices
Get list of available AI Receptionist voices.
AI Receptionist is a Webex Calling feature that uses AI to greet callers and intelligently route calls. This
API returns the available voice options that can be configured for an AI Receptionist. The response returns
all available engines and voices; no pagination is required.
This API requires a full or read-only administrator auth token with a scope of
`spark-admin:telephony_config_read`.
:param location_id: Location ID.
:type location_id: str
:param org_id: Optional target organization identifier. Defaults to token's organization if not provided.
:type org_id: str
:rtype: list[AiEngine]
"""
params: dict[str, Any] = dict()
if org_id is not None:
params['orgId'] = org_id
url = self.ep(f'telephony/config/locations/{location_id}/aiReceptionists/voices')
data = super().get(url, params=params)
r = TypeAdapter(list[AiEngine]).validate_python(data['aiEngines'])
return r
# noinspection method-overriding
[docs]
def delete(self, location_id: str, ai_receptionist_id: str, org_id: str = None) -> None: # type: ignore[override]
"""
Delete an AI Receptionist.
AI Receptionist is a Webex Calling feature that uses AI to greet callers and intelligently route calls to
people or services.
This API requires a full administrator auth token with a scope of `spark-admin:telephony_config_write`.
:param location_id: Location ID.
:type location_id: str
:param ai_receptionist_id: Unique identifier for the AI Receptionist.
:type ai_receptionist_id: str
:param org_id: Optional target organization identifier. Defaults to token's organization if not provided.
:type org_id: str
:rtype: None
"""
params: dict[str, Any] = dict()
if org_id is not None:
params['orgId'] = org_id
url = self.ep(f'telephony/config/locations/{location_id}/aiReceptionists/{ai_receptionist_id}')
super().delete(url, params=params)
[docs]
def details(self, location_id: str, ai_receptionist_id: str, org_id: str = None) -> AiReceptionist:
"""
Get AI Receptionist details.
AI Receptionist is a Webex Calling feature that uses AI to greet callers and intelligently route calls to
people or services.
This API requires a full or read-only administrator auth token with a scope of
`spark-admin:telephony_config_read`.
:param location_id: Location ID.
:type location_id: str
:param ai_receptionist_id: Unique identifier for the AI Receptionist.
:type ai_receptionist_id: str
:param org_id: Optional target organization identifier. Defaults to token's organization if not provided.
:type org_id: str
:rtype: :class:`AiReceptionist`
"""
params: dict[str, Any] = dict()
if org_id is not None:
params['orgId'] = org_id
url = self.ep(f'telephony/config/locations/{location_id}/aiReceptionists/{ai_receptionist_id}')
data = super().get(url, params=params)
r = AiReceptionist.model_validate(data)
return r
[docs]
def update(self, location_id: str, ai_receptionist_id: str, settings=AiReceptionist, org_id: str = None) -> None:
"""
Update an AI Receptionist.
AI Receptionist is a Webex Calling feature that uses AI to greet callers and intelligently route calls to
people or services.
This API requires a full administrator auth token with a scope of `spark-admin:telephony_config_write`.
:param location_id: Location ID.
:type location_id: str
:param ai_receptionist_id: Unique identifier for the AI Receptionist.
:type ai_receptionist_id: str
:param settings: settings for AI Receptionist
:type settings: :class:`AiReceptionist`
:param org_id: Optional target organization identifier. Defaults to token's organization if not provided.
:type org_id: str
:rtype: None
"""
params: dict[str, Any] = dict()
if org_id is not None:
params['orgId'] = org_id
body = settings.update()
url = self.ep(f'telephony/config/locations/{location_id}/aiReceptionists/{ai_receptionist_id}')
super().put(url, params=params, json=body)
[docs]
def intents(self, location_id: str, ai_receptionist_id: str, org_id: str = None) -> builtins.list[AIRIntent]:
"""
List AI Receptionist Intents
Get list of AI Receptionist Intents.
AI Receptionist is a Webex Calling feature that uses AI to greet callers and intelligently route calls. Intents
represent call-handling behaviors such as transfers.
Returns all intents in a single response.
This API requires a full or read-only administrator auth token with a scope of
`spark-admin:telephony_config_read`.
:param location_id: Location ID.
:type location_id: str
:param ai_receptionist_id: Unique identifier for the AI Receptionist.
:type ai_receptionist_id: str
:param org_id: Optional target organization identifier. Defaults to token's organization if not provided.
:type org_id: str
:rtype: list[AIRIntent]
"""
params: dict[str, Any] = dict()
if org_id is not None:
params['orgId'] = org_id
url = self.ep(f'telephony/config/locations/{location_id}/aiReceptionists/{ai_receptionist_id}/intents')
data = super().get(url, params=params)
r = TypeAdapter(list[AIRIntent]).validate_python(data['intents'])
return r
[docs]
def create_intent(
self,
location_id: str,
ai_receptionist_id: str,
name: str,
description: str,
transfer_to: TransferTo,
org_id: str = None,
) -> str:
"""
Create AI Receptionist Intent
Create a new AI Receptionist Intent.
AI Receptionist is a Webex Calling feature that uses AI to greet callers and intelligently route calls. Intents
represent call-handling behaviors such as transfers.
This API requires a full administrator auth token with a scope of `spark-admin:telephony_config_write`.
:param location_id: Location ID.
:type location_id: str
:param ai_receptionist_id: Unique identifier for the AI Receptionist.
:type ai_receptionist_id: str
:param name: Name of the intent.
:type name: str
:param description: Description of the intent (Action).
:type description: str
:param transfer_to: -
:type transfer_to: TransferTo
:param org_id: Optional target organization identifier. Defaults to token's organization if not provided.
:type org_id: str
:rtype: str
"""
params: dict[str, Any] = dict()
if org_id is not None:
params['orgId'] = org_id
body: dict[str, Any] = dict()
body['name'] = name
body['description'] = description
body['transferTo'] = transfer_to.model_dump(mode='json', by_alias=True, exclude_none=True)
url = self.ep(f'telephony/config/locations/{location_id}/aiReceptionists/{ai_receptionist_id}/intents')
data = super().post(url, params=params, json=body)
r = data['id']
return r
[docs]
def delete_intent(self, location_id: str, ai_receptionist_id: str, intent_id: str, org_id: str = None) -> None:
"""
Delete AI Receptionist Intent
Delete an AI Receptionist Intent.
AI Receptionist is a Webex Calling feature that uses AI to greet callers and intelligently route calls. Intents
represent call-handling behaviors such as transfers.
This API requires a full administrator auth token with a scope of `spark-admin:telephony_config_write`.
:param location_id: Location ID.
:type location_id: str
:param ai_receptionist_id: Unique identifier for the AI Receptionist.
:type ai_receptionist_id: str
:param intent_id: Unique identifier for a specific AI Receptionist intent within a given location and AI
Receptionist instance.
:type intent_id: str
:param org_id: Optional target organization identifier. Defaults to token's organization if not provided.
:type org_id: str
:rtype: None
"""
params: dict[str, Any] = dict()
if org_id is not None:
params['orgId'] = org_id
url = self.ep(
f'telephony/config/locations/{location_id}/aiReceptionists/{ai_receptionist_id}/intents/{intent_id}'
)
super().delete(url, params=params)
[docs]
def get_intent(self, location_id: str, ai_receptionist_id: str, intent_id: str, org_id: str = None) -> AIRIntent:
"""
Get AI Receptionist Intent
Get details of a specific AI Receptionist Intent.
AI Receptionist is a Webex Calling feature that uses AI to greet callers and intelligently route calls. Intents
represent call-handling behaviors such as transfers.
This API requires a full or read-only administrator auth token with a scope of
`spark-admin:telephony_config_read`.
:param location_id: Location ID.
:type location_id: str
:param ai_receptionist_id: Unique identifier for the AI Receptionist.
:type ai_receptionist_id: str
:param intent_id: Unique identifier for a specific AI Receptionist intent within a given location and AI
Receptionist instance.
:type intent_id: str
:param org_id: Optional target organization identifier. Defaults to token's organization if not provided.
:type org_id: str
:rtype: :class:`AIRIntent`
"""
params: dict[str, Any] = dict()
if org_id is not None:
params['orgId'] = org_id
url = self.ep(
f'telephony/config/locations/{location_id}/aiReceptionists/{ai_receptionist_id}/intents/{intent_id}'
)
data = super().get(url, params=params)
r = AIRIntent.model_validate(data)
return r
[docs]
def modify_intent(
self, location_id: str, ai_receptionist_id: str, intent_id: str, settings: AIRIntent, org_id: str = None
) -> None:
"""
Modify AI Receptionist Intent
Modify an existing AI Receptionist Intent.
AI Receptionist is a Webex Calling feature that uses AI to greet callers and intelligently route calls. Intents
represent call-handling behaviors such as transfers.
This API requires a full administrator auth token with a scope of `spark-admin:telephony_config_write`.
:param location_id: Location ID.
:type location_id: str
:param ai_receptionist_id: Unique identifier for the AI Receptionist.
:type ai_receptionist_id: str
:param intent_id: Unique identifier for a specific AI Receptionist intent within a given location and AI
Receptionist instance.
:type intent_id: str
:param settings: Settings for this AIRIntent.
:type settings: :class:`AIRIntent`
:param org_id: Optional target organization identifier. Defaults to token's organization if not provided.
:type org_id: str
:rtype: None
"""
params: dict[str, Any] = dict()
if org_id is not None:
params['orgId'] = org_id
body = settings.update()
url = self.ep(
f'telephony/config/locations/{location_id}/aiReceptionists/{ai_receptionist_id}/intents/{intent_id}'
)
super().put(url, params=params, json=body)