From c2b71ee422373efd1b80bb079a62b687eeeb5a18 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 6 Oct 2026 11:32:47 +0000 Subject: [PATCH] chore: sync code from next into release PR --- .release-please-manifest.json | 2 +- .stats.yml | 2 +- CHANGELOG.md | 7 + api.md | 114 ++- pyproject.toml | 2 +- src/telnyx/_client.py | 136 +++ src/telnyx/_version.py | 2 +- src/telnyx/resources/__init__.py | 28 + .../resources/ai/assistants/__init__.py | 14 + .../resources/ai/assistants/assistants.py | 413 ++++++++- src/telnyx/resources/ai/assistants/deleted.py | 288 +++++++ .../resources/ai/assistants/versions.py | 38 + src/telnyx/resources/ai/memory/memory.py | 6 - .../ai/memory/namespaces/namespaces.py | 233 ++++- src/telnyx/resources/ai/openai/chat.py | 20 +- src/telnyx/resources/ai/tools.py | 12 +- src/telnyx/resources/calls/actions.py | 162 +++- src/telnyx/resources/calls/calls.py | 68 +- src/telnyx/resources/dir/dir.py | 384 ++++++++- src/telnyx/resources/dir/phone_numbers.py | 22 +- src/telnyx/resources/dir/references.py | 30 +- src/telnyx/resources/enterprises/__init__.py | 14 + src/telnyx/resources/enterprises/dir.py | 39 +- .../resources/enterprises/enterprises.py | 310 ++++++- .../resources/enterprises/reputation/loa.py | 5 +- .../resources/enterprises/verify_email.py | 287 +++++++ .../resources/llm_token_gateway/__init__.py | 33 + .../llm_token_gateway/llm_token_gateway.py | 108 +++ .../resources/llm_token_gateway/usage.py | 232 +++++ .../meeting_sessions/meeting_sessions.py | 24 +- src/telnyx/resources/spend_limits.py | 803 ++++++++++++++++++ .../whatsapp/phone_numbers/__init__.py | 14 + .../whatsapp/phone_numbers/calling_routing.py | 314 +++++++ .../whatsapp/phone_numbers/phone_numbers.py | 38 + src/telnyx/types/__init__.py | 26 + src/telnyx/types/ai/__init__.py | 20 + .../types/ai/assistant_create_params.py | 96 ++- .../types/ai/assistant_delete_params.py | 15 + src/telnyx/types/ai/assistant_param.py | 14 +- src/telnyx/types/ai/assistant_tool_param.py | 25 +- .../types/ai/assistant_update_params.py | 96 ++- .../types/ai/assistant_whatsapp_params.py | 38 + .../types/ai/assistant_whatsapp_response.py | 15 + src/telnyx/types/ai/assistants/__init__.py | 2 + .../assistants/canary_deploy_create_params.py | 6 +- .../assistants/canary_deploy_update_params.py | 7 +- .../types/ai/assistants/deleted_assistant.py | 24 + .../ai/assistants/deleted_list_params.py | 17 + .../types/ai/assistants/rule_input_param.py | 11 +- .../scheduled_event_create_params.py | 10 +- .../assistants/scheduled_event_list_params.py | 6 +- src/telnyx/types/ai/assistants/serve_param.py | 7 +- .../types/ai/assistants/test_create_params.py | 6 +- .../types/ai/assistants/test_update_params.py | 7 +- .../ai/assistants/version_update_params.py | 22 + .../types/ai/collection_create_params.py | 11 +- .../retrieval_settings_wrapper_param.py | 7 +- .../ai/collections/setting_create_params.py | 7 +- .../collections/setting_patch_all_params.py | 7 +- .../ai/collections/source_create_params.py | 7 +- .../ai/collections/source_replace_params.py | 7 +- .../ai/collections/source_request_param.py | 7 +- .../types/ai/conversation_flow_req_param.py | 19 +- src/telnyx/types/ai/delegation_settings.py | 75 ++ .../types/ai/delegation_settings_param.py | 74 ++ src/telnyx/types/ai/external_llm_param.py | 46 + src/telnyx/types/ai/external_llm_req_param.py | 7 +- .../types/ai/fallback_config_req_param.py | 7 +- src/telnyx/types/ai/flow_edge.py | 33 +- src/telnyx/types/ai/flow_edge_param.py | 40 +- src/telnyx/types/ai/flow_node_req_param.py | 20 +- src/telnyx/types/ai/hangup_tool_param.py | 7 +- src/telnyx/types/ai/inference_embedding.py | 22 + ...e_embedding_interruption_settings_param.py | 7 +- .../ai/inference_embedding_voice_settings.py | 9 +- ...nference_embedding_voice_settings_param.py | 9 +- ...inference_embedding_webhook_tool_params.py | 14 +- ...nce_embedding_webhook_tool_params_param.py | 14 +- src/telnyx/types/ai/memory/__init__.py | 17 + src/telnyx/types/ai/memory/namespace.py | 20 + .../ai/memory/namespace_create_params.py | 12 + .../ai/memory/namespace_create_response.py | 13 + .../ai/memory/namespace_list_response.py | 14 + src/telnyx/types/ai/mission_create_params.py | 7 +- .../types/ai/mission_update_mission_params.py | 7 +- .../types/ai/missions/run_update_params.py | 7 +- .../ai/missions/runs/event_log_params.py | 7 +- .../runs/plan_add_steps_to_plan_params.py | 7 +- .../ai/missions/runs/plan_create_params.py | 7 +- .../missions/runs/plan_update_step_params.py | 7 +- .../types/ai/observability_req_param.py | 11 +- .../openai/chat_create_completion_params.py | 18 +- src/telnyx/types/ai/retrieval_tool_param.py | 7 +- src/telnyx/types/ai/speak_node_req_param.py | 7 +- .../types/ai/start_speaking_plan_param.py | 7 +- src/telnyx/types/ai/tool_create_params.py | 10 +- src/telnyx/types/ai/tool_node.py | 19 +- src/telnyx/types/ai/tool_node_req_param.py | 31 +- src/telnyx/types/ai/tool_update_params.py | 11 +- .../types/ai/transcription_settings_param.py | 7 +- src/telnyx/types/ai/voice_settings_param.py | 7 +- src/telnyx/types/ai/webhook_tool_param.py | 8 + src/telnyx/types/ai/websocket_settings.py | 35 + .../types/ai/websocket_settings_param.py | 33 + src/telnyx/types/ai/widget_settings_param.py | 7 +- .../authentication_provider_create_params.py | 7 +- .../authentication_provider_update_params.py | 7 +- src/telnyx/types/billing_contact.py | 17 +- src/telnyx/types/billing_contact_param.py | 17 +- .../types/bpo_authorization_input_param.py | 25 + .../types/call_assistant_request_param.py | 49 +- .../call_control_application_create_params.py | 11 +- .../call_control_application_update_params.py | 10 +- ...call_conversation_created_webhook_event.py | 74 ++ ...all_conversation_created_webhook_event1.py | 74 ++ src/telnyx/types/call_dial_params.py | 93 +- ...m_call_screening_detected_webhook_event.py | 67 ++ ..._call_screening_detected_webhook_event1.py | 67 ++ ...premium_detection_started_webhook_event.py | 60 ++ ...remium_detection_started_webhook_event1.py | 60 ++ .../call_machine_premium_greeting_ended.py | 9 +- ...action_add_ai_assistant_messages_params.py | 14 +- .../types/calls/action_answer_params.py | 22 +- .../calls/action_gather_using_ai_params.py | 29 +- .../calls/action_gather_using_speak_params.py | 17 +- .../calls/action_join_ai_assistant_params.py | 7 +- src/telnyx/types/calls/action_pay_params.py | 16 +- .../types/calls/action_reject_params.py | 9 +- src/telnyx/types/calls/action_speak_params.py | 21 +- .../calls/action_start_ai_assistant_params.py | 34 +- .../action_start_conversation_relay_params.py | 27 +- .../calls/action_start_playback_params.py | 7 +- .../action_start_transcription_params.py | 62 +- .../types/calls/action_transfer_params.py | 34 +- .../calls/telnyx_voice_settings_param.py | 6 +- .../transcription_engine_a_config_param.py | 6 +- .../transcription_engine_b_config_param.py | 7 +- ...ranscription_engine_google_config_param.py | 6 +- ...ranscription_engine_telnyx_config_param.py | 7 +- .../transcription_start_request_param.py | 63 +- .../types/conferences/action_hold_params.py | 6 +- .../types/conferences/action_join_params.py | 6 +- .../types/conferences/action_leave_params.py | 7 +- .../types/conferences/action_mute_params.py | 6 +- .../types/conferences/action_play_params.py | 6 +- .../conferences/action_record_pause_params.py | 7 +- .../action_record_resume_params.py | 7 +- .../conferences/action_record_start_params.py | 7 +- .../conferences/action_record_stop_params.py | 7 +- .../types/conferences/action_speak_params.py | 5 +- .../types/conferences/action_stop_params.py | 6 +- .../types/conferences/action_unhold_params.py | 6 +- .../types/conferences/action_unmute_params.py | 6 +- .../types/conferences/action_update_params.py | 6 +- ...onversation_relay_embedded_config_param.py | 53 +- ...ation_relay_interruption_settings_param.py | 11 +- .../conversation_relay_language_param.py | 39 +- .../credential_connection_create_params.py | 38 +- .../credential_connection_update_params.py | 38 +- ...custom_storage_credential_create_params.py | 15 +- ...custom_storage_credential_update_params.py | 15 +- src/telnyx/types/dir/comment_list_params.py | 6 +- src/telnyx/types/dir/dir.py | 16 + .../dir/phone_number_batch_list_params.py | 6 +- .../types/dir/phone_number_list_params.py | 6 +- .../types/dir/phone_number_remove_params.py | 4 + .../types/dir/reference_create_params.py | 9 +- .../types/dir/reference_update_params.py | 22 +- src/telnyx/types/dir_bpo_loa_params.py | 27 + src/telnyx/types/dir_delete_response.py | 23 + src/telnyx/types/dir_list_params.py | 6 +- src/telnyx/types/dir_new_loa_params.py | 24 +- .../dir_retrieve_bpo_authorizations_params.py | 20 + ...ir_retrieve_bpo_authorizations_response.py | 53 ++ src/telnyx/types/dir_status.py | 1 + .../types/dir_update_infringement_params.py | 15 +- src/telnyx/types/dir_update_params.py | 27 +- src/telnyx/types/doc_reqs_requirement.py | 4 +- src/telnyx/types/document.py | 1 + src/telnyx/types/document_param.py | 1 + src/telnyx/types/email_address_input_param.py | 6 +- .../types/email_domain_create_params.py | 11 +- src/telnyx/types/email_domain_list_params.py | 10 +- .../types/email_domain_update_params.py | 11 +- .../email_domains/webhook_create_params.py | 7 +- .../email_domains/webhook_update_params.py | 7 +- .../messages/action_forward_params.py | 11 +- .../inbox_action_recipient_input_param.py | 5 +- .../types/email_message_batch_params.py | 22 +- .../types/email_message_create_params.py | 22 +- src/telnyx/types/enterprise_create_params.py | 79 +- src/telnyx/types/enterprise_list_params.py | 8 +- src/telnyx/types/enterprise_public.py | 85 +- src/telnyx/types/enterprise_update_params.py | 83 +- src/telnyx/types/enterprises/__init__.py | 8 + .../types/enterprises/dir_create_params.py | 25 +- ...prise_email_verification_status_wrapped.py | 41 + .../reputation/agent_input_param.py | 31 + .../reputation/loa_render_params.py | 37 +- .../reputation/remediation_list_params.py | 6 +- .../enterprises/reputation_enable_params.py | 7 +- .../reputation_update_frequency_params.py | 7 +- .../verify_email_confirm_params.py | 12 + .../types/fax_application_create_params.py | 6 +- .../types/fax_application_update_params.py | 6 +- src/telnyx/types/fax_create_params.py | 6 +- .../types/fqdn_connection_create_params.py | 46 +- .../types/fqdn_connection_update_params.py | 46 +- src/telnyx/types/infringement_claim.py | 4 + .../infringement_claim_contest_params.py | 7 +- .../types/ip_connection_create_params.py | 34 +- .../types/ip_connection_update_params.py | 38 +- .../types/llm_token_gateway/__init__.py | 18 + .../usage_retrieve_summary_params.py | 25 + .../usage_retrieve_summary_response.py | 215 +++++ ...session_delete_recording_media_response.py | 2 +- ...ng_session_retrieve_recordings_response.py | 5 +- src/telnyx/types/message_whatsapp_params.py | 6 +- .../messaging_10dlc/brand_create_params.py | 14 +- .../messaging_10dlc/brand_update_params.py | 22 +- .../types/messaging_profile_create_params.py | 14 +- .../messaging_profile_metric_list_params.py | 7 +- ...ssaging_profile_retrieve_metrics_params.py | 7 +- .../types/messaging_profile_update_params.py | 14 +- .../verification/request_create_params.py | 22 +- .../verification/request_list_params.py | 6 +- .../verification/request_update_params.py | 22 +- src/telnyx/types/model_metadata.py | 6 +- .../types/network_coverage_list_params.py | 8 +- src/telnyx/types/network_create_params.py | 7 +- src/telnyx/types/network_update_params.py | 7 +- ...phone_number_update_requirements_params.py | 7 +- .../types/number_order_update_params.py | 7 +- .../types/number_reservation_create_params.py | 7 +- src/telnyx/types/organization_contact.py | 12 +- .../types/organization_contact_param.py | 12 +- src/telnyx/types/outbound_fqdn_param.py | 7 +- .../outbound_voice_profile_create_params.py | 18 +- .../outbound_voice_profile_update_params.py | 18 +- .../phone_numbers/job_update_batch_params.py | 6 +- .../update_voice_settings_param.py | 19 +- .../phone_numbers/voice_update_params.py | 19 +- src/telnyx/types/physical_address.py | 10 + src/telnyx/types/physical_address_param.py | 10 + .../types/porting/report_create_params.py | 7 +- src/telnyx/types/porting_order.py | 4 +- .../types/porting_order_end_user_param.py | 11 +- src/telnyx/types/porting_order_list_params.py | 6 +- src/telnyx/types/porting_order_misc_param.py | 7 +- .../types/porting_order_update_params.py | 22 +- .../porting_phone_number_block.py | 4 +- src/telnyx/types/porting_phone_number.py | 4 +- .../types/portouts/report_create_params.py | 7 +- .../types/pronunciation_dict_create_params.py | 7 +- .../types/pronunciation_dict_item_param.py | 8 +- .../types/pronunciation_dict_update_params.py | 7 +- .../rcs/agent_campaign_configuration_param.py | 10 +- .../types/rcs/agent_configuration_param.py | 35 +- src/telnyx/types/rcs/agent_create_params.py | 10 +- src/telnyx/types/rcs/agent_launch_params.py | 14 +- src/telnyx/types/rcs/agent_update_params.py | 11 +- src/telnyx/types/rcs/brand_create_params.py | 28 +- .../types/rcs/brand_identifier_param.py | 8 +- src/telnyx/types/rcs/brand_update_params.py | 28 +- src/telnyx/types/rcs_agent_message_param.py | 16 +- src/telnyx/types/rcs_card_content_param.py | 11 +- src/telnyx/types/requirement_list_params.py | 2 +- .../types/room_composition_create_params.py | 7 +- .../shared_params/book_appointment_tool.py | 7 +- .../call_control_retrieval_tool.py | 7 +- .../shared_params/check_availability_tool.py | 7 +- src/telnyx/types/signature_payload_param.py | 19 + src/telnyx/types/sim_card_update_params.py | 6 +- .../speech_to_text_list_providers_params.py | 7 +- src/telnyx/types/spend_limit.py | 145 ++++ src/telnyx/types/spend_limit_create_params.py | 44 + src/telnyx/types/spend_limit_delete_params.py | 18 + src/telnyx/types/spend_limit_list_response.py | 26 + src/telnyx/types/spend_limit_period.py | 9 + src/telnyx/types/spend_limit_response.py | 13 + src/telnyx/types/spend_limit_update_params.py | 38 + .../types/sub_number_order_update_params.py | 7 +- .../terms_of_service/agreement_list_params.py | 6 +- .../types/terms_of_service/tos_agreement.py | 4 + .../terms_of_service_retrieve_info_params.py | 7 +- ...terms_of_service_retrieve_info_response.py | 4 + ...terms_of_service_retrieve_status_params.py | 7 +- ...rms_of_service_retrieve_status_response.py | 1 + .../types/texml_application_create_params.py | 10 +- .../types/texml_application_update_params.py | 10 +- .../text_to_speech_generate_speech_params.py | 5 +- .../types/uac_connection_create_params.py | 46 +- .../types/uac_connection_update_params.py | 46 +- .../types/unsafe_unwrap_webhook_event.py | 8 + src/telnyx/types/unwrap_webhook_event.py | 8 + .../types/whatsapp/phone_numbers/__init__.py | 16 + .../calling_routing_list_response.py | 12 + .../calling_routing_patch_all_params.py | 18 + .../calling_routing_patch_all_response.py | 12 + .../whatsapp_calling_routing_data.py | 21 + .../types/whatsapp/template_create_params.py | 22 +- .../types/whatsapp_interactive_param.py | 15 +- .../types/whatsapp_message_content_param.py | 31 +- ...whatsapp_message_template_update_params.py | 22 +- .../ai/assistants/test_deleted.py | 183 ++++ .../ai/assistants/test_versions.py | 44 + .../ai/memory/test_namespaces.py | 214 ++++- tests/api_resources/ai/test_assistants.py | 341 +++++++- tests/api_resources/ai/test_embeddings.py | 4 +- tests/api_resources/ai/test_tools.py | 12 +- tests/api_resources/calls/test_actions.py | 22 +- tests/api_resources/enterprises/test_dir.py | 14 + .../enterprises/test_verify_email.py | 200 +++++ .../llm_token_gateway/__init__.py | 1 + .../llm_token_gateway/test_usage.py | 105 +++ tests/api_resources/test_calls.py | 10 + tests/api_resources/test_dir.py | 290 ++++++- tests/api_resources/test_enterprises.py | 2 + tests/api_resources/test_spend_limits.py | 611 +++++++++++++ .../phone_numbers/test_calling_routing.py | 203 +++++ uv.lock | 2 +- 321 files changed, 10178 insertions(+), 1433 deletions(-) create mode 100644 src/telnyx/resources/ai/assistants/deleted.py create mode 100644 src/telnyx/resources/enterprises/verify_email.py create mode 100644 src/telnyx/resources/llm_token_gateway/__init__.py create mode 100644 src/telnyx/resources/llm_token_gateway/llm_token_gateway.py create mode 100644 src/telnyx/resources/llm_token_gateway/usage.py create mode 100644 src/telnyx/resources/spend_limits.py create mode 100644 src/telnyx/resources/whatsapp/phone_numbers/calling_routing.py create mode 100644 src/telnyx/types/ai/assistant_delete_params.py create mode 100644 src/telnyx/types/ai/assistant_whatsapp_params.py create mode 100644 src/telnyx/types/ai/assistant_whatsapp_response.py create mode 100644 src/telnyx/types/ai/assistants/deleted_assistant.py create mode 100644 src/telnyx/types/ai/assistants/deleted_list_params.py create mode 100644 src/telnyx/types/ai/delegation_settings.py create mode 100644 src/telnyx/types/ai/delegation_settings_param.py create mode 100644 src/telnyx/types/ai/external_llm_param.py create mode 100644 src/telnyx/types/ai/memory/namespace.py create mode 100644 src/telnyx/types/ai/memory/namespace_create_params.py create mode 100644 src/telnyx/types/ai/memory/namespace_create_response.py create mode 100644 src/telnyx/types/ai/memory/namespace_list_response.py create mode 100644 src/telnyx/types/ai/websocket_settings.py create mode 100644 src/telnyx/types/ai/websocket_settings_param.py create mode 100644 src/telnyx/types/bpo_authorization_input_param.py create mode 100644 src/telnyx/types/call_conversation_created_webhook_event.py create mode 100644 src/telnyx/types/call_conversation_created_webhook_event1.py create mode 100644 src/telnyx/types/call_machine_premium_call_screening_detected_webhook_event.py create mode 100644 src/telnyx/types/call_machine_premium_call_screening_detected_webhook_event1.py create mode 100644 src/telnyx/types/call_machine_premium_detection_started_webhook_event.py create mode 100644 src/telnyx/types/call_machine_premium_detection_started_webhook_event1.py create mode 100644 src/telnyx/types/dir_bpo_loa_params.py create mode 100644 src/telnyx/types/dir_delete_response.py create mode 100644 src/telnyx/types/dir_retrieve_bpo_authorizations_params.py create mode 100644 src/telnyx/types/dir_retrieve_bpo_authorizations_response.py create mode 100644 src/telnyx/types/enterprises/enterprise_email_verification_status_wrapped.py create mode 100644 src/telnyx/types/enterprises/verify_email_confirm_params.py create mode 100644 src/telnyx/types/llm_token_gateway/__init__.py create mode 100644 src/telnyx/types/llm_token_gateway/usage_retrieve_summary_params.py create mode 100644 src/telnyx/types/llm_token_gateway/usage_retrieve_summary_response.py create mode 100644 src/telnyx/types/signature_payload_param.py create mode 100644 src/telnyx/types/spend_limit.py create mode 100644 src/telnyx/types/spend_limit_create_params.py create mode 100644 src/telnyx/types/spend_limit_delete_params.py create mode 100644 src/telnyx/types/spend_limit_list_response.py create mode 100644 src/telnyx/types/spend_limit_period.py create mode 100644 src/telnyx/types/spend_limit_response.py create mode 100644 src/telnyx/types/spend_limit_update_params.py create mode 100644 src/telnyx/types/whatsapp/phone_numbers/calling_routing_list_response.py create mode 100644 src/telnyx/types/whatsapp/phone_numbers/calling_routing_patch_all_params.py create mode 100644 src/telnyx/types/whatsapp/phone_numbers/calling_routing_patch_all_response.py create mode 100644 src/telnyx/types/whatsapp/phone_numbers/whatsapp_calling_routing_data.py create mode 100644 tests/api_resources/ai/assistants/test_deleted.py create mode 100644 tests/api_resources/enterprises/test_verify_email.py create mode 100644 tests/api_resources/llm_token_gateway/__init__.py create mode 100644 tests/api_resources/llm_token_gateway/test_usage.py create mode 100644 tests/api_resources/test_spend_limits.py create mode 100644 tests/api_resources/whatsapp/phone_numbers/test_calling_routing.py diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 72019e396..acf7fd8f0 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "4.182.0" + ".": "4.183.0" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index 35e5522ba..ac4a2f512 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1 +1 @@ -configured_endpoints: 1284 +configured_endpoints: 1302 diff --git a/CHANGELOG.md b/CHANGELOG.md index 46fed3ebd..d4e02b07c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [4.183.0](https://github.com/team-telnyx/telnyx-python/compare/v4.182.0...v4.183.0) (2026-10-06) + + +### Features + +* promote from staging 057094f ([68dc138](https://github.com/team-telnyx/telnyx-python/commit/68dc1388498571521eabdcbeba537f30ea4469ba)) + ## [4.182.0](https://github.com/team-telnyx/telnyx-python/compare/v4.181.0...v4.182.0) (2026-09-25) diff --git a/api.md b/api.md index 77ff31afa..f0ba36b98 100644 --- a/api.md +++ b/api.md @@ -340,6 +340,7 @@ from telnyx.types import ( ArtifactFailedWebhookEvent, CallAnsweredWebhookEvent, CallBridgedWebhookEvent, + CallConversationCreatedWebhookEvent, CallConversationEndedWebhookEvent, CallConversationInsightsGeneratedWebhookEvent, CallCostWebhookEvent, @@ -356,7 +357,9 @@ from telnyx.types import ( CallLeftQueueWebhookEvent, CallMachineDetectionEndedWebhookEvent, CallMachineGreetingEndedWebhookEvent, + CallMachinePremiumCallScreeningDetectedWebhookEvent, CallMachinePremiumDetectionEndedWebhookEvent, + CallMachinePremiumDetectionStartedWebhookEvent, CallMachinePremiumGreetingEndedWebhookEvent, CallPaymentCompletedWebhookEvent, CallPaymentProgressWebhookEvent, @@ -406,6 +409,7 @@ from telnyx.types import ( ArtifactFailedWebhookEvent, CallAnsweredWebhookEvent, CallBridgedWebhookEvent, + CallConversationCreatedWebhookEvent, CallConversationEndedWebhookEvent, CallConversationInsightsGeneratedWebhookEvent, CallCostWebhookEvent, @@ -422,7 +426,9 @@ from telnyx.types import ( CallLeftQueueWebhookEvent, CallMachineDetectionEndedWebhookEvent, CallMachineGreetingEndedWebhookEvent, + CallMachinePremiumCallScreeningDetectedWebhookEvent, CallMachinePremiumDetectionEndedWebhookEvent, + CallMachinePremiumDetectionStartedWebhookEvent, CallMachinePremiumGreetingEndedWebhookEvent, CallPaymentCompletedWebhookEvent, CallPaymentProgressWebhookEvent, @@ -620,6 +626,7 @@ from telnyx.types.ai import ( ComparisonExpression, ConversationFlow, ConversationFlowReq, + DelegationSettings, EnabledFeatures, Expression, ExternalLlm, @@ -659,11 +666,13 @@ from telnyx.types.ai import ( TransferTool, VoiceSettings, WebhookTool, + WebsocketSettings, WidgetSettings, AssistantDeleteResponse, AssistantChatResponse, AssistantGetTexmlResponse, AssistantSendSMSResponse, + AssistantWhatsappResponse, ) ``` @@ -673,12 +682,14 @@ Methods: - client.ai.assistants.retrieve(assistant_id, \*\*params) -> InferenceEmbedding - client.ai.assistants.update(assistant_id, \*\*params) -> InferenceEmbedding - client.ai.assistants.list() -> AssistantsList -- client.ai.assistants.delete(assistant_id) -> AssistantDeleteResponse +- client.ai.assistants.delete(assistant_id, \*\*params) -> AssistantDeleteResponse - client.ai.assistants.chat(assistant_id, \*\*params) -> AssistantChatResponse - client.ai.assistants.clone(assistant_id) -> InferenceEmbedding - client.ai.assistants.get_texml(assistant_id) -> str - client.ai.assistants.imports(\*\*params) -> AssistantsList +- client.ai.assistants.restore(assistant_id) -> InferenceEmbedding - client.ai.assistants.send_sms(assistant_id, \*\*params) -> AssistantSendSMSResponse +- client.ai.assistants.whatsapp(assistant_id, \*\*params) -> AssistantWhatsappResponse ### Tests @@ -841,6 +852,19 @@ Methods: - client.ai.assistants.instructions.enhance(assistant_id, \*\*params) -> str +### Deleted + +Types: + +```python +from telnyx.types.ai.assistants import DeletedAssistant +``` + +Methods: + +- client.ai.assistants.deleted.list(\*\*params) -> SyncDefaultFlatPagination[DeletedAssistant] +- client.ai.assistants.deleted.get(assistant_id) -> DeletedAssistant + ## Audio Types: @@ -1310,7 +1334,7 @@ Methods: - client.ai.tools.retrieve(tool_id) -> SharedToolResponse - client.ai.tools.update(tool_id, \*\*params) -> SharedToolResponse - client.ai.tools.list(\*\*params) -> SyncDefaultFlatPagination[SharedToolResponse] -- client.ai.tools.delete(tool_id) -> object +- client.ai.tools.delete(tool_id) -> None ## Anthropic @@ -1361,12 +1385,20 @@ Methods: Types: ```python -from telnyx.types.ai.memory import NamespaceRetrieveResponse +from telnyx.types.ai.memory import ( + Namespace, + NamespaceCreateResponse, + NamespaceRetrieveResponse, + NamespaceListResponse, +) ``` Methods: +- client.ai.memory.namespaces.create(\*\*params) -> NamespaceCreateResponse - client.ai.memory.namespaces.retrieve(operation_id, \*, namespace) -> NamespaceRetrieveResponse +- client.ai.memory.namespaces.list() -> NamespaceListResponse +- client.ai.memory.namespaces.delete(namespace) -> None #### Profiles @@ -5936,6 +5968,23 @@ Methods: - client.whatsapp.phone_numbers.conversational_components.list(phone_number) -> ConversationalComponentListResponse - client.whatsapp.phone_numbers.conversational_components.patch_all(phone_number, \*\*params) -> ConversationalComponentPatchAllResponse +### CallingRouting + +Types: + +```python +from telnyx.types.whatsapp.phone_numbers import ( + WhatsappCallingRoutingData, + CallingRoutingListResponse, + CallingRoutingPatchAllResponse, +) +``` + +Methods: + +- client.whatsapp.phone_numbers.calling_routing.list(id) -> CallingRoutingListResponse +- client.whatsapp.phone_numbers.calling_routing.patch_all(id, \*\*params) -> CallingRoutingPatchAllResponse + ## UserData Types: @@ -6163,6 +6212,19 @@ Methods: - client.enterprises.dir.create(enterprise_id, \*\*params) -> DirWrapped - client.enterprises.dir.list(enterprise_id, \*\*params) -> SyncDefaultFlatPagination[Dir] +## VerifyEmail + +Types: + +```python +from telnyx.types.enterprises import EnterpriseEmailVerificationStatusWrapped +``` + +Methods: + +- client.enterprises.verify_email.create(enterprise_id) -> EnterpriseEmailVerificationStatusWrapped +- client.enterprises.verify_email.confirm(enterprise_id, \*\*params) -> EnterpriseEmailVerificationStatusWrapped + # Reputation ## Numbers @@ -6311,7 +6373,18 @@ Methods: Types: ```python -from telnyx.types import Dir, DirList, DirStatus, DirWrapped, Document, DirListDocumentTypesResponse +from telnyx.types import ( + BpoAuthorizationInput, + Dir, + DirList, + DirStatus, + DirWrapped, + Document, + SignaturePayload, + DirDeleteResponse, + DirListDocumentTypesResponse, + DirRetrieveBpoAuthorizationsResponse, +) ``` Methods: @@ -6319,10 +6392,12 @@ Methods: - client.dir.retrieve(dir_id) -> DirWrapped - client.dir.update(dir_id, \*\*params) -> DirWrapped - client.dir.list(\*\*params) -> SyncDefaultFlatPagination[Dir] -- client.dir.delete(dir_id) -> None +- client.dir.delete(dir_id) -> DirDeleteResponse +- client.dir.bpo_loa(dir_id, \*\*params) -> BinaryAPIResponse - client.dir.list_document_types() -> DirListDocumentTypesResponse - client.dir.list_infringement_claims(dir_id, \*\*params) -> SyncDefaultFlatPagination[InfringementClaim] - client.dir.new_loa(dir_id, \*\*params) -> BinaryAPIResponse +- client.dir.retrieve_bpo_authorizations(dir_id, \*\*params) -> DirRetrieveBpoAuthorizationsResponse - client.dir.submit(dir_id) -> DirWrapped - client.dir.update_infringement(dir_id, \*\*params) -> DirWrapped @@ -7025,3 +7100,32 @@ from telnyx.types import MachinePaymentAccountCreditResponse Methods: - client.machine_payments.account_credit(\*\*params) -> MachinePaymentAccountCreditResponse + +# SpendLimits + +Types: + +```python +from telnyx.types import SpendLimit, SpendLimitPeriod, SpendLimitResponse, SpendLimitListResponse +``` + +Methods: + +- client.spend_limits.create(\*\*params) -> SpendLimitResponse +- client.spend_limits.update(product, \*\*params) -> SpendLimitResponse +- client.spend_limits.list() -> SpendLimitListResponse +- client.spend_limits.delete(product, \*\*params) -> SpendLimitResponse + +# LlmTokenGateway + +## Usage + +Types: + +```python +from telnyx.types.llm_token_gateway import UsageRetrieveSummaryResponse +``` + +Methods: + +- client.llm_token_gateway.usage.retrieve_summary(\*\*params) -> UsageRetrieveSummaryResponse diff --git a/pyproject.toml b/pyproject.toml index 943ee0b1a..7221235ad 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "telnyx" -version = "4.182.0" +version = "4.183.0" description = "The official Python library for the telnyx API" dynamic = ["readme"] license = "MIT" diff --git a/src/telnyx/_client.py b/src/telnyx/_client.py index 8a9e789f8..e81238b3f 100644 --- a/src/telnyx/_client.py +++ b/src/telnyx/_client.py @@ -93,6 +93,7 @@ email_events, oauth_grants, requirements, + spend_limits, voice_clones, bot_challenge, channel_zones, @@ -146,6 +147,7 @@ charges_breakdown, email_validations, global_ip_latency, + llm_token_gateway, messaging_optouts, requirement_types, room_compositions, @@ -259,6 +261,7 @@ from .resources.email_events import EmailEventsResource, AsyncEmailEventsResource from .resources.oauth_grants import OAuthGrantsResource, AsyncOAuthGrantsResource from .resources.requirements import RequirementsResource, AsyncRequirementsResource + from .resources.spend_limits import SpendLimitsResource, AsyncSpendLimitsResource from .resources.voice_clones import VoiceClonesResource, AsyncVoiceClonesResource from .resources.bot_challenge import BotChallengeResource, AsyncBotChallengeResource from .resources.channel_zones import ChannelZonesResource, AsyncChannelZonesResource @@ -465,6 +468,7 @@ from .resources.terms_of_service.terms_of_service import TermsOfServiceResource, AsyncTermsOfServiceResource from .resources.verified_numbers.verified_numbers import VerifiedNumbersResource, AsyncVerifiedNumbersResource from .resources.email_validations.email_validations import EmailValidationsResource, AsyncEmailValidationsResource + from .resources.llm_token_gateway.llm_token_gateway import LlmTokenGatewayResource, AsyncLlmTokenGatewayResource from .resources.messaging_profiles.messaging_profiles import ( MessagingProfilesResource, AsyncMessagingProfilesResource, @@ -1920,6 +1924,28 @@ def machine_payments(self) -> MachinePaymentsResource: return MachinePaymentsResource(self) + @cached_property + def spend_limits(self) -> SpendLimitsResource: + """Daily and monthly spend limits per product. + + A limit applies to the organization of the authenticated user, or to the user's own account when they belong to no organization; every user of the organization sees and changes the same limits. + + - **Periods.** `daily` covers the current UTC day and `monthly` the current UTC calendar month. The two limits are independent: you can set either, both or neither. + - **Blocking.** When spend in a period goes above the limit (strictly greater), the product is blocked until the period ends: 00:00 UTC the next day for `daily`, 00:00 UTC on the 1st of the next month for `monthly`. A block appears within about 2 minutes (daily) or 10 minutes (monthly) of the spend being recorded. + - **Changes apply immediately.** Creating, updating or deleting a limit checks the period's spend in the same request: raising the limit above the spend, or removing it, lifts that period's block, and lowering it below the spend blocks the product at once. The `evaluation` object in the response says what happened. + - **Supported products.** Today only `inference` supports spend limits. A blocked account gets HTTP 403 with the error title `Inference spend limit reached` (code `10039`) on new billable chat completions, Responses, Anthropic Messages and classification requests; requests already running finish normally. Take the list of products from the list operation. + - **Limits set by Telnyx.** Telnyx support can also set a limit on your account. It is listed with `origin: operator` and you can update or delete it like your own. + """ + from .resources.spend_limits import SpendLimitsResource + + return SpendLimitsResource(self) + + @cached_property + def llm_token_gateway(self) -> LlmTokenGatewayResource: + from .resources.llm_token_gateway import LlmTokenGatewayResource + + return LlmTokenGatewayResource(self) + @cached_property def with_raw_response(self) -> TelnyxWithRawResponse: return TelnyxWithRawResponse(self) @@ -3473,6 +3499,28 @@ def machine_payments(self) -> AsyncMachinePaymentsResource: return AsyncMachinePaymentsResource(self) + @cached_property + def spend_limits(self) -> AsyncSpendLimitsResource: + """Daily and monthly spend limits per product. + + A limit applies to the organization of the authenticated user, or to the user's own account when they belong to no organization; every user of the organization sees and changes the same limits. + + - **Periods.** `daily` covers the current UTC day and `monthly` the current UTC calendar month. The two limits are independent: you can set either, both or neither. + - **Blocking.** When spend in a period goes above the limit (strictly greater), the product is blocked until the period ends: 00:00 UTC the next day for `daily`, 00:00 UTC on the 1st of the next month for `monthly`. A block appears within about 2 minutes (daily) or 10 minutes (monthly) of the spend being recorded. + - **Changes apply immediately.** Creating, updating or deleting a limit checks the period's spend in the same request: raising the limit above the spend, or removing it, lifts that period's block, and lowering it below the spend blocks the product at once. The `evaluation` object in the response says what happened. + - **Supported products.** Today only `inference` supports spend limits. A blocked account gets HTTP 403 with the error title `Inference spend limit reached` (code `10039`) on new billable chat completions, Responses, Anthropic Messages and classification requests; requests already running finish normally. Take the list of products from the list operation. + - **Limits set by Telnyx.** Telnyx support can also set a limit on your account. It is listed with `origin: operator` and you can update or delete it like your own. + """ + from .resources.spend_limits import AsyncSpendLimitsResource + + return AsyncSpendLimitsResource(self) + + @cached_property + def llm_token_gateway(self) -> AsyncLlmTokenGatewayResource: + from .resources.llm_token_gateway import AsyncLlmTokenGatewayResource + + return AsyncLlmTokenGatewayResource(self) + @cached_property def with_raw_response(self) -> AsyncTelnyxWithRawResponse: return AsyncTelnyxWithRawResponse(self) @@ -4962,6 +5010,28 @@ def machine_payments(self) -> machine_payments.MachinePaymentsResourceWithRawRes return MachinePaymentsResourceWithRawResponse(self._client.machine_payments) + @cached_property + def spend_limits(self) -> spend_limits.SpendLimitsResourceWithRawResponse: + """Daily and monthly spend limits per product. + + A limit applies to the organization of the authenticated user, or to the user's own account when they belong to no organization; every user of the organization sees and changes the same limits. + + - **Periods.** `daily` covers the current UTC day and `monthly` the current UTC calendar month. The two limits are independent: you can set either, both or neither. + - **Blocking.** When spend in a period goes above the limit (strictly greater), the product is blocked until the period ends: 00:00 UTC the next day for `daily`, 00:00 UTC on the 1st of the next month for `monthly`. A block appears within about 2 minutes (daily) or 10 minutes (monthly) of the spend being recorded. + - **Changes apply immediately.** Creating, updating or deleting a limit checks the period's spend in the same request: raising the limit above the spend, or removing it, lifts that period's block, and lowering it below the spend blocks the product at once. The `evaluation` object in the response says what happened. + - **Supported products.** Today only `inference` supports spend limits. A blocked account gets HTTP 403 with the error title `Inference spend limit reached` (code `10039`) on new billable chat completions, Responses, Anthropic Messages and classification requests; requests already running finish normally. Take the list of products from the list operation. + - **Limits set by Telnyx.** Telnyx support can also set a limit on your account. It is listed with `origin: operator` and you can update or delete it like your own. + """ + from .resources.spend_limits import SpendLimitsResourceWithRawResponse + + return SpendLimitsResourceWithRawResponse(self._client.spend_limits) + + @cached_property + def llm_token_gateway(self) -> llm_token_gateway.LlmTokenGatewayResourceWithRawResponse: + from .resources.llm_token_gateway import LlmTokenGatewayResourceWithRawResponse + + return LlmTokenGatewayResourceWithRawResponse(self._client.llm_token_gateway) + class AsyncTelnyxWithRawResponse: _client: AsyncTelnyx @@ -6324,6 +6394,28 @@ def machine_payments(self) -> machine_payments.AsyncMachinePaymentsResourceWithR return AsyncMachinePaymentsResourceWithRawResponse(self._client.machine_payments) + @cached_property + def spend_limits(self) -> spend_limits.AsyncSpendLimitsResourceWithRawResponse: + """Daily and monthly spend limits per product. + + A limit applies to the organization of the authenticated user, or to the user's own account when they belong to no organization; every user of the organization sees and changes the same limits. + + - **Periods.** `daily` covers the current UTC day and `monthly` the current UTC calendar month. The two limits are independent: you can set either, both or neither. + - **Blocking.** When spend in a period goes above the limit (strictly greater), the product is blocked until the period ends: 00:00 UTC the next day for `daily`, 00:00 UTC on the 1st of the next month for `monthly`. A block appears within about 2 minutes (daily) or 10 minutes (monthly) of the spend being recorded. + - **Changes apply immediately.** Creating, updating or deleting a limit checks the period's spend in the same request: raising the limit above the spend, or removing it, lifts that period's block, and lowering it below the spend blocks the product at once. The `evaluation` object in the response says what happened. + - **Supported products.** Today only `inference` supports spend limits. A blocked account gets HTTP 403 with the error title `Inference spend limit reached` (code `10039`) on new billable chat completions, Responses, Anthropic Messages and classification requests; requests already running finish normally. Take the list of products from the list operation. + - **Limits set by Telnyx.** Telnyx support can also set a limit on your account. It is listed with `origin: operator` and you can update or delete it like your own. + """ + from .resources.spend_limits import AsyncSpendLimitsResourceWithRawResponse + + return AsyncSpendLimitsResourceWithRawResponse(self._client.spend_limits) + + @cached_property + def llm_token_gateway(self) -> llm_token_gateway.AsyncLlmTokenGatewayResourceWithRawResponse: + from .resources.llm_token_gateway import AsyncLlmTokenGatewayResourceWithRawResponse + + return AsyncLlmTokenGatewayResourceWithRawResponse(self._client.llm_token_gateway) + class TelnyxWithStreamedResponse: _client: Telnyx @@ -7688,6 +7780,28 @@ def machine_payments(self) -> machine_payments.MachinePaymentsResourceWithStream return MachinePaymentsResourceWithStreamingResponse(self._client.machine_payments) + @cached_property + def spend_limits(self) -> spend_limits.SpendLimitsResourceWithStreamingResponse: + """Daily and monthly spend limits per product. + + A limit applies to the organization of the authenticated user, or to the user's own account when they belong to no organization; every user of the organization sees and changes the same limits. + + - **Periods.** `daily` covers the current UTC day and `monthly` the current UTC calendar month. The two limits are independent: you can set either, both or neither. + - **Blocking.** When spend in a period goes above the limit (strictly greater), the product is blocked until the period ends: 00:00 UTC the next day for `daily`, 00:00 UTC on the 1st of the next month for `monthly`. A block appears within about 2 minutes (daily) or 10 minutes (monthly) of the spend being recorded. + - **Changes apply immediately.** Creating, updating or deleting a limit checks the period's spend in the same request: raising the limit above the spend, or removing it, lifts that period's block, and lowering it below the spend blocks the product at once. The `evaluation` object in the response says what happened. + - **Supported products.** Today only `inference` supports spend limits. A blocked account gets HTTP 403 with the error title `Inference spend limit reached` (code `10039`) on new billable chat completions, Responses, Anthropic Messages and classification requests; requests already running finish normally. Take the list of products from the list operation. + - **Limits set by Telnyx.** Telnyx support can also set a limit on your account. It is listed with `origin: operator` and you can update or delete it like your own. + """ + from .resources.spend_limits import SpendLimitsResourceWithStreamingResponse + + return SpendLimitsResourceWithStreamingResponse(self._client.spend_limits) + + @cached_property + def llm_token_gateway(self) -> llm_token_gateway.LlmTokenGatewayResourceWithStreamingResponse: + from .resources.llm_token_gateway import LlmTokenGatewayResourceWithStreamingResponse + + return LlmTokenGatewayResourceWithStreamingResponse(self._client.llm_token_gateway) + class AsyncTelnyxWithStreamedResponse: _client: AsyncTelnyx @@ -9100,6 +9214,28 @@ def machine_payments(self) -> machine_payments.AsyncMachinePaymentsResourceWithS return AsyncMachinePaymentsResourceWithStreamingResponse(self._client.machine_payments) + @cached_property + def spend_limits(self) -> spend_limits.AsyncSpendLimitsResourceWithStreamingResponse: + """Daily and monthly spend limits per product. + + A limit applies to the organization of the authenticated user, or to the user's own account when they belong to no organization; every user of the organization sees and changes the same limits. + + - **Periods.** `daily` covers the current UTC day and `monthly` the current UTC calendar month. The two limits are independent: you can set either, both or neither. + - **Blocking.** When spend in a period goes above the limit (strictly greater), the product is blocked until the period ends: 00:00 UTC the next day for `daily`, 00:00 UTC on the 1st of the next month for `monthly`. A block appears within about 2 minutes (daily) or 10 minutes (monthly) of the spend being recorded. + - **Changes apply immediately.** Creating, updating or deleting a limit checks the period's spend in the same request: raising the limit above the spend, or removing it, lifts that period's block, and lowering it below the spend blocks the product at once. The `evaluation` object in the response says what happened. + - **Supported products.** Today only `inference` supports spend limits. A blocked account gets HTTP 403 with the error title `Inference spend limit reached` (code `10039`) on new billable chat completions, Responses, Anthropic Messages and classification requests; requests already running finish normally. Take the list of products from the list operation. + - **Limits set by Telnyx.** Telnyx support can also set a limit on your account. It is listed with `origin: operator` and you can update or delete it like your own. + """ + from .resources.spend_limits import AsyncSpendLimitsResourceWithStreamingResponse + + return AsyncSpendLimitsResourceWithStreamingResponse(self._client.spend_limits) + + @cached_property + def llm_token_gateway(self) -> llm_token_gateway.AsyncLlmTokenGatewayResourceWithStreamingResponse: + from .resources.llm_token_gateway import AsyncLlmTokenGatewayResourceWithStreamingResponse + + return AsyncLlmTokenGatewayResourceWithStreamingResponse(self._client.llm_token_gateway) + Client = Telnyx diff --git a/src/telnyx/_version.py b/src/telnyx/_version.py index d9fdc8dc7..b27cecb7a 100644 --- a/src/telnyx/_version.py +++ b/src/telnyx/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "telnyx" -__version__ = "4.182.0" # x-release-please-version +__version__ = "4.183.0" # x-release-please-version diff --git a/src/telnyx/resources/__init__.py b/src/telnyx/resources/__init__.py index a07625f89..35a968ec8 100644 --- a/src/telnyx/resources/__init__.py +++ b/src/telnyx/resources/__init__.py @@ -449,6 +449,14 @@ RequirementsResourceWithStreamingResponse, AsyncRequirementsResourceWithStreamingResponse, ) +from .spend_limits import ( + SpendLimitsResource, + AsyncSpendLimitsResource, + SpendLimitsResourceWithRawResponse, + AsyncSpendLimitsResourceWithRawResponse, + SpendLimitsResourceWithStreamingResponse, + AsyncSpendLimitsResourceWithStreamingResponse, +) from .voice_clones import ( VoiceClonesResource, AsyncVoiceClonesResource, @@ -873,6 +881,14 @@ GlobalIPLatencyResourceWithStreamingResponse, AsyncGlobalIPLatencyResourceWithStreamingResponse, ) +from .llm_token_gateway import ( + LlmTokenGatewayResource, + AsyncLlmTokenGatewayResource, + LlmTokenGatewayResourceWithRawResponse, + AsyncLlmTokenGatewayResourceWithRawResponse, + LlmTokenGatewayResourceWithStreamingResponse, + AsyncLlmTokenGatewayResourceWithStreamingResponse, +) from .messaging_optouts import ( MessagingOptoutsResource, AsyncMessagingOptoutsResource, @@ -2623,4 +2639,16 @@ "AsyncMachinePaymentsResourceWithRawResponse", "MachinePaymentsResourceWithStreamingResponse", "AsyncMachinePaymentsResourceWithStreamingResponse", + "SpendLimitsResource", + "AsyncSpendLimitsResource", + "SpendLimitsResourceWithRawResponse", + "AsyncSpendLimitsResourceWithRawResponse", + "SpendLimitsResourceWithStreamingResponse", + "AsyncSpendLimitsResourceWithStreamingResponse", + "LlmTokenGatewayResource", + "AsyncLlmTokenGatewayResource", + "LlmTokenGatewayResourceWithRawResponse", + "AsyncLlmTokenGatewayResourceWithRawResponse", + "LlmTokenGatewayResourceWithStreamingResponse", + "AsyncLlmTokenGatewayResourceWithStreamingResponse", ] diff --git a/src/telnyx/resources/ai/assistants/__init__.py b/src/telnyx/resources/ai/assistants/__init__.py index e572476e8..f9768eb44 100644 --- a/src/telnyx/resources/ai/assistants/__init__.py +++ b/src/telnyx/resources/ai/assistants/__init__.py @@ -24,6 +24,14 @@ ToolsResourceWithStreamingResponse, AsyncToolsResourceWithStreamingResponse, ) +from .deleted import ( + DeletedResource, + AsyncDeletedResource, + DeletedResourceWithRawResponse, + AsyncDeletedResourceWithRawResponse, + DeletedResourceWithStreamingResponse, + AsyncDeletedResourceWithStreamingResponse, +) from .versions import ( VersionsResource, AsyncVersionsResource, @@ -108,6 +116,12 @@ "AsyncInstructionsResourceWithRawResponse", "InstructionsResourceWithStreamingResponse", "AsyncInstructionsResourceWithStreamingResponse", + "DeletedResource", + "AsyncDeletedResource", + "DeletedResourceWithRawResponse", + "AsyncDeletedResourceWithRawResponse", + "DeletedResourceWithStreamingResponse", + "AsyncDeletedResourceWithStreamingResponse", "AssistantsResource", "AsyncAssistantsResource", "AssistantsResourceWithRawResponse", diff --git a/src/telnyx/resources/ai/assistants/assistants.py b/src/telnyx/resources/ai/assistants/assistants.py index 3fe718d55..7ccab59b4 100644 --- a/src/telnyx/resources/ai/assistants/assistants.py +++ b/src/telnyx/resources/ai/assistants/assistants.py @@ -23,6 +23,14 @@ ToolsResourceWithStreamingResponse, AsyncToolsResourceWithStreamingResponse, ) +from .deleted import ( + DeletedResource, + AsyncDeletedResource, + DeletedResourceWithRawResponse, + AsyncDeletedResourceWithRawResponse, + DeletedResourceWithStreamingResponse, + AsyncDeletedResourceWithStreamingResponse, +) from .versions import ( VersionsResource, AsyncVersionsResource, @@ -37,10 +45,12 @@ from ....types.ai import ( assistant_chat_params, assistant_create_params, + assistant_delete_params, assistant_update_params, assistant_imports_params, assistant_retrieve_params, assistant_send_sms_params, + assistant_whatsapp_params, ) from .tests.tests import ( TestsResource, @@ -94,12 +104,15 @@ from ....types.ai.observability_req_param import ObservabilityReqParam from ....types.ai.messaging_settings_param import MessagingSettingsParam from ....types.ai.telephony_settings_param import TelephonySettingsParam +from ....types.ai.websocket_settings_param import WebsocketSettingsParam from ....types.ai.assistant_delete_response import AssistantDeleteResponse +from ....types.ai.delegation_settings_param import DelegationSettingsParam from ....types.ai.fallback_config_req_param import FallbackConfigReqParam from ....types.ai.assistant_a2_a_agent_param import AssistantA2AAgentParam from ....types.ai.assistant_mcp_server_param import AssistantMcpServerParam from ....types.ai.assistant_integration_param import AssistantIntegrationParam from ....types.ai.assistant_send_sms_response import AssistantSendSMSResponse +from ....types.ai.assistant_whatsapp_response import AssistantWhatsappResponse from ....types.ai.conversation_flow_req_param import ConversationFlowReqParam from ....types.ai.transcription_settings_param import TranscriptionSettingsParam from ....types.ai.post_conversation_settings_req_param import PostConversationSettingsReqParam @@ -147,6 +160,11 @@ def instructions(self) -> InstructionsResource: """Configure AI assistant specifications""" return InstructionsResource(self._client) + @cached_property + def deleted(self) -> DeletedResource: + """Configure AI assistant specifications""" + return DeletedResource(self._client) + @cached_property def with_raw_response(self) -> AssistantsResourceWithRawResponse: """ @@ -173,6 +191,7 @@ def create( name: str, a2a_agents: Iterable[AssistantA2AAgentParam] | Omit = omit, conversation_flow: ConversationFlowReqParam | Omit = omit, + delegation_settings: DelegationSettingsParam | Omit = omit, description: str | Omit = omit, dynamic_variables: Dict[str, object] | Omit = omit, dynamic_variables_webhook_timeout_ms: int | Omit = omit, @@ -197,6 +216,7 @@ def create( tools: Iterable[AssistantToolParam] | Omit = omit, transcription: TranscriptionSettingsParam | Omit = omit, voice_settings: InferenceEmbeddingVoiceSettingsParam | Omit = omit, + websocket_settings: WebsocketSettingsParam | Omit = omit, widget_settings: WidgetSettingsParam | Omit = omit, idempotency_key: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -229,6 +249,14 @@ def create( unique node/edge IDs, that `start_node_id` references a real node, and that every edge's endpoints reference real nodes. + delegation_settings: Splits the conversation between a frontend model that talks to the caller and a + backend model that does the work. On the GPT-Live route the frontend model + cannot call tools at all — when it needs something done it raises a delegation + and waits. On the chat completion route the frontend keeps a single `delegate` + tool that returns immediately, so the conversation carries on while the backend + works. Either way the backend's answer is spoken as commentary or kept as silent + context, depending on `speak_results`. Beta feature. + dynamic_variables: Map of dynamic variables and their default values dynamic_variables_webhook_timeout_ms: Timeout in milliseconds for the dynamic variables webhook. Must be between 1 and @@ -297,6 +325,12 @@ def create( assistant. Prefer `tool_ids` to attach shared tools created with the AI Tools endpoints. + websocket_settings: Streams conversation and telephony events to a WebSocket server you host, and + accepts messages injected back into the conversation. Telnyx opens the + connection as a client, once per conversation. Delivery is best effort + throughout: while the connection is down events are dropped rather than queued, + and no socket failure is ever allowed to affect the call. Beta feature. + widget_settings: Configuration settings for the assistant's web widget. extra_headers: Send extra headers @@ -316,6 +350,7 @@ def create( "name": name, "a2a_agents": a2a_agents, "conversation_flow": conversation_flow, + "delegation_settings": delegation_settings, "description": description, "dynamic_variables": dynamic_variables, "dynamic_variables_webhook_timeout_ms": dynamic_variables_webhook_timeout_ms, @@ -340,6 +375,7 @@ def create( "tools": tools, "transcription": transcription, "voice_settings": voice_settings, + "websocket_settings": websocket_settings, "widget_settings": widget_settings, }, assistant_create_params.AssistantCreateParams, @@ -413,6 +449,7 @@ def update( *, a2a_agents: Iterable[AssistantA2AAgentParam] | Omit = omit, conversation_flow: ConversationFlowReqParam | Omit = omit, + delegation_settings: DelegationSettingsParam | Omit = omit, description: str | Omit = omit, dynamic_variables: Dict[str, object] | Omit = omit, dynamic_variables_webhook_timeout_ms: int | Omit = omit, @@ -441,6 +478,7 @@ def update( transcription: TranscriptionSettingsParam | Omit = omit, version_name: str | Omit = omit, voice_settings: InferenceEmbeddingVoiceSettingsParam | Omit = omit, + websocket_settings: WebsocketSettingsParam | Omit = omit, widget_settings: WidgetSettingsParam | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -471,6 +509,14 @@ def update( unique node/edge IDs, that `start_node_id` references a real node, and that every edge's endpoints reference real nodes. + delegation_settings: Splits the conversation between a frontend model that talks to the caller and a + backend model that does the work. On the GPT-Live route the frontend model + cannot call tools at all — when it needs something done it raises a delegation + and waits. On the chat completion route the frontend keeps a single `delegate` + tool that returns immediately, so the conversation carries on while the backend + works. Either way the backend's answer is spoken as commentary or kept as silent + context, depending on `speak_results`. Beta feature. + dynamic_variables: Map of dynamic variables and their default values dynamic_variables_webhook_timeout_ms: Timeout in milliseconds for the dynamic variables webhook. Must be between 1 and @@ -558,6 +604,12 @@ def update( version_name: Human-readable name for the assistant version. + websocket_settings: Streams conversation and telephony events to a WebSocket server you host, and + accepts messages injected back into the conversation. Telnyx opens the + connection as a client, once per conversation. Delivery is best effort + throughout: while the connection is down events are dropped rather than queued, + and no socket failure is ever allowed to affect the call. Beta feature. + widget_settings: Configuration settings for the assistant's web widget. extra_headers: Send extra headers @@ -576,6 +628,7 @@ def update( { "a2a_agents": a2a_agents, "conversation_flow": conversation_flow, + "delegation_settings": delegation_settings, "description": description, "dynamic_variables": dynamic_variables, "dynamic_variables_webhook_timeout_ms": dynamic_variables_webhook_timeout_ms, @@ -604,6 +657,7 @@ def update( "transcription": transcription, "version_name": version_name, "voice_settings": voice_settings, + "websocket_settings": websocket_settings, "widget_settings": widget_settings, }, assistant_update_params.AssistantUpdateParams, @@ -637,6 +691,7 @@ def delete( self, assistant_id: str, *, + hard_delete: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -647,7 +702,24 @@ def delete( """ Delete an AI Assistant by `assistant_id`. + By default this performs a soft delete: the assistant moves to the Recently + Deleted list and stays restorable for 30 days, after which it is permanently + deleted automatically. The assistant's versions and TeXML application are + preserved during the retention window. + + Pass `hard_delete=true` to skip the retention window and permanently delete the + assistant immediately. A hard delete erases the assistant and all of its + versions, and deletes its TeXML application unless phone numbers are still + assigned to it. It does not delete conversations, recordings, shared tools the + assistant referenced, or knowledge-base embeddings. + + Deletion fails with `400` if other assistants reference this one through a + handoff tool or a conversation-flow edge — remove those references first. + Args: + hard_delete: Permanently delete the assistant immediately instead of soft-deleting it to the + Recently Deleted list, where it stays restorable for 30 days. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -661,7 +733,11 @@ def delete( return self._delete( path_template("/ai/assistants/{assistant_id}", assistant_id=assistant_id), options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform({"hard_delete": hard_delete}, assistant_delete_params.AssistantDeleteParams), ), cast_to=AssistantDeleteResponse, ) @@ -855,6 +931,43 @@ def imports( cast_to=AssistantsList, ) + def restore( + self, + assistant_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> InferenceEmbedding: + """ + Restore a soft-deleted assistant from the Recently Deleted list. + + The assistant becomes fully active again with its versions and TeXML application + as they were at deletion time. Restoring does not re-enable numbers or + connections that were released separately after the deletion. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not assistant_id: + raise ValueError(f"Expected a non-empty value for `assistant_id` but received {assistant_id!r}") + return self._post( + path_template("/ai/assistants/{assistant_id}/restore", assistant_id=assistant_id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=InferenceEmbedding, + ) + def send_sms( self, assistant_id: str, @@ -916,6 +1029,81 @@ def send_sms( cast_to=AssistantSendSMSResponse, ) + def whatsapp( + self, + assistant_id: str, + *, + content: str, + from_: str, + to: str, + conversation_metadata: Dict[str, Union[str, int, bool]] | Omit = omit, + idempotency_key: str | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> AssistantWhatsappResponse: + """Start a WhatsApp conversation with a customer from the business side. + + This + endpoint: + + 1. Validates that `from` is a WhatsApp number on your account whose messaging + profile has this assistant configured + 2. Creates a new `whatsapp_chat` conversation with the provided metadata + 3. Asks the assistant to pick one of its approved WhatsApp templates and fill + its variables from `content` + 4. Sends the template from `from` to `to` + 5. Returns the conversation ID and the message ID + + When the customer replies, the reply is routed to the same conversation and the + assistant answers within the 24-hour customer service window. The assistant + needs a `whatsapp_template` tool with at least one approved template, data + retention enabled and PII redaction disabled. + + Args: + content: Instruction for the assistant, including the values for the template variables, + e.g. `Send the login verification code 482913 to the customer.` + + from_: WhatsApp number on your account to send from, in E.164 format. Its messaging + profile must have this assistant configured. + + to: Customer to message, as an E.164 phone number or a WhatsApp business-scoped user + ID (BSUID). + + conversation_metadata: Metadata stored on the conversation. Keys starting with `telnyx_` and the + `assistant_id` key are reserved. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not assistant_id: + raise ValueError(f"Expected a non-empty value for `assistant_id` but received {assistant_id!r}") + extra_headers = {**strip_not_given({"Idempotency-Key": idempotency_key}), **(extra_headers or {})} + return self._post( + path_template("/ai/assistants/{assistant_id}/chat/whatsapp", assistant_id=assistant_id), + body=maybe_transform( + { + "content": content, + "from_": from_, + "to": to, + "conversation_metadata": conversation_metadata, + }, + assistant_whatsapp_params.AssistantWhatsappParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=AssistantWhatsappResponse, + ) + class AsyncAssistantsResource(AsyncAPIResource): """Configure AI assistant specifications""" @@ -955,6 +1143,11 @@ def instructions(self) -> AsyncInstructionsResource: """Configure AI assistant specifications""" return AsyncInstructionsResource(self._client) + @cached_property + def deleted(self) -> AsyncDeletedResource: + """Configure AI assistant specifications""" + return AsyncDeletedResource(self._client) + @cached_property def with_raw_response(self) -> AsyncAssistantsResourceWithRawResponse: """ @@ -981,6 +1174,7 @@ async def create( name: str, a2a_agents: Iterable[AssistantA2AAgentParam] | Omit = omit, conversation_flow: ConversationFlowReqParam | Omit = omit, + delegation_settings: DelegationSettingsParam | Omit = omit, description: str | Omit = omit, dynamic_variables: Dict[str, object] | Omit = omit, dynamic_variables_webhook_timeout_ms: int | Omit = omit, @@ -1005,6 +1199,7 @@ async def create( tools: Iterable[AssistantToolParam] | Omit = omit, transcription: TranscriptionSettingsParam | Omit = omit, voice_settings: InferenceEmbeddingVoiceSettingsParam | Omit = omit, + websocket_settings: WebsocketSettingsParam | Omit = omit, widget_settings: WidgetSettingsParam | Omit = omit, idempotency_key: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -1037,6 +1232,14 @@ async def create( unique node/edge IDs, that `start_node_id` references a real node, and that every edge's endpoints reference real nodes. + delegation_settings: Splits the conversation between a frontend model that talks to the caller and a + backend model that does the work. On the GPT-Live route the frontend model + cannot call tools at all — when it needs something done it raises a delegation + and waits. On the chat completion route the frontend keeps a single `delegate` + tool that returns immediately, so the conversation carries on while the backend + works. Either way the backend's answer is spoken as commentary or kept as silent + context, depending on `speak_results`. Beta feature. + dynamic_variables: Map of dynamic variables and their default values dynamic_variables_webhook_timeout_ms: Timeout in milliseconds for the dynamic variables webhook. Must be between 1 and @@ -1105,6 +1308,12 @@ async def create( assistant. Prefer `tool_ids` to attach shared tools created with the AI Tools endpoints. + websocket_settings: Streams conversation and telephony events to a WebSocket server you host, and + accepts messages injected back into the conversation. Telnyx opens the + connection as a client, once per conversation. Delivery is best effort + throughout: while the connection is down events are dropped rather than queued, + and no socket failure is ever allowed to affect the call. Beta feature. + widget_settings: Configuration settings for the assistant's web widget. extra_headers: Send extra headers @@ -1124,6 +1333,7 @@ async def create( "name": name, "a2a_agents": a2a_agents, "conversation_flow": conversation_flow, + "delegation_settings": delegation_settings, "description": description, "dynamic_variables": dynamic_variables, "dynamic_variables_webhook_timeout_ms": dynamic_variables_webhook_timeout_ms, @@ -1148,6 +1358,7 @@ async def create( "tools": tools, "transcription": transcription, "voice_settings": voice_settings, + "websocket_settings": websocket_settings, "widget_settings": widget_settings, }, assistant_create_params.AssistantCreateParams, @@ -1221,6 +1432,7 @@ async def update( *, a2a_agents: Iterable[AssistantA2AAgentParam] | Omit = omit, conversation_flow: ConversationFlowReqParam | Omit = omit, + delegation_settings: DelegationSettingsParam | Omit = omit, description: str | Omit = omit, dynamic_variables: Dict[str, object] | Omit = omit, dynamic_variables_webhook_timeout_ms: int | Omit = omit, @@ -1249,6 +1461,7 @@ async def update( transcription: TranscriptionSettingsParam | Omit = omit, version_name: str | Omit = omit, voice_settings: InferenceEmbeddingVoiceSettingsParam | Omit = omit, + websocket_settings: WebsocketSettingsParam | Omit = omit, widget_settings: WidgetSettingsParam | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -1279,6 +1492,14 @@ async def update( unique node/edge IDs, that `start_node_id` references a real node, and that every edge's endpoints reference real nodes. + delegation_settings: Splits the conversation between a frontend model that talks to the caller and a + backend model that does the work. On the GPT-Live route the frontend model + cannot call tools at all — when it needs something done it raises a delegation + and waits. On the chat completion route the frontend keeps a single `delegate` + tool that returns immediately, so the conversation carries on while the backend + works. Either way the backend's answer is spoken as commentary or kept as silent + context, depending on `speak_results`. Beta feature. + dynamic_variables: Map of dynamic variables and their default values dynamic_variables_webhook_timeout_ms: Timeout in milliseconds for the dynamic variables webhook. Must be between 1 and @@ -1366,6 +1587,12 @@ async def update( version_name: Human-readable name for the assistant version. + websocket_settings: Streams conversation and telephony events to a WebSocket server you host, and + accepts messages injected back into the conversation. Telnyx opens the + connection as a client, once per conversation. Delivery is best effort + throughout: while the connection is down events are dropped rather than queued, + and no socket failure is ever allowed to affect the call. Beta feature. + widget_settings: Configuration settings for the assistant's web widget. extra_headers: Send extra headers @@ -1384,6 +1611,7 @@ async def update( { "a2a_agents": a2a_agents, "conversation_flow": conversation_flow, + "delegation_settings": delegation_settings, "description": description, "dynamic_variables": dynamic_variables, "dynamic_variables_webhook_timeout_ms": dynamic_variables_webhook_timeout_ms, @@ -1412,6 +1640,7 @@ async def update( "transcription": transcription, "version_name": version_name, "voice_settings": voice_settings, + "websocket_settings": websocket_settings, "widget_settings": widget_settings, }, assistant_update_params.AssistantUpdateParams, @@ -1445,6 +1674,7 @@ async def delete( self, assistant_id: str, *, + hard_delete: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -1455,7 +1685,24 @@ async def delete( """ Delete an AI Assistant by `assistant_id`. + By default this performs a soft delete: the assistant moves to the Recently + Deleted list and stays restorable for 30 days, after which it is permanently + deleted automatically. The assistant's versions and TeXML application are + preserved during the retention window. + + Pass `hard_delete=true` to skip the retention window and permanently delete the + assistant immediately. A hard delete erases the assistant and all of its + versions, and deletes its TeXML application unless phone numbers are still + assigned to it. It does not delete conversations, recordings, shared tools the + assistant referenced, or knowledge-base embeddings. + + Deletion fails with `400` if other assistants reference this one through a + handoff tool or a conversation-flow edge — remove those references first. + Args: + hard_delete: Permanently delete the assistant immediately instead of soft-deleting it to the + Recently Deleted list, where it stays restorable for 30 days. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -1469,7 +1716,13 @@ async def delete( return await self._delete( path_template("/ai/assistants/{assistant_id}", assistant_id=assistant_id), options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform( + {"hard_delete": hard_delete}, assistant_delete_params.AssistantDeleteParams + ), ), cast_to=AssistantDeleteResponse, ) @@ -1663,6 +1916,43 @@ async def imports( cast_to=AssistantsList, ) + async def restore( + self, + assistant_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> InferenceEmbedding: + """ + Restore a soft-deleted assistant from the Recently Deleted list. + + The assistant becomes fully active again with its versions and TeXML application + as they were at deletion time. Restoring does not re-enable numbers or + connections that were released separately after the deletion. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not assistant_id: + raise ValueError(f"Expected a non-empty value for `assistant_id` but received {assistant_id!r}") + return await self._post( + path_template("/ai/assistants/{assistant_id}/restore", assistant_id=assistant_id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=InferenceEmbedding, + ) + async def send_sms( self, assistant_id: str, @@ -1724,6 +2014,81 @@ async def send_sms( cast_to=AssistantSendSMSResponse, ) + async def whatsapp( + self, + assistant_id: str, + *, + content: str, + from_: str, + to: str, + conversation_metadata: Dict[str, Union[str, int, bool]] | Omit = omit, + idempotency_key: str | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> AssistantWhatsappResponse: + """Start a WhatsApp conversation with a customer from the business side. + + This + endpoint: + + 1. Validates that `from` is a WhatsApp number on your account whose messaging + profile has this assistant configured + 2. Creates a new `whatsapp_chat` conversation with the provided metadata + 3. Asks the assistant to pick one of its approved WhatsApp templates and fill + its variables from `content` + 4. Sends the template from `from` to `to` + 5. Returns the conversation ID and the message ID + + When the customer replies, the reply is routed to the same conversation and the + assistant answers within the 24-hour customer service window. The assistant + needs a `whatsapp_template` tool with at least one approved template, data + retention enabled and PII redaction disabled. + + Args: + content: Instruction for the assistant, including the values for the template variables, + e.g. `Send the login verification code 482913 to the customer.` + + from_: WhatsApp number on your account to send from, in E.164 format. Its messaging + profile must have this assistant configured. + + to: Customer to message, as an E.164 phone number or a WhatsApp business-scoped user + ID (BSUID). + + conversation_metadata: Metadata stored on the conversation. Keys starting with `telnyx_` and the + `assistant_id` key are reserved. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not assistant_id: + raise ValueError(f"Expected a non-empty value for `assistant_id` but received {assistant_id!r}") + extra_headers = {**strip_not_given({"Idempotency-Key": idempotency_key}), **(extra_headers or {})} + return await self._post( + path_template("/ai/assistants/{assistant_id}/chat/whatsapp", assistant_id=assistant_id), + body=await async_maybe_transform( + { + "content": content, + "from_": from_, + "to": to, + "conversation_metadata": conversation_metadata, + }, + assistant_whatsapp_params.AssistantWhatsappParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=AssistantWhatsappResponse, + ) + class AssistantsResourceWithRawResponse: def __init__(self, assistants: AssistantsResource) -> None: @@ -1756,9 +2121,15 @@ def __init__(self, assistants: AssistantsResource) -> None: self.imports = to_raw_response_wrapper( assistants.imports, ) + self.restore = to_raw_response_wrapper( + assistants.restore, + ) self.send_sms = to_raw_response_wrapper( assistants.send_sms, ) + self.whatsapp = to_raw_response_wrapper( + assistants.whatsapp, + ) @cached_property def tests(self) -> TestsResourceWithRawResponse: @@ -1795,6 +2166,11 @@ def instructions(self) -> InstructionsResourceWithRawResponse: """Configure AI assistant specifications""" return InstructionsResourceWithRawResponse(self._assistants.instructions) + @cached_property + def deleted(self) -> DeletedResourceWithRawResponse: + """Configure AI assistant specifications""" + return DeletedResourceWithRawResponse(self._assistants.deleted) + class AsyncAssistantsResourceWithRawResponse: def __init__(self, assistants: AsyncAssistantsResource) -> None: @@ -1827,9 +2203,15 @@ def __init__(self, assistants: AsyncAssistantsResource) -> None: self.imports = async_to_raw_response_wrapper( assistants.imports, ) + self.restore = async_to_raw_response_wrapper( + assistants.restore, + ) self.send_sms = async_to_raw_response_wrapper( assistants.send_sms, ) + self.whatsapp = async_to_raw_response_wrapper( + assistants.whatsapp, + ) @cached_property def tests(self) -> AsyncTestsResourceWithRawResponse: @@ -1866,6 +2248,11 @@ def instructions(self) -> AsyncInstructionsResourceWithRawResponse: """Configure AI assistant specifications""" return AsyncInstructionsResourceWithRawResponse(self._assistants.instructions) + @cached_property + def deleted(self) -> AsyncDeletedResourceWithRawResponse: + """Configure AI assistant specifications""" + return AsyncDeletedResourceWithRawResponse(self._assistants.deleted) + class AssistantsResourceWithStreamingResponse: def __init__(self, assistants: AssistantsResource) -> None: @@ -1898,9 +2285,15 @@ def __init__(self, assistants: AssistantsResource) -> None: self.imports = to_streamed_response_wrapper( assistants.imports, ) + self.restore = to_streamed_response_wrapper( + assistants.restore, + ) self.send_sms = to_streamed_response_wrapper( assistants.send_sms, ) + self.whatsapp = to_streamed_response_wrapper( + assistants.whatsapp, + ) @cached_property def tests(self) -> TestsResourceWithStreamingResponse: @@ -1937,6 +2330,11 @@ def instructions(self) -> InstructionsResourceWithStreamingResponse: """Configure AI assistant specifications""" return InstructionsResourceWithStreamingResponse(self._assistants.instructions) + @cached_property + def deleted(self) -> DeletedResourceWithStreamingResponse: + """Configure AI assistant specifications""" + return DeletedResourceWithStreamingResponse(self._assistants.deleted) + class AsyncAssistantsResourceWithStreamingResponse: def __init__(self, assistants: AsyncAssistantsResource) -> None: @@ -1969,9 +2367,15 @@ def __init__(self, assistants: AsyncAssistantsResource) -> None: self.imports = async_to_streamed_response_wrapper( assistants.imports, ) + self.restore = async_to_streamed_response_wrapper( + assistants.restore, + ) self.send_sms = async_to_streamed_response_wrapper( assistants.send_sms, ) + self.whatsapp = async_to_streamed_response_wrapper( + assistants.whatsapp, + ) @cached_property def tests(self) -> AsyncTestsResourceWithStreamingResponse: @@ -2007,3 +2411,8 @@ def tags(self) -> AsyncTagsResourceWithStreamingResponse: def instructions(self) -> AsyncInstructionsResourceWithStreamingResponse: """Configure AI assistant specifications""" return AsyncInstructionsResourceWithStreamingResponse(self._assistants.instructions) + + @cached_property + def deleted(self) -> AsyncDeletedResourceWithStreamingResponse: + """Configure AI assistant specifications""" + return AsyncDeletedResourceWithStreamingResponse(self._assistants.deleted) diff --git a/src/telnyx/resources/ai/assistants/deleted.py b/src/telnyx/resources/ai/assistants/deleted.py new file mode 100644 index 000000000..78045594c --- /dev/null +++ b/src/telnyx/resources/ai/assistants/deleted.py @@ -0,0 +1,288 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import httpx + +from ...._types import Body, Omit, Query, Headers, NotGiven, omit, not_given +from ...._utils import path_template, maybe_transform +from ...._compat import cached_property +from ...._resource import SyncAPIResource, AsyncAPIResource +from ...._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ....pagination import SyncDefaultFlatPagination, AsyncDefaultFlatPagination +from ...._base_client import AsyncPaginator, make_request_options +from ....types.ai.assistants import deleted_list_params +from ....types.ai.assistants.deleted_assistant import DeletedAssistant + +__all__ = ["DeletedResource", "AsyncDeletedResource"] + + +class DeletedResource(SyncAPIResource): + """Configure AI assistant specifications""" + + @cached_property + def with_raw_response(self) -> DeletedResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/team-telnyx/telnyx-python#accessing-raw-response-data-eg-headers + """ + return DeletedResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> DeletedResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/team-telnyx/telnyx-python#with_streaming_response + """ + return DeletedResourceWithStreamingResponse(self) + + def list( + self, + *, + page_number: int | Omit = omit, + page_size: int | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> SyncDefaultFlatPagination[DeletedAssistant]: + """ + List the organization's soft-deleted assistants in the Recently Deleted list. + + Each entry includes `deleted_at` and `permanently_deleted_at`, the point after + which the assistant is erased automatically and can no longer be restored. + + Args: + page_number: Page number to retrieve (1-based). + + page_size: Number of items to return per page. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._get_api_list( + "/ai/assistants/deleted", + page=SyncDefaultFlatPagination[DeletedAssistant], + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "page_number": page_number, + "page_size": page_size, + }, + deleted_list_params.DeletedListParams, + ), + ), + model=DeletedAssistant, + ) + + def get( + self, + assistant_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> DeletedAssistant: + """ + Retrieve a soft-deleted assistant from the Recently Deleted list by + `assistant_id`, including its `deleted_at` and `permanently_deleted_at` + timestamps. This is a read-only view; the assistant cannot be modified while it + remains deleted. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not assistant_id: + raise ValueError(f"Expected a non-empty value for `assistant_id` but received {assistant_id!r}") + return self._get( + path_template("/ai/assistants/{assistant_id}/deleted", assistant_id=assistant_id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=DeletedAssistant, + ) + + +class AsyncDeletedResource(AsyncAPIResource): + """Configure AI assistant specifications""" + + @cached_property + def with_raw_response(self) -> AsyncDeletedResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/team-telnyx/telnyx-python#accessing-raw-response-data-eg-headers + """ + return AsyncDeletedResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncDeletedResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/team-telnyx/telnyx-python#with_streaming_response + """ + return AsyncDeletedResourceWithStreamingResponse(self) + + def list( + self, + *, + page_number: int | Omit = omit, + page_size: int | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> AsyncPaginator[DeletedAssistant, AsyncDefaultFlatPagination[DeletedAssistant]]: + """ + List the organization's soft-deleted assistants in the Recently Deleted list. + + Each entry includes `deleted_at` and `permanently_deleted_at`, the point after + which the assistant is erased automatically and can no longer be restored. + + Args: + page_number: Page number to retrieve (1-based). + + page_size: Number of items to return per page. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._get_api_list( + "/ai/assistants/deleted", + page=AsyncDefaultFlatPagination[DeletedAssistant], + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "page_number": page_number, + "page_size": page_size, + }, + deleted_list_params.DeletedListParams, + ), + ), + model=DeletedAssistant, + ) + + async def get( + self, + assistant_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> DeletedAssistant: + """ + Retrieve a soft-deleted assistant from the Recently Deleted list by + `assistant_id`, including its `deleted_at` and `permanently_deleted_at` + timestamps. This is a read-only view; the assistant cannot be modified while it + remains deleted. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not assistant_id: + raise ValueError(f"Expected a non-empty value for `assistant_id` but received {assistant_id!r}") + return await self._get( + path_template("/ai/assistants/{assistant_id}/deleted", assistant_id=assistant_id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=DeletedAssistant, + ) + + +class DeletedResourceWithRawResponse: + def __init__(self, deleted: DeletedResource) -> None: + self._deleted = deleted + + self.list = to_raw_response_wrapper( + deleted.list, + ) + self.get = to_raw_response_wrapper( + deleted.get, + ) + + +class AsyncDeletedResourceWithRawResponse: + def __init__(self, deleted: AsyncDeletedResource) -> None: + self._deleted = deleted + + self.list = async_to_raw_response_wrapper( + deleted.list, + ) + self.get = async_to_raw_response_wrapper( + deleted.get, + ) + + +class DeletedResourceWithStreamingResponse: + def __init__(self, deleted: DeletedResource) -> None: + self._deleted = deleted + + self.list = to_streamed_response_wrapper( + deleted.list, + ) + self.get = to_streamed_response_wrapper( + deleted.get, + ) + + +class AsyncDeletedResourceWithStreamingResponse: + def __init__(self, deleted: AsyncDeletedResource) -> None: + self._deleted = deleted + + self.list = async_to_streamed_response_wrapper( + deleted.list, + ) + self.get = async_to_streamed_response_wrapper( + deleted.get, + ) diff --git a/src/telnyx/resources/ai/assistants/versions.py b/src/telnyx/resources/ai/assistants/versions.py index cbe091a4e..423eed487 100644 --- a/src/telnyx/resources/ai/assistants/versions.py +++ b/src/telnyx/resources/ai/assistants/versions.py @@ -29,6 +29,8 @@ from ....types.ai.observability_req_param import ObservabilityReqParam from ....types.ai.messaging_settings_param import MessagingSettingsParam from ....types.ai.telephony_settings_param import TelephonySettingsParam +from ....types.ai.websocket_settings_param import WebsocketSettingsParam +from ....types.ai.delegation_settings_param import DelegationSettingsParam from ....types.ai.fallback_config_req_param import FallbackConfigReqParam from ....types.ai.assistant_a2_a_agent_param import AssistantA2AAgentParam from ....types.ai.assistant_mcp_server_param import AssistantMcpServerParam @@ -118,6 +120,7 @@ def update( assistant_id: str, a2a_agents: Iterable[AssistantA2AAgentParam] | Omit = omit, conversation_flow: ConversationFlowReqParam | Omit = omit, + delegation_settings: DelegationSettingsParam | Omit = omit, description: str | Omit = omit, dynamic_variables: Dict[str, object] | Omit = omit, dynamic_variables_webhook_timeout_ms: int | Omit = omit, @@ -145,6 +148,7 @@ def update( transcription: TranscriptionSettingsParam | Omit = omit, version_name: str | Omit = omit, voice_settings: InferenceEmbeddingVoiceSettingsParam | Omit = omit, + websocket_settings: WebsocketSettingsParam | Omit = omit, widget_settings: WidgetSettingsParam | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -175,6 +179,14 @@ def update( unique node/edge IDs, that `start_node_id` references a real node, and that every edge's endpoints reference real nodes. + delegation_settings: Splits the conversation between a frontend model that talks to the caller and a + backend model that does the work. On the GPT-Live route the frontend model + cannot call tools at all — when it needs something done it raises a delegation + and waits. On the chat completion route the frontend keeps a single `delegate` + tool that returns immediately, so the conversation carries on while the backend + works. Either way the backend's answer is spoken as commentary or kept as silent + context, depending on `speak_results`. Beta feature. + dynamic_variables: Map of dynamic variables and their default values dynamic_variables_webhook_timeout_ms: Timeout in milliseconds for the dynamic variables webhook. Must be between 1 and @@ -259,6 +271,12 @@ def update( version_name: Human-readable name for the assistant version. + websocket_settings: Streams conversation and telephony events to a WebSocket server you host, and + accepts messages injected back into the conversation. Telnyx opens the + connection as a client, once per conversation. Delivery is best effort + throughout: while the connection is down events are dropped rather than queued, + and no socket failure is ever allowed to affect the call. Beta feature. + widget_settings: Configuration settings for the assistant's web widget. extra_headers: Send extra headers @@ -281,6 +299,7 @@ def update( { "a2a_agents": a2a_agents, "conversation_flow": conversation_flow, + "delegation_settings": delegation_settings, "description": description, "dynamic_variables": dynamic_variables, "dynamic_variables_webhook_timeout_ms": dynamic_variables_webhook_timeout_ms, @@ -308,6 +327,7 @@ def update( "transcription": transcription, "version_name": version_name, "voice_settings": voice_settings, + "websocket_settings": websocket_settings, "widget_settings": widget_settings, }, version_update_params.VersionUpdateParams, @@ -512,6 +532,7 @@ async def update( assistant_id: str, a2a_agents: Iterable[AssistantA2AAgentParam] | Omit = omit, conversation_flow: ConversationFlowReqParam | Omit = omit, + delegation_settings: DelegationSettingsParam | Omit = omit, description: str | Omit = omit, dynamic_variables: Dict[str, object] | Omit = omit, dynamic_variables_webhook_timeout_ms: int | Omit = omit, @@ -539,6 +560,7 @@ async def update( transcription: TranscriptionSettingsParam | Omit = omit, version_name: str | Omit = omit, voice_settings: InferenceEmbeddingVoiceSettingsParam | Omit = omit, + websocket_settings: WebsocketSettingsParam | Omit = omit, widget_settings: WidgetSettingsParam | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -569,6 +591,14 @@ async def update( unique node/edge IDs, that `start_node_id` references a real node, and that every edge's endpoints reference real nodes. + delegation_settings: Splits the conversation between a frontend model that talks to the caller and a + backend model that does the work. On the GPT-Live route the frontend model + cannot call tools at all — when it needs something done it raises a delegation + and waits. On the chat completion route the frontend keeps a single `delegate` + tool that returns immediately, so the conversation carries on while the backend + works. Either way the backend's answer is spoken as commentary or kept as silent + context, depending on `speak_results`. Beta feature. + dynamic_variables: Map of dynamic variables and their default values dynamic_variables_webhook_timeout_ms: Timeout in milliseconds for the dynamic variables webhook. Must be between 1 and @@ -653,6 +683,12 @@ async def update( version_name: Human-readable name for the assistant version. + websocket_settings: Streams conversation and telephony events to a WebSocket server you host, and + accepts messages injected back into the conversation. Telnyx opens the + connection as a client, once per conversation. Delivery is best effort + throughout: while the connection is down events are dropped rather than queued, + and no socket failure is ever allowed to affect the call. Beta feature. + widget_settings: Configuration settings for the assistant's web widget. extra_headers: Send extra headers @@ -675,6 +711,7 @@ async def update( { "a2a_agents": a2a_agents, "conversation_flow": conversation_flow, + "delegation_settings": delegation_settings, "description": description, "dynamic_variables": dynamic_variables, "dynamic_variables_webhook_timeout_ms": dynamic_variables_webhook_timeout_ms, @@ -702,6 +739,7 @@ async def update( "transcription": transcription, "version_name": version_name, "voice_settings": voice_settings, + "websocket_settings": websocket_settings, "widget_settings": widget_settings, }, version_update_params.VersionUpdateParams, diff --git a/src/telnyx/resources/ai/memory/memory.py b/src/telnyx/resources/ai/memory/memory.py index 92bcab36b..36eddf88d 100644 --- a/src/telnyx/resources/ai/memory/memory.py +++ b/src/telnyx/resources/ai/memory/memory.py @@ -19,7 +19,6 @@ class MemoryResource(SyncAPIResource): @cached_property def namespaces(self) -> NamespacesResource: - """Whether a write has finished.""" return NamespacesResource(self._client) @cached_property @@ -45,7 +44,6 @@ def with_streaming_response(self) -> MemoryResourceWithStreamingResponse: class AsyncMemoryResource(AsyncAPIResource): @cached_property def namespaces(self) -> AsyncNamespacesResource: - """Whether a write has finished.""" return AsyncNamespacesResource(self._client) @cached_property @@ -74,7 +72,6 @@ def __init__(self, memory: MemoryResource) -> None: @cached_property def namespaces(self) -> NamespacesResourceWithRawResponse: - """Whether a write has finished.""" return NamespacesResourceWithRawResponse(self._memory.namespaces) @@ -84,7 +81,6 @@ def __init__(self, memory: AsyncMemoryResource) -> None: @cached_property def namespaces(self) -> AsyncNamespacesResourceWithRawResponse: - """Whether a write has finished.""" return AsyncNamespacesResourceWithRawResponse(self._memory.namespaces) @@ -94,7 +90,6 @@ def __init__(self, memory: MemoryResource) -> None: @cached_property def namespaces(self) -> NamespacesResourceWithStreamingResponse: - """Whether a write has finished.""" return NamespacesResourceWithStreamingResponse(self._memory.namespaces) @@ -104,5 +99,4 @@ def __init__(self, memory: AsyncMemoryResource) -> None: @cached_property def namespaces(self) -> AsyncNamespacesResourceWithStreamingResponse: - """Whether a write has finished.""" return AsyncNamespacesResourceWithStreamingResponse(self._memory.namespaces) diff --git a/src/telnyx/resources/ai/memory/namespaces/namespaces.py b/src/telnyx/resources/ai/memory/namespaces/namespaces.py index ad927a82e..f3409462d 100644 --- a/src/telnyx/resources/ai/memory/namespaces/namespaces.py +++ b/src/telnyx/resources/ai/memory/namespaces/namespaces.py @@ -12,8 +12,8 @@ SettingsResourceWithStreamingResponse, AsyncSettingsResourceWithStreamingResponse, ) -from ....._types import Body, Query, Headers, NotGiven, not_given -from ....._utils import path_template +from ....._types import Body, Query, Headers, NoneType, NotGiven, not_given +from ....._utils import path_template, maybe_transform, async_maybe_transform from ....._compat import cached_property from ....._resource import SyncAPIResource, AsyncAPIResource from ....._response import ( @@ -31,14 +31,15 @@ ProfilesResourceWithStreamingResponse, AsyncProfilesResourceWithStreamingResponse, ) +from .....types.ai.memory import namespace_create_params +from .....types.ai.memory.namespace_list_response import NamespaceListResponse +from .....types.ai.memory.namespace_create_response import NamespaceCreateResponse from .....types.ai.memory.namespace_retrieve_response import NamespaceRetrieveResponse __all__ = ["NamespacesResource", "AsyncNamespacesResource"] class NamespacesResource(SyncAPIResource): - """Whether a write has finished.""" - @cached_property def profiles(self) -> ProfilesResource: return ProfilesResource(self._client) @@ -67,6 +68,42 @@ def with_streaming_response(self) -> NamespacesResourceWithStreamingResponse: """ return NamespacesResourceWithStreamingResponse(self) + def create( + self, + *, + name: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> NamespaceCreateResponse: + """Create a namespace. + + An organization can have at most five, `default` among them + — a sixth returns `403`. + + Args: + name: A name for the new namespace, unique within your organization. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._post( + "/ai/memory/namespaces", + body=maybe_transform({"name": name}, namespace_create_params.NamespaceCreateParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NamespaceCreateResponse, + ) + def retrieve( self, operation_id: str, @@ -110,10 +147,65 @@ def retrieve( cast_to=NamespaceRetrieveResponse, ) + def list( + self, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> NamespaceListResponse: + """Every namespace in your organization, `default` among them.""" + return self._get( + "/ai/memory/namespaces", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NamespaceListResponse, + ) + + def delete( + self, + namespace: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> None: + """Delete a namespace and every profile and memory in it. -class AsyncNamespacesResource(AsyncAPIResource): - """Whether a write has finished.""" + `default` cannot be + deleted. This cannot be undone. + + Args: + namespace: The namespace to delete. `default` cannot be deleted. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not namespace: + raise ValueError(f"Expected a non-empty value for `namespace` but received {namespace!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return self._delete( + path_template("/ai/memory/namespaces/{namespace}", namespace=namespace), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + +class AsyncNamespacesResource(AsyncAPIResource): @cached_property def profiles(self) -> AsyncProfilesResource: return AsyncProfilesResource(self._client) @@ -142,6 +234,42 @@ def with_streaming_response(self) -> AsyncNamespacesResourceWithStreamingRespons """ return AsyncNamespacesResourceWithStreamingResponse(self) + async def create( + self, + *, + name: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> NamespaceCreateResponse: + """Create a namespace. + + An organization can have at most five, `default` among them + — a sixth returns `403`. + + Args: + name: A name for the new namespace, unique within your organization. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._post( + "/ai/memory/namespaces", + body=await async_maybe_transform({"name": name}, namespace_create_params.NamespaceCreateParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NamespaceCreateResponse, + ) + async def retrieve( self, operation_id: str, @@ -185,14 +313,80 @@ async def retrieve( cast_to=NamespaceRetrieveResponse, ) + async def list( + self, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> NamespaceListResponse: + """Every namespace in your organization, `default` among them.""" + return await self._get( + "/ai/memory/namespaces", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NamespaceListResponse, + ) + + async def delete( + self, + namespace: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> None: + """Delete a namespace and every profile and memory in it. + + `default` cannot be + deleted. This cannot be undone. + + Args: + namespace: The namespace to delete. `default` cannot be deleted. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not namespace: + raise ValueError(f"Expected a non-empty value for `namespace` but received {namespace!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + return await self._delete( + path_template("/ai/memory/namespaces/{namespace}", namespace=namespace), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + class NamespacesResourceWithRawResponse: def __init__(self, namespaces: NamespacesResource) -> None: self._namespaces = namespaces + self.create = to_raw_response_wrapper( + namespaces.create, + ) self.retrieve = to_raw_response_wrapper( namespaces.retrieve, ) + self.list = to_raw_response_wrapper( + namespaces.list, + ) + self.delete = to_raw_response_wrapper( + namespaces.delete, + ) @cached_property def profiles(self) -> ProfilesResourceWithRawResponse: @@ -208,9 +402,18 @@ class AsyncNamespacesResourceWithRawResponse: def __init__(self, namespaces: AsyncNamespacesResource) -> None: self._namespaces = namespaces + self.create = async_to_raw_response_wrapper( + namespaces.create, + ) self.retrieve = async_to_raw_response_wrapper( namespaces.retrieve, ) + self.list = async_to_raw_response_wrapper( + namespaces.list, + ) + self.delete = async_to_raw_response_wrapper( + namespaces.delete, + ) @cached_property def profiles(self) -> AsyncProfilesResourceWithRawResponse: @@ -226,9 +429,18 @@ class NamespacesResourceWithStreamingResponse: def __init__(self, namespaces: NamespacesResource) -> None: self._namespaces = namespaces + self.create = to_streamed_response_wrapper( + namespaces.create, + ) self.retrieve = to_streamed_response_wrapper( namespaces.retrieve, ) + self.list = to_streamed_response_wrapper( + namespaces.list, + ) + self.delete = to_streamed_response_wrapper( + namespaces.delete, + ) @cached_property def profiles(self) -> ProfilesResourceWithStreamingResponse: @@ -244,9 +456,18 @@ class AsyncNamespacesResourceWithStreamingResponse: def __init__(self, namespaces: AsyncNamespacesResource) -> None: self._namespaces = namespaces + self.create = async_to_streamed_response_wrapper( + namespaces.create, + ) self.retrieve = async_to_streamed_response_wrapper( namespaces.retrieve, ) + self.list = async_to_streamed_response_wrapper( + namespaces.list, + ) + self.delete = async_to_streamed_response_wrapper( + namespaces.delete, + ) @cached_property def profiles(self) -> AsyncProfilesResourceWithStreamingResponse: diff --git a/src/telnyx/resources/ai/openai/chat.py b/src/telnyx/resources/ai/openai/chat.py index 5de789c19..8d1467650 100644 --- a/src/telnyx/resources/ai/openai/chat.py +++ b/src/telnyx/resources/ai/openai/chat.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import Union, Iterable +from typing import Union, Iterable, Optional from typing_extensions import Literal import httpx @@ -55,7 +55,7 @@ def create_completion( frequency_penalty: float | Omit = omit, length_penalty: float | Omit = omit, logprobs: bool | Omit = omit, - max_tokens: int | Omit = omit, + max_tokens: Optional[int] | Omit = omit, min_p: float | Omit = omit, mode: Literal["preferred", "strict"] | Omit = omit, model: str | Omit = omit, @@ -115,7 +115,12 @@ def create_completion( returns the log probabilities of each output token returned in the `content` of `message`. - max_tokens: Maximum number of completion tokens the model should generate. + max_tokens: Maximum number of completion (output) tokens the model may generate per request. + Defaults to 8192 when omitted or `null`. Set a higher value to allow longer + completions. The model's `max_completion_tokens` metadata (see + `GET /ai/models`), when set, caps both the default and any larger explicit + value. Reasoning models consume this budget across reasoning and answer tokens + combined. min_p: This is an alternative to `top_p` that [many prefer](https://github.com/huggingface/transformers/issues/27670). Must be @@ -264,7 +269,7 @@ async def create_completion( frequency_penalty: float | Omit = omit, length_penalty: float | Omit = omit, logprobs: bool | Omit = omit, - max_tokens: int | Omit = omit, + max_tokens: Optional[int] | Omit = omit, min_p: float | Omit = omit, mode: Literal["preferred", "strict"] | Omit = omit, model: str | Omit = omit, @@ -324,7 +329,12 @@ async def create_completion( returns the log probabilities of each output token returned in the `content` of `message`. - max_tokens: Maximum number of completion tokens the model should generate. + max_tokens: Maximum number of completion (output) tokens the model may generate per request. + Defaults to 8192 when omitted or `null`. Set a higher value to allow longer + completions. The model's `max_completion_tokens` metadata (see + `GET /ai/models`), when set, caps both the default and any larger explicit + value. Reasoning models consume this budget across reasoning and answer tokens + combined. min_p: This is an alternative to `top_p` that [many prefer](https://github.com/huggingface/transformers/issues/27670). Must be diff --git a/src/telnyx/resources/ai/tools.py b/src/telnyx/resources/ai/tools.py index 8d7886550..c7024e343 100644 --- a/src/telnyx/resources/ai/tools.py +++ b/src/telnyx/resources/ai/tools.py @@ -6,7 +6,7 @@ import httpx -from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given +from ..._types import Body, Omit, Query, Headers, NoneType, NotGiven, omit, not_given from ..._utils import path_template, maybe_transform, strip_not_given, async_maybe_transform from ..._compat import cached_property from ...types.ai import ( @@ -273,7 +273,7 @@ def delete( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> object: + ) -> None: """ Permanently deletes the specified custom AI tool from your account. @@ -288,12 +288,13 @@ def delete( """ if not tool_id: raise ValueError(f"Expected a non-empty value for `tool_id` but received {tool_id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} return self._delete( path_template("/ai/tools/{tool_id}", tool_id=tool_id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=object, + cast_to=NoneType, ) @@ -540,7 +541,7 @@ async def delete( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> object: + ) -> None: """ Permanently deletes the specified custom AI tool from your account. @@ -555,12 +556,13 @@ async def delete( """ if not tool_id: raise ValueError(f"Expected a non-empty value for `tool_id` but received {tool_id!r}") + extra_headers = {"Accept": "*/*", **(extra_headers or {})} return await self._delete( path_template("/ai/tools/{tool_id}", tool_id=tool_id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=object, + cast_to=NoneType, ) diff --git a/src/telnyx/resources/calls/actions.py b/src/telnyx/resources/calls/actions.py index 96b99fdfc..a5bd4a883 100644 --- a/src/telnyx/resources/calls/actions.py +++ b/src/telnyx/resources/calls/actions.py @@ -266,9 +266,33 @@ def answer( You must issue this command before executing subsequent commands on an incoming call. + To answer with an AI assistant, include `assistant.id` and any per-call + overrides in the `assistant` object. Telnyx attempts to warm up the assistant + before answering the call, then starts the assistant automatically when the call + is answered. Do not also send `ai_assistant_start` for this flow. The HTTP + success response can arrive before the call is answered; use the `call.answered` + webhook to track the answer. If warm-up fails, Telnyx falls back to starting the + assistant after answering. + + When `assistant.id` is supplied, obtain the conversation ID from + `data.payload.conversation_id` in the + [call.conversation.created](/api-reference/callbacks/call-conversation-created) + webhook and correlate it using `data.payload.call_control_id`. The `answer` HTTP + response does not include `conversation_id`. The created event is emitted during + assistant startup and does not indicate that the assistant is ready to speak. + + Set the assistant voice with `assistant.voice_settings.voice` and speech-to-text + settings with `assistant.transcription`. You can reuse one stored assistant with + different per-call settings. Warm-up prepares assistant configuration and + dependencies; it does not wait for the greeting audio to be ready or guarantee + zero silence after answer. A plain `answer` followed by `ai_assistant_start` + performs assistant startup after the call has already been answered. + **Expected Webhooks:** - `call.answered` + - `call.conversation.created` when the requested assistant conversation is + created - `call.hold` and `call.unhold` if the call is held/unheld - `call.deepfake_detection.result` if `deepfake_detection` was enabled - `call.deepfake_detection.error` if `deepfake_detection` was enabled and an @@ -280,9 +304,11 @@ def answer( include a `recording_id` field. Args: - assistant: AI Assistant configuration. All fields except `id` are optional — the - assistant's stored configuration will be used as fallback for any omitted - fields. + assistant: AI Assistant configuration and per-call overrides. All fields except `id` are + optional. Omitted assistant fields use the stored configuration. Supplied + `voice_settings` and `transcription` objects replace their stored objects rather + than merging individual settings; include every setting you want to retain. + `dynamic_variables` are merged, with request values taking precedence. billing_group_id: Use this field to set the Billing Group ID for the call. Must be a valid and existing Billing Group ID. @@ -358,7 +384,9 @@ def answer( stream_url: The destination WebSocket address where the stream is going to be delivered. - transcription: Enable transcription upon call answer. The default value is false. + transcription: Enable standalone call transcription upon call answer. The default value is + false. Configure this feature with `transcription_config`. To configure speech + recognition for an AI assistant, use `assistant.transcription` instead. webhook_retries_policies: A map of event types to retry policies. Each retry policy contains an array of `retries_ms` specifying the delays between retry attempts in milliseconds. @@ -824,6 +852,8 @@ def gather_using_ai( **Expected Webhooks:** + - [`call.conversation.created`](/api-reference/callbacks/call-conversation-created) + includes `conversation_id` during startup - `call.ai_gather.ended` - `call.conversation.ended` - `call.ai_gather.partial_results` (if `send_partial_results` is set to `true`) @@ -1736,7 +1766,7 @@ def reject( self, call_control_id: str, *, - cause: Literal["CALL_REJECTED", "USER_BUSY"], + cause: Literal["CALL_REJECTED", "NOT_FOUND", "TEMPORARILY_UNAVAILABLE", "USER_BUSY"], client_state: str | Omit = omit, command_id: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -1754,7 +1784,11 @@ def reject( - `call.hangup` Args: - cause: Cause for call rejection. + cause: + Cause for call rejection. The cause sets the SIP response the caller receives: + `USER_BUSY` sends 486 User Busy, `CALL_REJECTED` sends 603 Decline, `NOT_FOUND` + sends 404 Not Found, and `TEMPORARILY_UNAVAILABLE` sends 480 Temporarily + Unavailable. client_state: Use this field to add state to every subsequent webhook. It must be a valid Base-64 encoded string. @@ -2182,13 +2216,17 @@ def start_ai_assistant( **Expected Webhooks:** + - [`call.conversation.created`](/api-reference/callbacks/call-conversation-created) + includes `conversation_id` during startup - `call.conversation.ended` - `call.conversation_insights.generated` Args: - assistant: AI Assistant configuration. All fields except `id` are optional — the - assistant's stored configuration will be used as fallback for any omitted - fields. + assistant: AI Assistant configuration and per-call overrides. All fields except `id` are + optional. Omitted assistant fields use the stored configuration. Supplied + `voice_settings` and `transcription` objects replace their stored objects rather + than merging individual settings; include every setting you want to retain. + `dynamic_variables` are merged, with request values taking precedence. client_state: Use this field to add state to every subsequent webhook. It must be a valid Base-64 encoded string. @@ -3937,7 +3975,13 @@ def transfer( *, to: str, answering_machine_detection: Literal[ - "premium", "detect", "detect_beep", "detect_words", "greeting_end", "disabled" + "premium", + "premium_ios_call_screening_detection", + "detect", + "detect_beep", + "detect_words", + "greeting_end", + "disabled", ] | Omit = omit, answering_machine_detection_config: action_transfer_params.AnsweringMachineDetectionConfig | Omit = omit, @@ -4006,6 +4050,9 @@ def transfer( `answering_machine_detection=premium` was requested - `call.machine.premium.greeting.ended` if `answering_machine_detection=premium` was requested and a beep was detected + - `call.machine.premium.call_screening.detected` if + `answering_machine_detection=premium_ios_call_screening_detection` was + requested and an Apple Call Screening tone was detected Args: to: The DID or SIP URI to dial out to. For SIP URI destinations, append @@ -4024,12 +4071,22 @@ def transfer( 'greeting_end' or 'detect_words' is used and a 'machine' is detected, you will receive another 'call.machine.greeting.ended' webhook when the answering machine greeting ends with a beep or silence. If `detect_beep` is used, you will only - receive 'call.machine.greeting.ended' if a beep is detected. + receive 'call.machine.greeting.ended' if a beep is detected. If + `answering_machine_detection` is set to `premium_ios_call_screening_detection`, + Premium AMD runs with iOS Call Screening support: after an initial `machine` + result, Telnyx listens for the iOS call-screening prompt to end or for an Apple + Call Screening tone, sends `call.machine.premium.greeting.ended` with + `result=prompt_ended` or `call.machine.premium.call_screening.detected` with + `result=screening` respectively. When the Apple Call Screening tone is detected, + Premium AMD is restarted on the screened call and a + `call.machine.premium.detection.ended` webhook with the post-screening + classification follows. answering_machine_detection_config: Optional configuration parameters to modify 'answering_machine_detection' performance. Only `total_analysis_time_millis` and `greeting_duration_millis` parameters are applicable when `premium` is selected as - answering_machine_detection. + answering_machine_detection. `prompt_end_timeout_millis` is additionally + applicable when `premium_ios_call_screening_detection` is selected. audio_url: The URL of a file to be played back when the transfer destination answers before bridging the call. The URL can point to either a WAV or MP3 file. media_name and @@ -4413,9 +4470,33 @@ async def answer( You must issue this command before executing subsequent commands on an incoming call. + To answer with an AI assistant, include `assistant.id` and any per-call + overrides in the `assistant` object. Telnyx attempts to warm up the assistant + before answering the call, then starts the assistant automatically when the call + is answered. Do not also send `ai_assistant_start` for this flow. The HTTP + success response can arrive before the call is answered; use the `call.answered` + webhook to track the answer. If warm-up fails, Telnyx falls back to starting the + assistant after answering. + + When `assistant.id` is supplied, obtain the conversation ID from + `data.payload.conversation_id` in the + [call.conversation.created](/api-reference/callbacks/call-conversation-created) + webhook and correlate it using `data.payload.call_control_id`. The `answer` HTTP + response does not include `conversation_id`. The created event is emitted during + assistant startup and does not indicate that the assistant is ready to speak. + + Set the assistant voice with `assistant.voice_settings.voice` and speech-to-text + settings with `assistant.transcription`. You can reuse one stored assistant with + different per-call settings. Warm-up prepares assistant configuration and + dependencies; it does not wait for the greeting audio to be ready or guarantee + zero silence after answer. A plain `answer` followed by `ai_assistant_start` + performs assistant startup after the call has already been answered. + **Expected Webhooks:** - `call.answered` + - `call.conversation.created` when the requested assistant conversation is + created - `call.hold` and `call.unhold` if the call is held/unheld - `call.deepfake_detection.result` if `deepfake_detection` was enabled - `call.deepfake_detection.error` if `deepfake_detection` was enabled and an @@ -4427,9 +4508,11 @@ async def answer( include a `recording_id` field. Args: - assistant: AI Assistant configuration. All fields except `id` are optional — the - assistant's stored configuration will be used as fallback for any omitted - fields. + assistant: AI Assistant configuration and per-call overrides. All fields except `id` are + optional. Omitted assistant fields use the stored configuration. Supplied + `voice_settings` and `transcription` objects replace their stored objects rather + than merging individual settings; include every setting you want to retain. + `dynamic_variables` are merged, with request values taking precedence. billing_group_id: Use this field to set the Billing Group ID for the call. Must be a valid and existing Billing Group ID. @@ -4505,7 +4588,9 @@ async def answer( stream_url: The destination WebSocket address where the stream is going to be delivered. - transcription: Enable transcription upon call answer. The default value is false. + transcription: Enable standalone call transcription upon call answer. The default value is + false. Configure this feature with `transcription_config`. To configure speech + recognition for an AI assistant, use `assistant.transcription` instead. webhook_retries_policies: A map of event types to retry policies. Each retry policy contains an array of `retries_ms` specifying the delays between retry attempts in milliseconds. @@ -4971,6 +5056,8 @@ async def gather_using_ai( **Expected Webhooks:** + - [`call.conversation.created`](/api-reference/callbacks/call-conversation-created) + includes `conversation_id` during startup - `call.ai_gather.ended` - `call.conversation.ended` - `call.ai_gather.partial_results` (if `send_partial_results` is set to `true`) @@ -5883,7 +5970,7 @@ async def reject( self, call_control_id: str, *, - cause: Literal["CALL_REJECTED", "USER_BUSY"], + cause: Literal["CALL_REJECTED", "NOT_FOUND", "TEMPORARILY_UNAVAILABLE", "USER_BUSY"], client_state: str | Omit = omit, command_id: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -5901,7 +5988,11 @@ async def reject( - `call.hangup` Args: - cause: Cause for call rejection. + cause: + Cause for call rejection. The cause sets the SIP response the caller receives: + `USER_BUSY` sends 486 User Busy, `CALL_REJECTED` sends 603 Decline, `NOT_FOUND` + sends 404 Not Found, and `TEMPORARILY_UNAVAILABLE` sends 480 Temporarily + Unavailable. client_state: Use this field to add state to every subsequent webhook. It must be a valid Base-64 encoded string. @@ -6329,13 +6420,17 @@ async def start_ai_assistant( **Expected Webhooks:** + - [`call.conversation.created`](/api-reference/callbacks/call-conversation-created) + includes `conversation_id` during startup - `call.conversation.ended` - `call.conversation_insights.generated` Args: - assistant: AI Assistant configuration. All fields except `id` are optional — the - assistant's stored configuration will be used as fallback for any omitted - fields. + assistant: AI Assistant configuration and per-call overrides. All fields except `id` are + optional. Omitted assistant fields use the stored configuration. Supplied + `voice_settings` and `transcription` objects replace their stored objects rather + than merging individual settings; include every setting you want to retain. + `dynamic_variables` are merged, with request values taking precedence. client_state: Use this field to add state to every subsequent webhook. It must be a valid Base-64 encoded string. @@ -8086,7 +8181,13 @@ async def transfer( *, to: str, answering_machine_detection: Literal[ - "premium", "detect", "detect_beep", "detect_words", "greeting_end", "disabled" + "premium", + "premium_ios_call_screening_detection", + "detect", + "detect_beep", + "detect_words", + "greeting_end", + "disabled", ] | Omit = omit, answering_machine_detection_config: action_transfer_params.AnsweringMachineDetectionConfig | Omit = omit, @@ -8155,6 +8256,9 @@ async def transfer( `answering_machine_detection=premium` was requested - `call.machine.premium.greeting.ended` if `answering_machine_detection=premium` was requested and a beep was detected + - `call.machine.premium.call_screening.detected` if + `answering_machine_detection=premium_ios_call_screening_detection` was + requested and an Apple Call Screening tone was detected Args: to: The DID or SIP URI to dial out to. For SIP URI destinations, append @@ -8173,12 +8277,22 @@ async def transfer( 'greeting_end' or 'detect_words' is used and a 'machine' is detected, you will receive another 'call.machine.greeting.ended' webhook when the answering machine greeting ends with a beep or silence. If `detect_beep` is used, you will only - receive 'call.machine.greeting.ended' if a beep is detected. + receive 'call.machine.greeting.ended' if a beep is detected. If + `answering_machine_detection` is set to `premium_ios_call_screening_detection`, + Premium AMD runs with iOS Call Screening support: after an initial `machine` + result, Telnyx listens for the iOS call-screening prompt to end or for an Apple + Call Screening tone, sends `call.machine.premium.greeting.ended` with + `result=prompt_ended` or `call.machine.premium.call_screening.detected` with + `result=screening` respectively. When the Apple Call Screening tone is detected, + Premium AMD is restarted on the screened call and a + `call.machine.premium.detection.ended` webhook with the post-screening + classification follows. answering_machine_detection_config: Optional configuration parameters to modify 'answering_machine_detection' performance. Only `total_analysis_time_millis` and `greeting_duration_millis` parameters are applicable when `premium` is selected as - answering_machine_detection. + answering_machine_detection. `prompt_end_timeout_millis` is additionally + applicable when `premium_ios_call_screening_detection` is selected. audio_url: The URL of a file to be played back when the transfer destination answers before bridging the call. The URL can point to either a WAV or MP3 file. media_name and diff --git a/src/telnyx/resources/calls/calls.py b/src/telnyx/resources/calls/calls.py index d12e0b6d5..33f30b298 100644 --- a/src/telnyx/resources/calls/calls.py +++ b/src/telnyx/resources/calls/calls.py @@ -84,7 +84,13 @@ def dial( from_: str, to: Union[str, SequenceNotStr[str]], answering_machine_detection: Literal[ - "premium", "detect", "detect_beep", "detect_words", "greeting_end", "disabled" + "premium", + "premium_ios_call_screening_detection", + "detect", + "detect_beep", + "detect_words", + "greeting_end", + "disabled", ] | Omit = omit, answering_machine_detection_config: call_dial_params.AnsweringMachineDetectionConfig | Omit = omit, @@ -173,6 +179,9 @@ def dial( `answering_machine_detection=premium` was requested - `call.machine.premium.greeting.ended` if `answering_machine_detection=premium` was requested and a beep was detected + - `call.machine.premium.call_screening.detected` if + `answering_machine_detection=premium_ios_call_screening_detection` was + requested and an Apple Call Screening tone was detected - `call.deepfake_detection.result` if `deepfake_detection` was enabled - `call.deepfake_detection.error` if `deepfake_detection` was enabled and an error occurred @@ -217,16 +226,28 @@ def dial( `greeting_end` or `detect_words` is used and a `machine` is detected, you will receive another `call.machine.greeting.ended` webhook when the answering machine greeting ends with a beep or silence. If `detect_beep` is used, you will only - receive `call.machine.greeting.ended` if a beep is detected. + receive `call.machine.greeting.ended` if a beep is detected. If + `answering_machine_detection` is set to `premium_ios_call_screening_detection`, + Premium AMD runs with iOS Call Screening support: after an initial `machine` + result, Telnyx listens for the iOS call-screening prompt to end or for an Apple + Call Screening tone, sends `call.machine.premium.greeting.ended` with + `result=prompt_ended` or `call.machine.premium.call_screening.detected` with + `result=screening` respectively. When the Apple Call Screening tone is detected, + Premium AMD is restarted on the screened call and a + `call.machine.premium.detection.ended` webhook with the post-screening + classification follows. answering_machine_detection_config: Optional configuration parameters to modify 'answering_machine_detection' performance. Only `total_analysis_time_millis` and `greeting_duration_millis` parameters are applicable when `premium` is selected as - answering_machine_detection. + answering_machine_detection. `prompt_end_timeout_millis` is additionally + applicable when `premium_ios_call_screening_detection` is selected. - assistant: AI Assistant configuration. All fields except `id` are optional — the - assistant's stored configuration will be used as fallback for any omitted - fields. + assistant: AI Assistant configuration and per-call overrides. All fields except `id` are + optional. Omitted assistant fields use the stored configuration. Supplied + `voice_settings` and `transcription` objects replace their stored objects rather + than merging individual settings; include every setting you want to retain. + `dynamic_variables` are merged, with request values taking precedence. audio_url: The URL of a file to be played back to the callee when the call is answered. The URL can point to either a WAV or MP3 file. media_name and audio_url cannot be @@ -582,7 +603,13 @@ async def dial( from_: str, to: Union[str, SequenceNotStr[str]], answering_machine_detection: Literal[ - "premium", "detect", "detect_beep", "detect_words", "greeting_end", "disabled" + "premium", + "premium_ios_call_screening_detection", + "detect", + "detect_beep", + "detect_words", + "greeting_end", + "disabled", ] | Omit = omit, answering_machine_detection_config: call_dial_params.AnsweringMachineDetectionConfig | Omit = omit, @@ -671,6 +698,9 @@ async def dial( `answering_machine_detection=premium` was requested - `call.machine.premium.greeting.ended` if `answering_machine_detection=premium` was requested and a beep was detected + - `call.machine.premium.call_screening.detected` if + `answering_machine_detection=premium_ios_call_screening_detection` was + requested and an Apple Call Screening tone was detected - `call.deepfake_detection.result` if `deepfake_detection` was enabled - `call.deepfake_detection.error` if `deepfake_detection` was enabled and an error occurred @@ -715,16 +745,28 @@ async def dial( `greeting_end` or `detect_words` is used and a `machine` is detected, you will receive another `call.machine.greeting.ended` webhook when the answering machine greeting ends with a beep or silence. If `detect_beep` is used, you will only - receive `call.machine.greeting.ended` if a beep is detected. + receive `call.machine.greeting.ended` if a beep is detected. If + `answering_machine_detection` is set to `premium_ios_call_screening_detection`, + Premium AMD runs with iOS Call Screening support: after an initial `machine` + result, Telnyx listens for the iOS call-screening prompt to end or for an Apple + Call Screening tone, sends `call.machine.premium.greeting.ended` with + `result=prompt_ended` or `call.machine.premium.call_screening.detected` with + `result=screening` respectively. When the Apple Call Screening tone is detected, + Premium AMD is restarted on the screened call and a + `call.machine.premium.detection.ended` webhook with the post-screening + classification follows. answering_machine_detection_config: Optional configuration parameters to modify 'answering_machine_detection' performance. Only `total_analysis_time_millis` and `greeting_duration_millis` parameters are applicable when `premium` is selected as - answering_machine_detection. - - assistant: AI Assistant configuration. All fields except `id` are optional — the - assistant's stored configuration will be used as fallback for any omitted - fields. + answering_machine_detection. `prompt_end_timeout_millis` is additionally + applicable when `premium_ios_call_screening_detection` is selected. + + assistant: AI Assistant configuration and per-call overrides. All fields except `id` are + optional. Omitted assistant fields use the stored configuration. Supplied + `voice_settings` and `transcription` objects replace their stored objects rather + than merging individual settings; include every setting you want to retain. + `dynamic_variables` are merged, with request values taking precedence. audio_url: The URL of a file to be played back to the callee when the call is answered. The URL can point to either a WAV or MP3 file. media_name and audio_url cannot be diff --git a/src/telnyx/resources/dir/dir.py b/src/telnyx/resources/dir/dir.py index b2201c82a..01457f176 100644 --- a/src/telnyx/resources/dir/dir.py +++ b/src/telnyx/resources/dir/dir.py @@ -12,11 +12,13 @@ DirStatus, dir_list_params, dir_update_params, + dir_bpo_loa_params, dir_new_loa_params, dir_update_infringement_params, dir_list_infringement_claims_params, + dir_retrieve_bpo_authorizations_params, ) -from ..._types import Body, Omit, Query, Headers, NoneType, NotGiven, SequenceNotStr, omit, not_given +from ..._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given from ..._utils import path_template, maybe_transform, async_maybe_transform from .comments import ( CommentsResource, @@ -81,7 +83,11 @@ ) from ...types.document_param import DocumentParam from ...types.infringement_claim import InfringementClaim +from ...types.dir_delete_response import DirDeleteResponse +from ...types.signature_payload_param import SignaturePayloadParam +from ...types.bpo_authorization_input_param import BpoAuthorizationInputParam from ...types.dir_list_document_types_response import DirListDocumentTypesResponse +from ...types.dir_retrieve_bpo_authorizations_response import DirRetrieveBpoAuthorizationsResponse from ...types.enterprises.reputation.agent_input_param import AgentInputParam __all__ = ["DirResource", "AsyncDirResource"] @@ -185,6 +191,7 @@ def update( *, authorizer_email: str | Omit = omit, authorizer_name: str | Omit = omit, + bpo_authorizations: Iterable[BpoAuthorizationInputParam] | Omit = omit, call_reasons: SequenceNotStr[str] | Omit = omit, certify_brand_is_accurate: bool | Omit = omit, certify_ip_ownership: bool | Omit = omit, @@ -193,6 +200,7 @@ def update( documents: Iterable[DocumentParam] | Omit = omit, logo_url: str | Omit = omit, reselling: bool | Omit = omit, + webhook_url: Optional[str] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -205,11 +213,14 @@ def update( DIRs in `draft`, `rejected`, `unsuccessful`, or `suspended` can be edited freely: PATCH is a pure edit, `status` is never changed, and you re-vet by calling `POST /v2/dir/{dir_id}/submit` explicitly. A `verified` DIR can also - be edited in place: a PATCH that changes any value returns the DIR to `draft` - and branded delivery stops until you re-submit and the DIR is approved again, - while a PATCH that changes nothing (an empty body or values identical to the - current ones) leaves the DIR `verified`, so idempotent retries are safe. DIRs in - any other status (`submitted`, `in_review`, `expired`, `infringement_claimed`, + be edited in place: a PATCH that changes any value returns the DIR to `draft`; + the currently approved identity keeps displaying, and the edited content goes + live only after you re-submit and the DIR is approved again. A PATCH that + changes nothing (an empty body or values identical to the current ones) leaves + the DIR `verified`, so idempotent retries are safe. Changing only + `bpo_authorizations` or `webhook_url` is the exception: the DIR stays + `verified`. Each BPO authorization is reviewed on its own instead. DIRs in any + other status (`submitted`, `in_review`, `expired`, `infringement_claimed`, `permanently_rejected`) cannot be edited. Args: @@ -219,6 +230,13 @@ def update( authorizer_name: Name of the person at your enterprise authorizing this DIR. Must be a real individual. + bpo_authorizations: Optional. Replace this DIR's authorized BPO (Business Process Outsourcer) + accounts with these, each with its signed Letter of Authorization. The supplied + list replaces the current one: a BPO left out has its authorization removed, and + a new BPO (or a changed Letter of Authorization) is created `pending` admin + review. Send an empty list to clear all authorizations; omit the field to leave + them unchanged. Editing this list does not re-vet the DIR. Maximum 10. + call_reasons: 1–10 reasons your business calls customers. Validate phrasing against `POST /call_reasons/validate`. @@ -243,6 +261,10 @@ def update( reselling: Set to true if your organization places calls on behalf of other enterprises (BPO/reseller). Updating this triggers re-vetting on next submit. + webhook_url: Optional `https://` URL that receives webhook notifications when this DIR's + compliance review completes. Send `null` to clear. Changing only this field on a + `verified` DIR does not re-vet it. Maximum 2048 characters. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -259,6 +281,7 @@ def update( { "authorizer_email": authorizer_email, "authorizer_name": authorizer_name, + "bpo_authorizations": bpo_authorizations, "call_reasons": call_reasons, "certify_brand_is_accurate": certify_brand_is_accurate, "certify_ip_ownership": certify_ip_ownership, @@ -267,6 +290,7 @@ def update( "documents": documents, "logo_url": logo_url, "reselling": reselling, + "webhook_url": webhook_url, }, dir_update_params.DirUpdateParams, ), @@ -380,12 +404,16 @@ def delete( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> None: - """Delete a DIR. + ) -> DirDeleteResponse: + """Request deletion of a DIR. - Failure modes: `400` if a child phone number is in a non-deletable - status, `409` if the DIR has an unresolved infringement claim, `404` if the DIR - is not yours. + This does not remove the DIR on this call: it records + the request, moves the DIR to `delete_requested`, and Telnyx completes the + removal (de-registration and cleanup) shortly after. A verified DIR keeps + serving its branded identity, and keeps billing, until the removal is executed. + Failure modes: `400` if a child phone number is still attached or the DIR is + `in_review` (wait for the review to finish), `409` if the DIR has an unresolved + infringement claim, `404` if the DIR is not yours. Args: extra_headers: Send extra headers @@ -398,13 +426,73 @@ def delete( """ if not dir_id: raise ValueError(f"Expected a non-empty value for `dir_id` but received {dir_id!r}") - extra_headers = {"Accept": "*/*", **(extra_headers or {})} return self._delete( path_template("/dir/{dir_id}", dir_id=dir_id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=NoneType, + cast_to=DirDeleteResponse, + ) + + def bpo_loa( + self, + dir_id: str, + *, + bpo_enterprise_id: str, + signature: SignaturePayloadParam | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> BinaryAPIResponse: + """ + The Letter of Authorization in which a Brand Owner authorizes an approved BPO + (Business Process Outsourcer) to place branded calls that display this DIR on + the owner's behalf. Both parties are read from the caller's account: the Brand + Owner is the enterprise that owns the DIR, and the BPO is `bpo_enterprise_id`. + No business identity is accepted in the body. + + When `signature` is omitted the PDF is returned unsigned so the Brand Owner can + sign it externally and the BPO can upload it via the Documents API. When + `signature` is present the PDF embeds the supplied image, printed name, and + signed-at date. + + Returns `application/pdf`. + + Args: + bpo_enterprise_id: The approved BPO enterprise the Brand Owner is authorizing. Must be a BPO + account on the caller's organization that has already been approved. + + signature: Optional. When provided the rendered PDF embeds the signature image, printed + name, and signed-at date. When absent the PDF is returned unsigned so the Brand + Owner can sign externally and the BPO can upload it via the Documents API. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not dir_id: + raise ValueError(f"Expected a non-empty value for `dir_id` but received {dir_id!r}") + extra_headers = {"Accept": "application/pdf", **(extra_headers or {})} + return self._post( + path_template("/dir/{dir_id}/bpo_loa", dir_id=dir_id), + body=maybe_transform( + { + "bpo_enterprise_id": bpo_enterprise_id, + "signature": signature, + }, + dir_bpo_loa_params.DirBpoLoaParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=BinaryAPIResponse, ) def list_document_types( @@ -493,7 +581,7 @@ def new_loa( *, phone_numbers: SequenceNotStr[str], agent: AgentInputParam | Omit = omit, - signature: dir_new_loa_params.Signature | Omit = omit, + signature: SignaturePayloadParam | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -552,6 +640,66 @@ def new_loa( cast_to=BinaryAPIResponse, ) + def retrieve_bpo_authorizations( + self, + dir_id: str, + *, + page_number: int | Omit = omit, + page_size: int | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> DirRetrieveBpoAuthorizationsResponse: + """ + List the BPO (Business Process Outsourcer) accounts a Brand Owner has authorized + on this DIR, together with the review state of each authorization. + + Authorizations are supplied as the `bpo_authorizations` array when creating or + updating a DIR, and each one is reviewed on its own. Only an `approved` + authorization adds that BPO to this DIR's authorized callers in the branded + calling registry; `pending` and `rejected` authorizations do not. Each entry + includes the `loa_document_id` you submitted: because `bpo_authorizations` + replaces the whole list on every DIR update, send each entry you want to keep + back with its `loa_document_id` unchanged, and it keeps its review state. A + rejected entry carries a `rejection_reason`. Returns an empty list when the DIR + has authorized no BPOs. + + Args: + page_number: 1-based page number. Out-of-range values return an empty page with correct meta. + + page_size: Items per page. Maximum 250; values above are clamped to 250. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not dir_id: + raise ValueError(f"Expected a non-empty value for `dir_id` but received {dir_id!r}") + return self._get( + path_template("/dir/{dir_id}/bpo_authorizations", dir_id=dir_id), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "page_number": page_number, + "page_size": page_size, + }, + dir_retrieve_bpo_authorizations_params.DirRetrieveBpoAuthorizationsParams, + ), + ), + cast_to=DirRetrieveBpoAuthorizationsResponse, + ) + def submit( self, dir_id: str, @@ -627,12 +775,16 @@ def update_infringement( certify_ip_ownership: Must be `true`. - certify_no_infringement: Must be `true`. + certify_no_infringement: Check to certify that the brand no longer infringes anyone else's trademark or + intellectual property. certify_no_shaft_content: Must be `true`. infringement_resolution_notes: Explanation of how the infringement concern was addressed. + display_name: The business name shown to call recipients, 1 to 35 characters, no emoji, not + blank. + documents: Append-only supporting documents to attach while resolving the claim (e.g. authorization or licensing proof). @@ -769,6 +921,7 @@ async def update( *, authorizer_email: str | Omit = omit, authorizer_name: str | Omit = omit, + bpo_authorizations: Iterable[BpoAuthorizationInputParam] | Omit = omit, call_reasons: SequenceNotStr[str] | Omit = omit, certify_brand_is_accurate: bool | Omit = omit, certify_ip_ownership: bool | Omit = omit, @@ -777,6 +930,7 @@ async def update( documents: Iterable[DocumentParam] | Omit = omit, logo_url: str | Omit = omit, reselling: bool | Omit = omit, + webhook_url: Optional[str] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -789,11 +943,14 @@ async def update( DIRs in `draft`, `rejected`, `unsuccessful`, or `suspended` can be edited freely: PATCH is a pure edit, `status` is never changed, and you re-vet by calling `POST /v2/dir/{dir_id}/submit` explicitly. A `verified` DIR can also - be edited in place: a PATCH that changes any value returns the DIR to `draft` - and branded delivery stops until you re-submit and the DIR is approved again, - while a PATCH that changes nothing (an empty body or values identical to the - current ones) leaves the DIR `verified`, so idempotent retries are safe. DIRs in - any other status (`submitted`, `in_review`, `expired`, `infringement_claimed`, + be edited in place: a PATCH that changes any value returns the DIR to `draft`; + the currently approved identity keeps displaying, and the edited content goes + live only after you re-submit and the DIR is approved again. A PATCH that + changes nothing (an empty body or values identical to the current ones) leaves + the DIR `verified`, so idempotent retries are safe. Changing only + `bpo_authorizations` or `webhook_url` is the exception: the DIR stays + `verified`. Each BPO authorization is reviewed on its own instead. DIRs in any + other status (`submitted`, `in_review`, `expired`, `infringement_claimed`, `permanently_rejected`) cannot be edited. Args: @@ -803,6 +960,13 @@ async def update( authorizer_name: Name of the person at your enterprise authorizing this DIR. Must be a real individual. + bpo_authorizations: Optional. Replace this DIR's authorized BPO (Business Process Outsourcer) + accounts with these, each with its signed Letter of Authorization. The supplied + list replaces the current one: a BPO left out has its authorization removed, and + a new BPO (or a changed Letter of Authorization) is created `pending` admin + review. Send an empty list to clear all authorizations; omit the field to leave + them unchanged. Editing this list does not re-vet the DIR. Maximum 10. + call_reasons: 1–10 reasons your business calls customers. Validate phrasing against `POST /call_reasons/validate`. @@ -827,6 +991,10 @@ async def update( reselling: Set to true if your organization places calls on behalf of other enterprises (BPO/reseller). Updating this triggers re-vetting on next submit. + webhook_url: Optional `https://` URL that receives webhook notifications when this DIR's + compliance review completes. Send `null` to clear. Changing only this field on a + `verified` DIR does not re-vet it. Maximum 2048 characters. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -843,6 +1011,7 @@ async def update( { "authorizer_email": authorizer_email, "authorizer_name": authorizer_name, + "bpo_authorizations": bpo_authorizations, "call_reasons": call_reasons, "certify_brand_is_accurate": certify_brand_is_accurate, "certify_ip_ownership": certify_ip_ownership, @@ -851,6 +1020,7 @@ async def update( "documents": documents, "logo_url": logo_url, "reselling": reselling, + "webhook_url": webhook_url, }, dir_update_params.DirUpdateParams, ), @@ -964,12 +1134,16 @@ async def delete( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> None: - """Delete a DIR. + ) -> DirDeleteResponse: + """Request deletion of a DIR. - Failure modes: `400` if a child phone number is in a non-deletable - status, `409` if the DIR has an unresolved infringement claim, `404` if the DIR - is not yours. + This does not remove the DIR on this call: it records + the request, moves the DIR to `delete_requested`, and Telnyx completes the + removal (de-registration and cleanup) shortly after. A verified DIR keeps + serving its branded identity, and keeps billing, until the removal is executed. + Failure modes: `400` if a child phone number is still attached or the DIR is + `in_review` (wait for the review to finish), `409` if the DIR has an unresolved + infringement claim, `404` if the DIR is not yours. Args: extra_headers: Send extra headers @@ -982,13 +1156,73 @@ async def delete( """ if not dir_id: raise ValueError(f"Expected a non-empty value for `dir_id` but received {dir_id!r}") - extra_headers = {"Accept": "*/*", **(extra_headers or {})} return await self._delete( path_template("/dir/{dir_id}", dir_id=dir_id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=NoneType, + cast_to=DirDeleteResponse, + ) + + async def bpo_loa( + self, + dir_id: str, + *, + bpo_enterprise_id: str, + signature: SignaturePayloadParam | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> AsyncBinaryAPIResponse: + """ + The Letter of Authorization in which a Brand Owner authorizes an approved BPO + (Business Process Outsourcer) to place branded calls that display this DIR on + the owner's behalf. Both parties are read from the caller's account: the Brand + Owner is the enterprise that owns the DIR, and the BPO is `bpo_enterprise_id`. + No business identity is accepted in the body. + + When `signature` is omitted the PDF is returned unsigned so the Brand Owner can + sign it externally and the BPO can upload it via the Documents API. When + `signature` is present the PDF embeds the supplied image, printed name, and + signed-at date. + + Returns `application/pdf`. + + Args: + bpo_enterprise_id: The approved BPO enterprise the Brand Owner is authorizing. Must be a BPO + account on the caller's organization that has already been approved. + + signature: Optional. When provided the rendered PDF embeds the signature image, printed + name, and signed-at date. When absent the PDF is returned unsigned so the Brand + Owner can sign externally and the BPO can upload it via the Documents API. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not dir_id: + raise ValueError(f"Expected a non-empty value for `dir_id` but received {dir_id!r}") + extra_headers = {"Accept": "application/pdf", **(extra_headers or {})} + return await self._post( + path_template("/dir/{dir_id}/bpo_loa", dir_id=dir_id), + body=await async_maybe_transform( + { + "bpo_enterprise_id": bpo_enterprise_id, + "signature": signature, + }, + dir_bpo_loa_params.DirBpoLoaParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=AsyncBinaryAPIResponse, ) async def list_document_types( @@ -1077,7 +1311,7 @@ async def new_loa( *, phone_numbers: SequenceNotStr[str], agent: AgentInputParam | Omit = omit, - signature: dir_new_loa_params.Signature | Omit = omit, + signature: SignaturePayloadParam | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -1136,6 +1370,66 @@ async def new_loa( cast_to=AsyncBinaryAPIResponse, ) + async def retrieve_bpo_authorizations( + self, + dir_id: str, + *, + page_number: int | Omit = omit, + page_size: int | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> DirRetrieveBpoAuthorizationsResponse: + """ + List the BPO (Business Process Outsourcer) accounts a Brand Owner has authorized + on this DIR, together with the review state of each authorization. + + Authorizations are supplied as the `bpo_authorizations` array when creating or + updating a DIR, and each one is reviewed on its own. Only an `approved` + authorization adds that BPO to this DIR's authorized callers in the branded + calling registry; `pending` and `rejected` authorizations do not. Each entry + includes the `loa_document_id` you submitted: because `bpo_authorizations` + replaces the whole list on every DIR update, send each entry you want to keep + back with its `loa_document_id` unchanged, and it keeps its review state. A + rejected entry carries a `rejection_reason`. Returns an empty list when the DIR + has authorized no BPOs. + + Args: + page_number: 1-based page number. Out-of-range values return an empty page with correct meta. + + page_size: Items per page. Maximum 250; values above are clamped to 250. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not dir_id: + raise ValueError(f"Expected a non-empty value for `dir_id` but received {dir_id!r}") + return await self._get( + path_template("/dir/{dir_id}/bpo_authorizations", dir_id=dir_id), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform( + { + "page_number": page_number, + "page_size": page_size, + }, + dir_retrieve_bpo_authorizations_params.DirRetrieveBpoAuthorizationsParams, + ), + ), + cast_to=DirRetrieveBpoAuthorizationsResponse, + ) + async def submit( self, dir_id: str, @@ -1211,12 +1505,16 @@ async def update_infringement( certify_ip_ownership: Must be `true`. - certify_no_infringement: Must be `true`. + certify_no_infringement: Check to certify that the brand no longer infringes anyone else's trademark or + intellectual property. certify_no_shaft_content: Must be `true`. infringement_resolution_notes: Explanation of how the infringement concern was addressed. + display_name: The business name shown to call recipients, 1 to 35 characters, no emoji, not + blank. + documents: Append-only supporting documents to attach while resolving the claim (e.g. authorization or licensing proof). @@ -1271,6 +1569,10 @@ def __init__(self, dir: DirResource) -> None: self.delete = to_raw_response_wrapper( dir.delete, ) + self.bpo_loa = to_custom_raw_response_wrapper( + dir.bpo_loa, + BinaryAPIResponse, + ) self.list_document_types = to_raw_response_wrapper( dir.list_document_types, ) @@ -1281,6 +1583,9 @@ def __init__(self, dir: DirResource) -> None: dir.new_loa, BinaryAPIResponse, ) + self.retrieve_bpo_authorizations = to_raw_response_wrapper( + dir.retrieve_bpo_authorizations, + ) self.submit = to_raw_response_wrapper( dir.submit, ) @@ -1342,6 +1647,10 @@ def __init__(self, dir: AsyncDirResource) -> None: self.delete = async_to_raw_response_wrapper( dir.delete, ) + self.bpo_loa = async_to_custom_raw_response_wrapper( + dir.bpo_loa, + AsyncBinaryAPIResponse, + ) self.list_document_types = async_to_raw_response_wrapper( dir.list_document_types, ) @@ -1352,6 +1661,9 @@ def __init__(self, dir: AsyncDirResource) -> None: dir.new_loa, AsyncBinaryAPIResponse, ) + self.retrieve_bpo_authorizations = async_to_raw_response_wrapper( + dir.retrieve_bpo_authorizations, + ) self.submit = async_to_raw_response_wrapper( dir.submit, ) @@ -1413,6 +1725,10 @@ def __init__(self, dir: DirResource) -> None: self.delete = to_streamed_response_wrapper( dir.delete, ) + self.bpo_loa = to_custom_streamed_response_wrapper( + dir.bpo_loa, + StreamedBinaryAPIResponse, + ) self.list_document_types = to_streamed_response_wrapper( dir.list_document_types, ) @@ -1423,6 +1739,9 @@ def __init__(self, dir: DirResource) -> None: dir.new_loa, StreamedBinaryAPIResponse, ) + self.retrieve_bpo_authorizations = to_streamed_response_wrapper( + dir.retrieve_bpo_authorizations, + ) self.submit = to_streamed_response_wrapper( dir.submit, ) @@ -1484,6 +1803,10 @@ def __init__(self, dir: AsyncDirResource) -> None: self.delete = async_to_streamed_response_wrapper( dir.delete, ) + self.bpo_loa = async_to_custom_streamed_response_wrapper( + dir.bpo_loa, + AsyncStreamedBinaryAPIResponse, + ) self.list_document_types = async_to_streamed_response_wrapper( dir.list_document_types, ) @@ -1494,6 +1817,9 @@ def __init__(self, dir: AsyncDirResource) -> None: dir.new_loa, AsyncStreamedBinaryAPIResponse, ) + self.retrieve_bpo_authorizations = async_to_streamed_response_wrapper( + dir.retrieve_bpo_authorizations, + ) self.submit = async_to_streamed_response_wrapper( dir.submit, ) diff --git a/src/telnyx/resources/dir/phone_numbers.py b/src/telnyx/resources/dir/phone_numbers.py index 99828d3bc..ac9113d42 100644 --- a/src/telnyx/resources/dir/phone_numbers.py +++ b/src/telnyx/resources/dir/phone_numbers.py @@ -129,11 +129,11 @@ def add( """Register phone numbers under a DIR. The enterprise is resolved server-side from - the DIR id. Same body, failure modes, and batch semantics whichever path form - you use. + the DIR id. - **Pricing:** This is a billable action. See https://telnyx.com/pricing/numbers - for current pricing. + **Pricing:** Adding phone numbers is free. Branded Calling fees are charged per + DIR and per branded call. See https://telnyx.com/pricing/branded-calling for + current pricing. Args: documents: Supporting documents covering this batch. At least one entry with @@ -188,6 +188,9 @@ def remove( the DIR id. Returns a partial-success envelope. Args: + phone_numbers: The phone numbers to remove from this brand, in E.164 format, up to 100 per + request. They must currently be attached to this brand. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -304,11 +307,11 @@ async def add( """Register phone numbers under a DIR. The enterprise is resolved server-side from - the DIR id. Same body, failure modes, and batch semantics whichever path form - you use. + the DIR id. - **Pricing:** This is a billable action. See https://telnyx.com/pricing/numbers - for current pricing. + **Pricing:** Adding phone numbers is free. Branded Calling fees are charged per + DIR and per branded call. See https://telnyx.com/pricing/branded-calling for + current pricing. Args: documents: Supporting documents covering this batch. At least one entry with @@ -363,6 +366,9 @@ async def remove( the DIR id. Returns a partial-success envelope. Args: + phone_numbers: The phone numbers to remove from this brand, in E.164 format, up to 100 per + request. They must currently be attached to this brand. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request diff --git a/src/telnyx/resources/dir/references.py b/src/telnyx/resources/dir/references.py index 0383d923c..8bed4a49f 100644 --- a/src/telnyx/resources/dir/references.py +++ b/src/telnyx/resources/dir/references.py @@ -162,19 +162,22 @@ def update( pending call into the new local calling window. Args: - email: Reference contact email address. + email: The reference's email address. We email them scheduling and dial-in instructions + before we call, so use an address they check. - full_name: Full name of the reference contact. + full_name: The full name of the person we should contact as your reference. - job_title: Job title of the reference contact. + job_title: The reference contact's job title, for example CFO or Owner. - organization: Organization the reference contact belongs to. + organization: The name of the organization the reference contact works for. - phone_e164: Reference phone number in E.164 format. + phone_e164: The reference's phone number in E.164 format, for example +14155550123. We call + this number during their local business hours. relationship_to_registrant: How the reference contact is related to the registering business. - timezone: IANA timezone id for the reference. + timezone: The reference's IANA time zone, for example America/New_York. We only call + during their local 8am to 9pm hours, which is why we need it. extra_headers: Send extra headers @@ -385,19 +388,22 @@ async def update( pending call into the new local calling window. Args: - email: Reference contact email address. + email: The reference's email address. We email them scheduling and dial-in instructions + before we call, so use an address they check. - full_name: Full name of the reference contact. + full_name: The full name of the person we should contact as your reference. - job_title: Job title of the reference contact. + job_title: The reference contact's job title, for example CFO or Owner. - organization: Organization the reference contact belongs to. + organization: The name of the organization the reference contact works for. - phone_e164: Reference phone number in E.164 format. + phone_e164: The reference's phone number in E.164 format, for example +14155550123. We call + this number during their local business hours. relationship_to_registrant: How the reference contact is related to the registering business. - timezone: IANA timezone id for the reference. + timezone: The reference's IANA time zone, for example America/New_York. We only call + during their local 8am to 9pm hours, which is why we need it. extra_headers: Send extra headers diff --git a/src/telnyx/resources/enterprises/__init__.py b/src/telnyx/resources/enterprises/__init__.py index f3f33c7f2..116d6a3a1 100644 --- a/src/telnyx/resources/enterprises/__init__.py +++ b/src/telnyx/resources/enterprises/__init__.py @@ -24,6 +24,14 @@ EnterprisesResourceWithStreamingResponse, AsyncEnterprisesResourceWithStreamingResponse, ) +from .verify_email import ( + VerifyEmailResource, + AsyncVerifyEmailResource, + VerifyEmailResourceWithRawResponse, + AsyncVerifyEmailResourceWithRawResponse, + VerifyEmailResourceWithStreamingResponse, + AsyncVerifyEmailResourceWithStreamingResponse, +) __all__ = [ "ReputationResource", @@ -38,6 +46,12 @@ "AsyncDirResourceWithRawResponse", "DirResourceWithStreamingResponse", "AsyncDirResourceWithStreamingResponse", + "VerifyEmailResource", + "AsyncVerifyEmailResource", + "VerifyEmailResourceWithRawResponse", + "AsyncVerifyEmailResourceWithRawResponse", + "VerifyEmailResourceWithStreamingResponse", + "AsyncVerifyEmailResourceWithStreamingResponse", "EnterprisesResource", "AsyncEnterprisesResource", "EnterprisesResourceWithRawResponse", diff --git a/src/telnyx/resources/enterprises/dir.py b/src/telnyx/resources/enterprises/dir.py index adf663033..8bc75eebd 100644 --- a/src/telnyx/resources/enterprises/dir.py +++ b/src/telnyx/resources/enterprises/dir.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import Union, Iterable +from typing import Union, Iterable, Optional from datetime import datetime from typing_extensions import Literal @@ -26,6 +26,7 @@ from ...types.dir_wrapped import DirWrapped from ...types.enterprises import dir_list_params, dir_create_params from ...types.document_param import DocumentParam +from ...types.bpo_authorization_input_param import BpoAuthorizationInputParam __all__ = ["DirResource", "AsyncDirResource"] @@ -65,9 +66,11 @@ def create( certify_ip_ownership: Literal[True], certify_no_shaft_content: Literal[True], display_name: str, + bpo_authorizations: Iterable[BpoAuthorizationInputParam] | Omit = omit, documents: Iterable[DocumentParam] | Omit = omit, logo_url: str | Omit = omit, reselling: bool | Omit = omit, + webhook_url: Optional[str] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -113,7 +116,8 @@ def create( call_reasons: 1–10 reasons your business calls customers. Validate phrasing against `POST /call_reasons/validate`. - certify_brand_is_accurate: Must be `true`. + certify_brand_is_accurate: Certification that the DIR information is accurate. Must be `true` for the DIR + to be submitted for vetting. certify_ip_ownership: Must be `true`. Confirms ownership of any logos/trademarks shown. @@ -122,6 +126,13 @@ def create( display_name: Name shown to call recipients. No emoji; not whitespace-only. + bpo_authorizations: Optional. Approved BPO (Business Process Outsourcer) accounts on your + organization authorized to place branded calls for this DIR, each with the + signed Letter of Authorization the Brand Owner granted it. Each authorization + starts `pending` and takes effect only after an admin reviews its Letter of + Authorization. Omit or send an empty list to authorize no BPO on this DIR. + Maximum 10. + documents: Supporting documents. Each `document_id` may appear at most once on a DIR. logo_url: Publicly accessible HTTPS URL (max 128 chars) to a 256x256 BMP logo (max 1 MB). @@ -129,6 +140,10 @@ def create( reselling: Set to true if your organization places calls on behalf of other enterprises (BPO/reseller). + webhook_url: Optional `https://` URL that receives webhook notifications when this DIR's + compliance review completes (rejection outcomes include structured rejection + reasons). Maximum 2048 characters. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -150,9 +165,11 @@ def create( "certify_ip_ownership": certify_ip_ownership, "certify_no_shaft_content": certify_no_shaft_content, "display_name": display_name, + "bpo_authorizations": bpo_authorizations, "documents": documents, "logo_url": logo_url, "reselling": reselling, + "webhook_url": webhook_url, }, dir_create_params.DirCreateParams, ), @@ -305,9 +322,11 @@ async def create( certify_ip_ownership: Literal[True], certify_no_shaft_content: Literal[True], display_name: str, + bpo_authorizations: Iterable[BpoAuthorizationInputParam] | Omit = omit, documents: Iterable[DocumentParam] | Omit = omit, logo_url: str | Omit = omit, reselling: bool | Omit = omit, + webhook_url: Optional[str] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -353,7 +372,8 @@ async def create( call_reasons: 1–10 reasons your business calls customers. Validate phrasing against `POST /call_reasons/validate`. - certify_brand_is_accurate: Must be `true`. + certify_brand_is_accurate: Certification that the DIR information is accurate. Must be `true` for the DIR + to be submitted for vetting. certify_ip_ownership: Must be `true`. Confirms ownership of any logos/trademarks shown. @@ -362,6 +382,13 @@ async def create( display_name: Name shown to call recipients. No emoji; not whitespace-only. + bpo_authorizations: Optional. Approved BPO (Business Process Outsourcer) accounts on your + organization authorized to place branded calls for this DIR, each with the + signed Letter of Authorization the Brand Owner granted it. Each authorization + starts `pending` and takes effect only after an admin reviews its Letter of + Authorization. Omit or send an empty list to authorize no BPO on this DIR. + Maximum 10. + documents: Supporting documents. Each `document_id` may appear at most once on a DIR. logo_url: Publicly accessible HTTPS URL (max 128 chars) to a 256x256 BMP logo (max 1 MB). @@ -369,6 +396,10 @@ async def create( reselling: Set to true if your organization places calls on behalf of other enterprises (BPO/reseller). + webhook_url: Optional `https://` URL that receives webhook notifications when this DIR's + compliance review completes (rejection outcomes include structured rejection + reasons). Maximum 2048 characters. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -390,9 +421,11 @@ async def create( "certify_ip_ownership": certify_ip_ownership, "certify_no_shaft_content": certify_no_shaft_content, "display_name": display_name, + "bpo_authorizations": bpo_authorizations, "documents": documents, "logo_url": logo_url, "reselling": reselling, + "webhook_url": webhook_url, }, dir_create_params.DirCreateParams, ), diff --git a/src/telnyx/resources/enterprises/enterprises.py b/src/telnyx/resources/enterprises/enterprises.py index 457d3b00d..f003af233 100644 --- a/src/telnyx/resources/enterprises/enterprises.py +++ b/src/telnyx/resources/enterprises/enterprises.py @@ -31,6 +31,14 @@ async_to_streamed_response_wrapper, ) from ...pagination import SyncDefaultFlatPagination, AsyncDefaultFlatPagination +from .verify_email import ( + VerifyEmailResource, + AsyncVerifyEmailResource, + VerifyEmailResourceWithRawResponse, + AsyncVerifyEmailResourceWithRawResponse, + VerifyEmailResourceWithStreamingResponse, + AsyncVerifyEmailResourceWithStreamingResponse, +) from ..._base_client import AsyncPaginator, make_request_options from .reputation.reputation import ( ReputationResource, @@ -64,6 +72,14 @@ def dir(self) -> DirResource: """ return DirResource(self._client) + @cached_property + def verify_email(self) -> VerifyEmailResource: + """Verify ownership of a DIR's authorizer email. + + A short code is emailed and confirmed; the email must be verified before references can be submitted. + """ + return VerifyEmailResource(self._client) + @cached_property def with_raw_response(self) -> EnterprisesResourceWithRawResponse: """ @@ -175,11 +191,20 @@ def create( Args: country_code: ISO 3166-1 alpha-2 country code. Currently `US` and `CA` are supported. + doing_business_as: The trade name your business operates under if it is different from your legal + name, also called a Doing Business As (DBA) name. Leave blank if you only use + your legal name. + fein: US Federal Employer Identification Number (`NN-NNNNNNN`) or Canadian equivalent. - industry: Industry classification. + industry: The industry your business operates in. Choose the closest match from the list; + if your value is not accepted, pick the nearest category. - legal_name: Legal name of the enterprise. + jurisdiction_of_incorporation: The state, province, or country where your business was legally incorporated, + for example Delaware. + + legal_name: Your business's full registered legal name, exactly as it appears on your + incorporation or tax documents, 3 to 64 characters. number_of_employees: Approximate headcount range. Used for vetting heuristics; pick the bucket that contains your current employee count. @@ -204,19 +229,35 @@ def create( - `non_profit` - registered 501(c)(3)/equivalent (incl. educational institutions, charities, religious organisations). - corporate_registration_number: Optional corporate-registration / company-number identifier. + website: Your business's public website address, including https://. Leave blank if your + business has no website. + + corporate_registration_number: The official number your company received when it was legally registered or + incorporated (for example from your state or national business registry). It is + on your certificate of incorporation. - customer_reference: Optional free-form string the caller can attach for their own bookkeeping. - Telnyx does not interpret it. + customer_reference: Your own label for this account. Enter any reference that helps you find it in + your records. Telnyx does not use it during vetting. - dun_bradstreet_number: Optional D-U-N-S Number. + dun_bradstreet_number: Your optional 9-digit D-U-N-S Number issued by Dun & Bradstreet, a unique + identifier for your business. Leave blank if you do not have one. - primary_business_domain_sic_code: Optional SIC code for the primary line of business. + primary_business_domain_sic_code: The 4-digit Standard Industrial Classification code for your main line of + business, which tells us what industry you operate in. Look it up in the SIC + code directory if you are unsure. - professional_license_number: Optional professional-license number for regulated industries. + professional_license_number: If your business operates under a professional license (for example legal, + medical, or financial services), enter the license number issued by the + licensing authority. Leave blank if it does not apply. - role_type: `enterprise` for an organization registering its own DIRs; `bpo` for a Business - Process Outsourcer placing calls on behalf of one or more enterprises. + role_type: `enterprise` for an organization registering its own DIRs (the default, and the + right choice when the calls display your own brand). `bpo` for a Business + Process Outsourcer: a call center that places calls on behalf of other + enterprises and displays their brand. A `bpo` enterprise describes the call + center itself and cannot own a DIR. Each client the call center calls for gets + its own `enterprise` in the same account, with the client's DIR under it; that + DIR is then linked to the `bpo` enterprise through `bpo_authorizations`. Fixed + at creation. extra_headers: Send extra headers @@ -375,10 +416,71 @@ def update( cannot be changed: including any of them in the body is rejected with `400 Bad Request` (`Field 'X' is not allowed in this request`). + For an approved BPO enterprise (`role_type` `bpo`), changing any identity field + (legal name, DBA, website, FEIN, industry, number of employees, physical + address, organization contact, D-U-N-S number, legal type, SIC code, corporate + registration number, professional license number, or jurisdiction of + incorporation) resets `bpo_verification_status` to `pending` for re-approval and + sets every DIR authorization for that BPO to `rejected`. After re-approval, link + it again with a newly signed LOA (a new `loa_document_id`); resending the old + one keeps the authorization `rejected`. Re-sending an unchanged value does not + reset anything. + + If Number Reputation is enabled on the enterprise, `legal_name`, + `doing_business_as`, `website`, `fein`, `industry`, `number_of_employees`, + `organization_physical_address`, `organization_contact`, and + `dun_bradstreet_number` cannot be changed: the request is rejected with `400`. + Args: - jurisdiction_of_incorporation: Updated state/province/country of incorporation. Optional on update. + corporate_registration_number: The official number your company received when it was legally registered or + incorporated (for example from your state or national business registry). It is + on your certificate of incorporation. + + customer_reference: Your own label for this account. Enter any reference that helps you find it in + your records. Telnyx does not use it during vetting. + + doing_business_as: The trade name your business operates under if it is different from your legal + name, also called a Doing Business As (DBA) name. Leave blank if you only use + your legal name. + + dun_bradstreet_number: Your optional 9-digit D-U-N-S Number issued by Dun & Bradstreet, a unique + identifier for your business. Leave blank if you do not have one. + + fein: US Federal Employer Identification Number (`NN-NNNNNNN`) or Canadian equivalent. + + industry: The industry your business operates in. Choose the closest match from the list; + if your value is not accepted, pick the nearest category. + + jurisdiction_of_incorporation: The state, province, or country where your business was legally incorporated, + for example Delaware. + + legal_name: Your business's full registered legal name, exactly as it appears on your + incorporation or tax documents, 3 to 64 characters. + + number_of_employees: Approximate headcount range. Used for vetting heuristics; pick the bucket that + contains your current employee count. + + organization_legal_type: + Legal-entity form. Pick the form that matches your incorporation documents: + + - `corporation` - C-corp or S-corp. + - `llc` - limited liability company. + - `partnership` - general/limited partnership. + - `nonprofit` - non-profit corporation, charitable trust, or + 501(c)(3)/equivalent. + - `other` - anything else (sole proprietorships, government bodies, DBAs, etc.). + You may be asked for additional documents during vetting. + + primary_business_domain_sic_code: The 4-digit Standard Industrial Classification code for your main line of + business, which tells us what industry you operate in. Look it up in the SIC + code directory if you are unsure. + + professional_license_number: If your business operates under a professional license (for example legal, + medical, or financial services), enter the license number issued by the + licensing authority. Leave blank if it does not apply. - legal_name: Legal name of the enterprise. + website: Your business's public website address, including https://. Leave blank if your + business has no website. extra_headers: Send extra headers @@ -424,6 +526,7 @@ def list( self, *, filter_legal_name_contains: str | Omit = omit, + filter_role_type: Literal["enterprise", "bpo"] | Omit = omit, legal_name: str | Omit = omit, page_number: int | Omit = omit, page_size: int | Omit = omit, @@ -442,6 +545,9 @@ def list( Args: filter_legal_name_contains: Case-insensitive partial match on legal name. + filter_role_type: Only return enterprises of this type: `bpo` for call-center (BPO) enterprises, + `enterprise` for normal enterprises. Omit to return both. + legal_name: Filter by legal name (partial match). page_number: 1-based page number. Out-of-range values return an empty page with correct meta. @@ -467,6 +573,7 @@ def list( query=maybe_transform( { "filter_legal_name_contains": filter_legal_name_contains, + "filter_role_type": filter_role_type, "legal_name": legal_name, "page_number": page_number, "page_size": page_size, @@ -531,8 +638,8 @@ def branded_calling( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> EnterprisePublicWrapped: - """ - Branded Calling is a paid product that must be activated on each enterprise. + """Branded Calling must be activated on each enterprise. + Activation is idempotent: - First call: marks the enterprise as activated and begins onboarding it with @@ -547,11 +654,15 @@ def branded_calling( Failure modes: + - `400` - the account has no available credit. Add funds and retry. + - `400` - the enterprise is not in the United States. Branded Calling is + currently available only to US enterprises. - `403` - Branded Calling Terms of Service not accepted. - `404` - enterprise does not exist or does not belong to your account. - **Pricing:** This is a billable action. See https://telnyx.com/pricing/numbers - for current pricing. + **Pricing:** Activation itself is free, but the account must have available + credit. Branded Calling fees are charged per DIR and per branded call. See + https://telnyx.com/pricing/branded-calling for current pricing. Args: extra_headers: Send extra headers @@ -588,6 +699,14 @@ def dir(self) -> AsyncDirResource: """ return AsyncDirResource(self._client) + @cached_property + def verify_email(self) -> AsyncVerifyEmailResource: + """Verify ownership of a DIR's authorizer email. + + A short code is emailed and confirmed; the email must be verified before references can be submitted. + """ + return AsyncVerifyEmailResource(self._client) + @cached_property def with_raw_response(self) -> AsyncEnterprisesResourceWithRawResponse: """ @@ -699,11 +818,20 @@ async def create( Args: country_code: ISO 3166-1 alpha-2 country code. Currently `US` and `CA` are supported. + doing_business_as: The trade name your business operates under if it is different from your legal + name, also called a Doing Business As (DBA) name. Leave blank if you only use + your legal name. + fein: US Federal Employer Identification Number (`NN-NNNNNNN`) or Canadian equivalent. - industry: Industry classification. + industry: The industry your business operates in. Choose the closest match from the list; + if your value is not accepted, pick the nearest category. + + jurisdiction_of_incorporation: The state, province, or country where your business was legally incorporated, + for example Delaware. - legal_name: Legal name of the enterprise. + legal_name: Your business's full registered legal name, exactly as it appears on your + incorporation or tax documents, 3 to 64 characters. number_of_employees: Approximate headcount range. Used for vetting heuristics; pick the bucket that contains your current employee count. @@ -728,19 +856,35 @@ async def create( - `non_profit` - registered 501(c)(3)/equivalent (incl. educational institutions, charities, religious organisations). - corporate_registration_number: Optional corporate-registration / company-number identifier. + website: Your business's public website address, including https://. Leave blank if your + business has no website. - customer_reference: Optional free-form string the caller can attach for their own bookkeeping. - Telnyx does not interpret it. + corporate_registration_number: The official number your company received when it was legally registered or + incorporated (for example from your state or national business registry). It is + on your certificate of incorporation. - dun_bradstreet_number: Optional D-U-N-S Number. + customer_reference: Your own label for this account. Enter any reference that helps you find it in + your records. Telnyx does not use it during vetting. - primary_business_domain_sic_code: Optional SIC code for the primary line of business. + dun_bradstreet_number: Your optional 9-digit D-U-N-S Number issued by Dun & Bradstreet, a unique + identifier for your business. Leave blank if you do not have one. - professional_license_number: Optional professional-license number for regulated industries. + primary_business_domain_sic_code: The 4-digit Standard Industrial Classification code for your main line of + business, which tells us what industry you operate in. Look it up in the SIC + code directory if you are unsure. - role_type: `enterprise` for an organization registering its own DIRs; `bpo` for a Business - Process Outsourcer placing calls on behalf of one or more enterprises. + professional_license_number: If your business operates under a professional license (for example legal, + medical, or financial services), enter the license number issued by the + licensing authority. Leave blank if it does not apply. + + role_type: `enterprise` for an organization registering its own DIRs (the default, and the + right choice when the calls display your own brand). `bpo` for a Business + Process Outsourcer: a call center that places calls on behalf of other + enterprises and displays their brand. A `bpo` enterprise describes the call + center itself and cannot own a DIR. Each client the call center calls for gets + its own `enterprise` in the same account, with the client's DIR under it; that + DIR is then linked to the `bpo` enterprise through `bpo_authorizations`. Fixed + at creation. extra_headers: Send extra headers @@ -899,10 +1043,71 @@ async def update( cannot be changed: including any of them in the body is rejected with `400 Bad Request` (`Field 'X' is not allowed in this request`). + For an approved BPO enterprise (`role_type` `bpo`), changing any identity field + (legal name, DBA, website, FEIN, industry, number of employees, physical + address, organization contact, D-U-N-S number, legal type, SIC code, corporate + registration number, professional license number, or jurisdiction of + incorporation) resets `bpo_verification_status` to `pending` for re-approval and + sets every DIR authorization for that BPO to `rejected`. After re-approval, link + it again with a newly signed LOA (a new `loa_document_id`); resending the old + one keeps the authorization `rejected`. Re-sending an unchanged value does not + reset anything. + + If Number Reputation is enabled on the enterprise, `legal_name`, + `doing_business_as`, `website`, `fein`, `industry`, `number_of_employees`, + `organization_physical_address`, `organization_contact`, and + `dun_bradstreet_number` cannot be changed: the request is rejected with `400`. + Args: - jurisdiction_of_incorporation: Updated state/province/country of incorporation. Optional on update. + corporate_registration_number: The official number your company received when it was legally registered or + incorporated (for example from your state or national business registry). It is + on your certificate of incorporation. - legal_name: Legal name of the enterprise. + customer_reference: Your own label for this account. Enter any reference that helps you find it in + your records. Telnyx does not use it during vetting. + + doing_business_as: The trade name your business operates under if it is different from your legal + name, also called a Doing Business As (DBA) name. Leave blank if you only use + your legal name. + + dun_bradstreet_number: Your optional 9-digit D-U-N-S Number issued by Dun & Bradstreet, a unique + identifier for your business. Leave blank if you do not have one. + + fein: US Federal Employer Identification Number (`NN-NNNNNNN`) or Canadian equivalent. + + industry: The industry your business operates in. Choose the closest match from the list; + if your value is not accepted, pick the nearest category. + + jurisdiction_of_incorporation: The state, province, or country where your business was legally incorporated, + for example Delaware. + + legal_name: Your business's full registered legal name, exactly as it appears on your + incorporation or tax documents, 3 to 64 characters. + + number_of_employees: Approximate headcount range. Used for vetting heuristics; pick the bucket that + contains your current employee count. + + organization_legal_type: + Legal-entity form. Pick the form that matches your incorporation documents: + + - `corporation` - C-corp or S-corp. + - `llc` - limited liability company. + - `partnership` - general/limited partnership. + - `nonprofit` - non-profit corporation, charitable trust, or + 501(c)(3)/equivalent. + - `other` - anything else (sole proprietorships, government bodies, DBAs, etc.). + You may be asked for additional documents during vetting. + + primary_business_domain_sic_code: The 4-digit Standard Industrial Classification code for your main line of + business, which tells us what industry you operate in. Look it up in the SIC + code directory if you are unsure. + + professional_license_number: If your business operates under a professional license (for example legal, + medical, or financial services), enter the license number issued by the + licensing authority. Leave blank if it does not apply. + + website: Your business's public website address, including https://. Leave blank if your + business has no website. extra_headers: Send extra headers @@ -948,6 +1153,7 @@ def list( self, *, filter_legal_name_contains: str | Omit = omit, + filter_role_type: Literal["enterprise", "bpo"] | Omit = omit, legal_name: str | Omit = omit, page_number: int | Omit = omit, page_size: int | Omit = omit, @@ -966,6 +1172,9 @@ def list( Args: filter_legal_name_contains: Case-insensitive partial match on legal name. + filter_role_type: Only return enterprises of this type: `bpo` for call-center (BPO) enterprises, + `enterprise` for normal enterprises. Omit to return both. + legal_name: Filter by legal name (partial match). page_number: 1-based page number. Out-of-range values return an empty page with correct meta. @@ -991,6 +1200,7 @@ def list( query=maybe_transform( { "filter_legal_name_contains": filter_legal_name_contains, + "filter_role_type": filter_role_type, "legal_name": legal_name, "page_number": page_number, "page_size": page_size, @@ -1055,8 +1265,8 @@ async def branded_calling( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> EnterprisePublicWrapped: - """ - Branded Calling is a paid product that must be activated on each enterprise. + """Branded Calling must be activated on each enterprise. + Activation is idempotent: - First call: marks the enterprise as activated and begins onboarding it with @@ -1071,11 +1281,15 @@ async def branded_calling( Failure modes: + - `400` - the account has no available credit. Add funds and retry. + - `400` - the enterprise is not in the United States. Branded Calling is + currently available only to US enterprises. - `403` - Branded Calling Terms of Service not accepted. - `404` - enterprise does not exist or does not belong to your account. - **Pricing:** This is a billable action. See https://telnyx.com/pricing/numbers - for current pricing. + **Pricing:** Activation itself is free, but the account must have available + credit. Branded Calling fees are charged per DIR and per branded call. See + https://telnyx.com/pricing/branded-calling for current pricing. Args: extra_headers: Send extra headers @@ -1132,6 +1346,14 @@ def dir(self) -> DirResourceWithRawResponse: """ return DirResourceWithRawResponse(self._enterprises.dir) + @cached_property + def verify_email(self) -> VerifyEmailResourceWithRawResponse: + """Verify ownership of a DIR's authorizer email. + + A short code is emailed and confirmed; the email must be verified before references can be submitted. + """ + return VerifyEmailResourceWithRawResponse(self._enterprises.verify_email) + class AsyncEnterprisesResourceWithRawResponse: def __init__(self, enterprises: AsyncEnterprisesResource) -> None: @@ -1168,6 +1390,14 @@ def dir(self) -> AsyncDirResourceWithRawResponse: """ return AsyncDirResourceWithRawResponse(self._enterprises.dir) + @cached_property + def verify_email(self) -> AsyncVerifyEmailResourceWithRawResponse: + """Verify ownership of a DIR's authorizer email. + + A short code is emailed and confirmed; the email must be verified before references can be submitted. + """ + return AsyncVerifyEmailResourceWithRawResponse(self._enterprises.verify_email) + class EnterprisesResourceWithStreamingResponse: def __init__(self, enterprises: EnterprisesResource) -> None: @@ -1204,6 +1434,14 @@ def dir(self) -> DirResourceWithStreamingResponse: """ return DirResourceWithStreamingResponse(self._enterprises.dir) + @cached_property + def verify_email(self) -> VerifyEmailResourceWithStreamingResponse: + """Verify ownership of a DIR's authorizer email. + + A short code is emailed and confirmed; the email must be verified before references can be submitted. + """ + return VerifyEmailResourceWithStreamingResponse(self._enterprises.verify_email) + class AsyncEnterprisesResourceWithStreamingResponse: def __init__(self, enterprises: AsyncEnterprisesResource) -> None: @@ -1239,3 +1477,11 @@ def dir(self) -> AsyncDirResourceWithStreamingResponse: A Display Identity Record (DIR) is the verified calling identity (display name, logo, call reasons) shown to recipients on outbound calls. """ return AsyncDirResourceWithStreamingResponse(self._enterprises.dir) + + @cached_property + def verify_email(self) -> AsyncVerifyEmailResourceWithStreamingResponse: + """Verify ownership of a DIR's authorizer email. + + A short code is emailed and confirmed; the email must be verified before references can be submitted. + """ + return AsyncVerifyEmailResourceWithStreamingResponse(self._enterprises.verify_email) diff --git a/src/telnyx/resources/enterprises/reputation/loa.py b/src/telnyx/resources/enterprises/reputation/loa.py index 1c99019fe..b2c4a686e 100644 --- a/src/telnyx/resources/enterprises/reputation/loa.py +++ b/src/telnyx/resources/enterprises/reputation/loa.py @@ -24,7 +24,6 @@ ) from ...._base_client import make_request_options from ....types.enterprises.reputation import loa_render_params, loa_update_params -from ....types.enterprises.reputation.agent_input_param import AgentInputParam from ....types.enterprises.enterprise_reputation_public_wrapped import EnterpriseReputationPublicWrapped __all__ = ["LoaResource", "AsyncLoaResource"] @@ -98,7 +97,7 @@ def render( self, enterprise_id: str, *, - agent: AgentInputParam | Omit = omit, + agent: loa_render_params.Agent | Omit = omit, signature: loa_render_params.Signature | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -219,7 +218,7 @@ async def render( self, enterprise_id: str, *, - agent: AgentInputParam | Omit = omit, + agent: loa_render_params.Agent | Omit = omit, signature: loa_render_params.Signature | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. diff --git a/src/telnyx/resources/enterprises/verify_email.py b/src/telnyx/resources/enterprises/verify_email.py new file mode 100644 index 000000000..7858d7597 --- /dev/null +++ b/src/telnyx/resources/enterprises/verify_email.py @@ -0,0 +1,287 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import httpx + +from ..._types import Body, Query, Headers, NotGiven, not_given +from ..._utils import path_template, maybe_transform, async_maybe_transform +from ..._compat import cached_property +from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ..._base_client import make_request_options +from ...types.enterprises import verify_email_confirm_params +from ...types.enterprises.enterprise_email_verification_status_wrapped import EnterpriseEmailVerificationStatusWrapped + +__all__ = ["VerifyEmailResource", "AsyncVerifyEmailResource"] + + +class VerifyEmailResource(SyncAPIResource): + """Verify ownership of a DIR's authorizer email. + + A short code is emailed and confirmed; the email must be verified before references can be submitted. + """ + + @cached_property + def with_raw_response(self) -> VerifyEmailResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/team-telnyx/telnyx-python#accessing-raw-response-data-eg-headers + """ + return VerifyEmailResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> VerifyEmailResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/team-telnyx/telnyx-python#with_streaming_response + """ + return VerifyEmailResourceWithStreamingResponse(self) + + def create( + self, + enterprise_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> EnterpriseEmailVerificationStatusWrapped: + """ + Email a 6-digit code to the enterprise account's contact email to confirm + ownership of that address. + + A BPO (Business Process Outsourcer) account has no DIR, so it proves ownership + of its own contact email here rather than through a DIR. A BPO account cannot be + approved for use until this contact email is verified. + + The code expires in 15 minutes. Requesting a new code invalidates any previous + one. Resends are rate limited (a short cooldown plus a daily cap). Submit the + code to `POST /enterprises/{enterprise_id}/verify_email/confirm`. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not enterprise_id: + raise ValueError(f"Expected a non-empty value for `enterprise_id` but received {enterprise_id!r}") + return self._post( + path_template("/enterprises/{enterprise_id}/verify_email", enterprise_id=enterprise_id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=EnterpriseEmailVerificationStatusWrapped, + ) + + def confirm( + self, + enterprise_id: str, + *, + code: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> EnterpriseEmailVerificationStatusWrapped: + """ + Submit the 6-digit code that was emailed to the enterprise account's contact + email. On success the contact email is marked verified. + + For security, any failure (wrong, expired, already-used, or too many attempts) + returns the same generic message. + + Args: + code: The 6-digit code sent to the enterprise account's contact email. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not enterprise_id: + raise ValueError(f"Expected a non-empty value for `enterprise_id` but received {enterprise_id!r}") + return self._post( + path_template("/enterprises/{enterprise_id}/verify_email/confirm", enterprise_id=enterprise_id), + body=maybe_transform({"code": code}, verify_email_confirm_params.VerifyEmailConfirmParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=EnterpriseEmailVerificationStatusWrapped, + ) + + +class AsyncVerifyEmailResource(AsyncAPIResource): + """Verify ownership of a DIR's authorizer email. + + A short code is emailed and confirmed; the email must be verified before references can be submitted. + """ + + @cached_property + def with_raw_response(self) -> AsyncVerifyEmailResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/team-telnyx/telnyx-python#accessing-raw-response-data-eg-headers + """ + return AsyncVerifyEmailResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncVerifyEmailResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/team-telnyx/telnyx-python#with_streaming_response + """ + return AsyncVerifyEmailResourceWithStreamingResponse(self) + + async def create( + self, + enterprise_id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> EnterpriseEmailVerificationStatusWrapped: + """ + Email a 6-digit code to the enterprise account's contact email to confirm + ownership of that address. + + A BPO (Business Process Outsourcer) account has no DIR, so it proves ownership + of its own contact email here rather than through a DIR. A BPO account cannot be + approved for use until this contact email is verified. + + The code expires in 15 minutes. Requesting a new code invalidates any previous + one. Resends are rate limited (a short cooldown plus a daily cap). Submit the + code to `POST /enterprises/{enterprise_id}/verify_email/confirm`. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not enterprise_id: + raise ValueError(f"Expected a non-empty value for `enterprise_id` but received {enterprise_id!r}") + return await self._post( + path_template("/enterprises/{enterprise_id}/verify_email", enterprise_id=enterprise_id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=EnterpriseEmailVerificationStatusWrapped, + ) + + async def confirm( + self, + enterprise_id: str, + *, + code: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> EnterpriseEmailVerificationStatusWrapped: + """ + Submit the 6-digit code that was emailed to the enterprise account's contact + email. On success the contact email is marked verified. + + For security, any failure (wrong, expired, already-used, or too many attempts) + returns the same generic message. + + Args: + code: The 6-digit code sent to the enterprise account's contact email. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not enterprise_id: + raise ValueError(f"Expected a non-empty value for `enterprise_id` but received {enterprise_id!r}") + return await self._post( + path_template("/enterprises/{enterprise_id}/verify_email/confirm", enterprise_id=enterprise_id), + body=await async_maybe_transform({"code": code}, verify_email_confirm_params.VerifyEmailConfirmParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=EnterpriseEmailVerificationStatusWrapped, + ) + + +class VerifyEmailResourceWithRawResponse: + def __init__(self, verify_email: VerifyEmailResource) -> None: + self._verify_email = verify_email + + self.create = to_raw_response_wrapper( + verify_email.create, + ) + self.confirm = to_raw_response_wrapper( + verify_email.confirm, + ) + + +class AsyncVerifyEmailResourceWithRawResponse: + def __init__(self, verify_email: AsyncVerifyEmailResource) -> None: + self._verify_email = verify_email + + self.create = async_to_raw_response_wrapper( + verify_email.create, + ) + self.confirm = async_to_raw_response_wrapper( + verify_email.confirm, + ) + + +class VerifyEmailResourceWithStreamingResponse: + def __init__(self, verify_email: VerifyEmailResource) -> None: + self._verify_email = verify_email + + self.create = to_streamed_response_wrapper( + verify_email.create, + ) + self.confirm = to_streamed_response_wrapper( + verify_email.confirm, + ) + + +class AsyncVerifyEmailResourceWithStreamingResponse: + def __init__(self, verify_email: AsyncVerifyEmailResource) -> None: + self._verify_email = verify_email + + self.create = async_to_streamed_response_wrapper( + verify_email.create, + ) + self.confirm = async_to_streamed_response_wrapper( + verify_email.confirm, + ) diff --git a/src/telnyx/resources/llm_token_gateway/__init__.py b/src/telnyx/resources/llm_token_gateway/__init__.py new file mode 100644 index 000000000..283ff2054 --- /dev/null +++ b/src/telnyx/resources/llm_token_gateway/__init__.py @@ -0,0 +1,33 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from .usage import ( + UsageResource, + AsyncUsageResource, + UsageResourceWithRawResponse, + AsyncUsageResourceWithRawResponse, + UsageResourceWithStreamingResponse, + AsyncUsageResourceWithStreamingResponse, +) +from .llm_token_gateway import ( + LlmTokenGatewayResource, + AsyncLlmTokenGatewayResource, + LlmTokenGatewayResourceWithRawResponse, + AsyncLlmTokenGatewayResourceWithRawResponse, + LlmTokenGatewayResourceWithStreamingResponse, + AsyncLlmTokenGatewayResourceWithStreamingResponse, +) + +__all__ = [ + "UsageResource", + "AsyncUsageResource", + "UsageResourceWithRawResponse", + "AsyncUsageResourceWithRawResponse", + "UsageResourceWithStreamingResponse", + "AsyncUsageResourceWithStreamingResponse", + "LlmTokenGatewayResource", + "AsyncLlmTokenGatewayResource", + "LlmTokenGatewayResourceWithRawResponse", + "AsyncLlmTokenGatewayResourceWithRawResponse", + "LlmTokenGatewayResourceWithStreamingResponse", + "AsyncLlmTokenGatewayResourceWithStreamingResponse", +] diff --git a/src/telnyx/resources/llm_token_gateway/llm_token_gateway.py b/src/telnyx/resources/llm_token_gateway/llm_token_gateway.py new file mode 100644 index 000000000..288d74768 --- /dev/null +++ b/src/telnyx/resources/llm_token_gateway/llm_token_gateway.py @@ -0,0 +1,108 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from .usage import ( + UsageResource, + AsyncUsageResource, + UsageResourceWithRawResponse, + AsyncUsageResourceWithRawResponse, + UsageResourceWithStreamingResponse, + AsyncUsageResourceWithStreamingResponse, +) +from ..._compat import cached_property +from ..._resource import SyncAPIResource, AsyncAPIResource + +__all__ = ["LlmTokenGatewayResource", "AsyncLlmTokenGatewayResource"] + + +class LlmTokenGatewayResource(SyncAPIResource): + @cached_property + def usage(self) -> UsageResource: + """Manage and report AI Gateway traffic.""" + return UsageResource(self._client) + + @cached_property + def with_raw_response(self) -> LlmTokenGatewayResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/team-telnyx/telnyx-python#accessing-raw-response-data-eg-headers + """ + return LlmTokenGatewayResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> LlmTokenGatewayResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/team-telnyx/telnyx-python#with_streaming_response + """ + return LlmTokenGatewayResourceWithStreamingResponse(self) + + +class AsyncLlmTokenGatewayResource(AsyncAPIResource): + @cached_property + def usage(self) -> AsyncUsageResource: + """Manage and report AI Gateway traffic.""" + return AsyncUsageResource(self._client) + + @cached_property + def with_raw_response(self) -> AsyncLlmTokenGatewayResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/team-telnyx/telnyx-python#accessing-raw-response-data-eg-headers + """ + return AsyncLlmTokenGatewayResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncLlmTokenGatewayResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/team-telnyx/telnyx-python#with_streaming_response + """ + return AsyncLlmTokenGatewayResourceWithStreamingResponse(self) + + +class LlmTokenGatewayResourceWithRawResponse: + def __init__(self, llm_token_gateway: LlmTokenGatewayResource) -> None: + self._llm_token_gateway = llm_token_gateway + + @cached_property + def usage(self) -> UsageResourceWithRawResponse: + """Manage and report AI Gateway traffic.""" + return UsageResourceWithRawResponse(self._llm_token_gateway.usage) + + +class AsyncLlmTokenGatewayResourceWithRawResponse: + def __init__(self, llm_token_gateway: AsyncLlmTokenGatewayResource) -> None: + self._llm_token_gateway = llm_token_gateway + + @cached_property + def usage(self) -> AsyncUsageResourceWithRawResponse: + """Manage and report AI Gateway traffic.""" + return AsyncUsageResourceWithRawResponse(self._llm_token_gateway.usage) + + +class LlmTokenGatewayResourceWithStreamingResponse: + def __init__(self, llm_token_gateway: LlmTokenGatewayResource) -> None: + self._llm_token_gateway = llm_token_gateway + + @cached_property + def usage(self) -> UsageResourceWithStreamingResponse: + """Manage and report AI Gateway traffic.""" + return UsageResourceWithStreamingResponse(self._llm_token_gateway.usage) + + +class AsyncLlmTokenGatewayResourceWithStreamingResponse: + def __init__(self, llm_token_gateway: AsyncLlmTokenGatewayResource) -> None: + self._llm_token_gateway = llm_token_gateway + + @cached_property + def usage(self) -> AsyncUsageResourceWithStreamingResponse: + """Manage and report AI Gateway traffic.""" + return AsyncUsageResourceWithStreamingResponse(self._llm_token_gateway.usage) diff --git a/src/telnyx/resources/llm_token_gateway/usage.py b/src/telnyx/resources/llm_token_gateway/usage.py new file mode 100644 index 000000000..886a7f311 --- /dev/null +++ b/src/telnyx/resources/llm_token_gateway/usage.py @@ -0,0 +1,232 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Union +from datetime import date + +import httpx + +from ..._types import Body, Query, Headers, NotGiven, not_given +from ..._utils import maybe_transform, async_maybe_transform +from ..._compat import cached_property +from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ..._base_client import make_request_options +from ...types.llm_token_gateway import usage_retrieve_summary_params +from ...types.llm_token_gateway.usage_retrieve_summary_response import UsageRetrieveSummaryResponse + +__all__ = ["UsageResource", "AsyncUsageResource"] + + +class UsageResource(SyncAPIResource): + """Manage and report AI Gateway traffic.""" + + @cached_property + def with_raw_response(self) -> UsageResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/team-telnyx/telnyx-python#accessing-raw-response-data-eg-headers + """ + return UsageResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> UsageResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/team-telnyx/telnyx-python#with_streaming_response + """ + return UsageResourceWithStreamingResponse(self) + + def retrieve_summary( + self, + *, + end_date: Union[str, date], + start_date: Union[str, date], + token_group_id: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> UsageRetrieveSummaryResponse: + """ + Return complete usage totals, UTC daily and model breakdowns, and guardrail + event counts for one token group owned by the authenticated account. Requires + the llm_token_gateway.usage.read permission; spend and guardrail read + permissions do not grant this combined report. All sections share one database + snapshot and include the latest usage corrections. Dates use an inclusive start + and exclusive end spanning 1 to 31 days. Only token_group_id, start_date and + end_date are accepted; pagination, group_by and other filters are rejected. + Spend is reference/enforcement USD, not invoice truth or BYOK provider charges. + Unknown cost is excluded from spend and reported through unknown_requests and + reserved_spend. Daily rows include zero-activity days. Model rows are ordered by + request count descending, then model name, and are limited to 1,000. Guardrail + counts count events, not distinct requests; recent_events contains at most 20 + newest events. A report that exceeds model or query limits returns 503 rather + than a truncated success. + + Args: + end_date: Exclusive UTC date in YYYY-MM-DD format. Must follow start_date by 1 to 31 days. + + start_date: Inclusive UTC date in YYYY-MM-DD format. Must precede end_date by 1 to 31 days. + + token_group_id: ID of a token group owned by the authenticated account. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._get( + "/llm_token_gateway/usage/summary", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "end_date": end_date, + "start_date": start_date, + "token_group_id": token_group_id, + }, + usage_retrieve_summary_params.UsageRetrieveSummaryParams, + ), + ), + cast_to=UsageRetrieveSummaryResponse, + ) + + +class AsyncUsageResource(AsyncAPIResource): + """Manage and report AI Gateway traffic.""" + + @cached_property + def with_raw_response(self) -> AsyncUsageResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/team-telnyx/telnyx-python#accessing-raw-response-data-eg-headers + """ + return AsyncUsageResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncUsageResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/team-telnyx/telnyx-python#with_streaming_response + """ + return AsyncUsageResourceWithStreamingResponse(self) + + async def retrieve_summary( + self, + *, + end_date: Union[str, date], + start_date: Union[str, date], + token_group_id: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> UsageRetrieveSummaryResponse: + """ + Return complete usage totals, UTC daily and model breakdowns, and guardrail + event counts for one token group owned by the authenticated account. Requires + the llm_token_gateway.usage.read permission; spend and guardrail read + permissions do not grant this combined report. All sections share one database + snapshot and include the latest usage corrections. Dates use an inclusive start + and exclusive end spanning 1 to 31 days. Only token_group_id, start_date and + end_date are accepted; pagination, group_by and other filters are rejected. + Spend is reference/enforcement USD, not invoice truth or BYOK provider charges. + Unknown cost is excluded from spend and reported through unknown_requests and + reserved_spend. Daily rows include zero-activity days. Model rows are ordered by + request count descending, then model name, and are limited to 1,000. Guardrail + counts count events, not distinct requests; recent_events contains at most 20 + newest events. A report that exceeds model or query limits returns 503 rather + than a truncated success. + + Args: + end_date: Exclusive UTC date in YYYY-MM-DD format. Must follow start_date by 1 to 31 days. + + start_date: Inclusive UTC date in YYYY-MM-DD format. Must precede end_date by 1 to 31 days. + + token_group_id: ID of a token group owned by the authenticated account. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._get( + "/llm_token_gateway/usage/summary", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform( + { + "end_date": end_date, + "start_date": start_date, + "token_group_id": token_group_id, + }, + usage_retrieve_summary_params.UsageRetrieveSummaryParams, + ), + ), + cast_to=UsageRetrieveSummaryResponse, + ) + + +class UsageResourceWithRawResponse: + def __init__(self, usage: UsageResource) -> None: + self._usage = usage + + self.retrieve_summary = to_raw_response_wrapper( + usage.retrieve_summary, + ) + + +class AsyncUsageResourceWithRawResponse: + def __init__(self, usage: AsyncUsageResource) -> None: + self._usage = usage + + self.retrieve_summary = async_to_raw_response_wrapper( + usage.retrieve_summary, + ) + + +class UsageResourceWithStreamingResponse: + def __init__(self, usage: UsageResource) -> None: + self._usage = usage + + self.retrieve_summary = to_streamed_response_wrapper( + usage.retrieve_summary, + ) + + +class AsyncUsageResourceWithStreamingResponse: + def __init__(self, usage: AsyncUsageResource) -> None: + self._usage = usage + + self.retrieve_summary = async_to_streamed_response_wrapper( + usage.retrieve_summary, + ) diff --git a/src/telnyx/resources/meeting_sessions/meeting_sessions.py b/src/telnyx/resources/meeting_sessions/meeting_sessions.py index b85190e01..05ee3487b 100644 --- a/src/telnyx/resources/meeting_sessions/meeting_sessions.py +++ b/src/telnyx/resources/meeting_sessions/meeting_sessions.py @@ -382,12 +382,12 @@ def delete_recording_media( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> MeetingSessionDeleteRecordingMediaResponse: """ - Irreversibly requests deletion of provider-hosted aggregate recording media - under the provider contract. The operation retains the Telnyx-local Meeting - session, transcript segments, events, artifacts, and usage records. It is - separate from `DELETE /meeting_sessions/{id}`, which stops or cancels - participation without deleting the persisted session. A missing/foreign session - returns 404; provider deletion failures return 502. + Irreversibly requests deletion of the aggregate recording media for the session. + The operation retains the Telnyx-local Meeting session, transcript segments, + events, artifacts, and usage records. It is separate from + `DELETE /meeting_sessions/{id}`, which stops or cancels participation without + deleting the persisted session. A missing/foreign session returns 404; provider + deletion failures return 502. Args: extra_headers: Send extra headers @@ -886,12 +886,12 @@ async def delete_recording_media( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> MeetingSessionDeleteRecordingMediaResponse: """ - Irreversibly requests deletion of provider-hosted aggregate recording media - under the provider contract. The operation retains the Telnyx-local Meeting - session, transcript segments, events, artifacts, and usage records. It is - separate from `DELETE /meeting_sessions/{id}`, which stops or cancels - participation without deleting the persisted session. A missing/foreign session - returns 404; provider deletion failures return 502. + Irreversibly requests deletion of the aggregate recording media for the session. + The operation retains the Telnyx-local Meeting session, transcript segments, + events, artifacts, and usage records. It is separate from + `DELETE /meeting_sessions/{id}`, which stops or cancels participation without + deleting the persisted session. A missing/foreign session returns 404; provider + deletion failures return 502. Args: extra_headers: Send extra headers diff --git a/src/telnyx/resources/spend_limits.py b/src/telnyx/resources/spend_limits.py new file mode 100644 index 000000000..65b997d58 --- /dev/null +++ b/src/telnyx/resources/spend_limits.py @@ -0,0 +1,803 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal, overload + +import httpx + +from ..types import SpendLimitPeriod, spend_limit_create_params, spend_limit_delete_params, spend_limit_update_params +from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given +from .._utils import path_template, required_args, maybe_transform, async_maybe_transform +from .._compat import cached_property +from .._resource import SyncAPIResource, AsyncAPIResource +from .._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from .._base_client import make_request_options +from ..types.spend_limit_period import SpendLimitPeriod +from ..types.spend_limit_response import SpendLimitResponse +from ..types.spend_limit_list_response import SpendLimitListResponse + +__all__ = ["SpendLimitsResource", "AsyncSpendLimitsResource"] + + +class SpendLimitsResource(SyncAPIResource): + """Daily and monthly spend limits per product. + + A limit applies to the organization of the authenticated user, or to the user's own account when they belong to no organization; every user of the organization sees and changes the same limits. + + - **Periods.** `daily` covers the current UTC day and `monthly` the current UTC calendar month. The two limits are independent: you can set either, both or neither. + - **Blocking.** When spend in a period goes above the limit (strictly greater), the product is blocked until the period ends: 00:00 UTC the next day for `daily`, 00:00 UTC on the 1st of the next month for `monthly`. A block appears within about 2 minutes (daily) or 10 minutes (monthly) of the spend being recorded. + - **Changes apply immediately.** Creating, updating or deleting a limit checks the period's spend in the same request: raising the limit above the spend, or removing it, lifts that period's block, and lowering it below the spend blocks the product at once. The `evaluation` object in the response says what happened. + - **Supported products.** Today only `inference` supports spend limits. A blocked account gets HTTP 403 with the error title `Inference spend limit reached` (code `10039`) on new billable chat completions, Responses, Anthropic Messages and classification requests; requests already running finish normally. Take the list of products from the list operation. + - **Limits set by Telnyx.** Telnyx support can also set a limit on your account. It is listed with `origin: operator` and you can update or delete it like your own. + """ + + @cached_property + def with_raw_response(self) -> SpendLimitsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/team-telnyx/telnyx-python#accessing-raw-response-data-eg-headers + """ + return SpendLimitsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> SpendLimitsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/team-telnyx/telnyx-python#with_streaming_response + """ + return SpendLimitsResourceWithStreamingResponse(self) + + @overload + def create( + self, + *, + amount: float, + product: str, + period: SpendLimitPeriod | Omit = omit, + reason: str | Omit = omit, + unlimited: Literal[False] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> SpendLimitResponse: + """Sets a limit for a product and period that has none. + + Send exactly one of + `amount` and `unlimited: true`. The period's spend is checked at once: if it is + already above the new limit, the product is blocked immediately + (`evaluation.blocked_now`). Returns 409 when a limit already exists for the + product and period; update it instead. + + Args: + amount: Limit in USD. `0` blocks at the first cent of spend. + + product: Product to limit, as returned in `product` by the list operation. + + period: `daily` is the current UTC day; `monthly` is the current UTC calendar month. + + reason: Why the limit is set or changed, kept for audit. + + unlimited: Optional; only `false` is allowed together with `amount`. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + def create( + self, + *, + product: str, + unlimited: Literal[True], + period: SpendLimitPeriod | Omit = omit, + reason: str | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> SpendLimitResponse: + """Sets a limit for a product and period that has none. + + Send exactly one of + `amount` and `unlimited: true`. The period's spend is checked at once: if it is + already above the new limit, the product is blocked immediately + (`evaluation.blocked_now`). Returns 409 when a limit already exists for the + product and period; update it instead. + + Args: + product: Product to limit, as returned in `product` by the list operation. + + unlimited: `true`: explicitly no cap. + + period: `daily` is the current UTC day; `monthly` is the current UTC calendar month. + + reason: Why the limit is set or changed, kept for audit. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @required_args(["amount", "product"], ["product", "unlimited"]) + def create( + self, + *, + amount: float | Omit = omit, + product: str, + period: SpendLimitPeriod | Omit = omit, + reason: str | Omit = omit, + unlimited: Literal[False] | Literal[True] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> SpendLimitResponse: + return self._post( + "/spend_limits", + body=maybe_transform( + { + "amount": amount, + "product": product, + "period": period, + "reason": reason, + "unlimited": unlimited, + }, + spend_limit_create_params.SpendLimitCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=SpendLimitResponse, + ) + + @overload + def update( + self, + product: str, + *, + amount: float, + period: SpendLimitPeriod | Omit = omit, + reason: str | Omit = omit, + unlimited: Literal[False] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> SpendLimitResponse: + """Replaces the value of the existing limit for the product and period. + + Send + exactly one of `amount` and `unlimited: true`. The period's spend is checked at + once: raising the limit above the spend lifts the period's block + (`evaluation.released`), and lowering it below the spend blocks the product + (`evaluation.blocked_now`). Returns 404 when no limit is set; create it instead. + + Args: + amount: Limit in USD. `0` blocks at the first cent of spend. + + period: Limit period. Defaults to `daily`; send it explicitly. + + reason: Why the limit is set or changed, kept for audit. + + unlimited: Optional; only `false` is allowed together with `amount`. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + def update( + self, + product: str, + *, + unlimited: Literal[True], + period: SpendLimitPeriod | Omit = omit, + reason: str | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> SpendLimitResponse: + """Replaces the value of the existing limit for the product and period. + + Send + exactly one of `amount` and `unlimited: true`. The period's spend is checked at + once: raising the limit above the spend lifts the period's block + (`evaluation.released`), and lowering it below the spend blocks the product + (`evaluation.blocked_now`). Returns 404 when no limit is set; create it instead. + + Args: + unlimited: `true`: explicitly no cap. + + period: Limit period. Defaults to `daily`; send it explicitly. + + reason: Why the limit is set or changed, kept for audit. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @required_args(["amount"], ["unlimited"]) + def update( + self, + product: str, + *, + amount: float | Omit = omit, + period: SpendLimitPeriod | Omit = omit, + reason: str | Omit = omit, + unlimited: Literal[False] | Literal[True] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> SpendLimitResponse: + if not product: + raise ValueError(f"Expected a non-empty value for `product` but received {product!r}") + return self._patch( + path_template("/spend_limits/{product}", product=product), + body=maybe_transform( + { + "amount": amount, + "reason": reason, + "unlimited": unlimited, + }, + spend_limit_update_params.SpendLimitUpdateParams, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform({"period": period}, spend_limit_update_params.SpendLimitUpdateParams), + ), + cast_to=SpendLimitResponse, + ) + + def list( + self, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> SpendLimitListResponse: + """ + Returns one entry per product and period you can set a limit on, with the limit, + the spend so far in the period and whether the product is blocked. An entry + without a limit is still listed (`limit: null`). When the spend cannot be read, + the entry is returned with `spend_usd: null` and `spend_error` set. The list is + not paginated. + """ + return self._get( + "/spend_limits", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=SpendLimitListResponse, + ) + + def delete( + self, + product: str, + *, + period: SpendLimitPeriod | Omit = omit, + reason: str | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> SpendLimitResponse: + """Removes the limit for the product and period. + + For `inference`, which has no + default limit, the product becomes unlimited for the period and the period's + block is lifted (`evaluation.released`). The response carries `limit: null` and + the `effective_limit_usd` that applies after the removal. Returns 404 when no + limit is set. + + Args: + period: Limit period. Defaults to `daily`; send it explicitly. + + reason: Why the limit is removed, kept for audit. At most 500 characters. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not product: + raise ValueError(f"Expected a non-empty value for `product` but received {product!r}") + return self._delete( + path_template("/spend_limits/{product}", product=product), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "period": period, + "reason": reason, + }, + spend_limit_delete_params.SpendLimitDeleteParams, + ), + ), + cast_to=SpendLimitResponse, + ) + + +class AsyncSpendLimitsResource(AsyncAPIResource): + """Daily and monthly spend limits per product. + + A limit applies to the organization of the authenticated user, or to the user's own account when they belong to no organization; every user of the organization sees and changes the same limits. + + - **Periods.** `daily` covers the current UTC day and `monthly` the current UTC calendar month. The two limits are independent: you can set either, both or neither. + - **Blocking.** When spend in a period goes above the limit (strictly greater), the product is blocked until the period ends: 00:00 UTC the next day for `daily`, 00:00 UTC on the 1st of the next month for `monthly`. A block appears within about 2 minutes (daily) or 10 minutes (monthly) of the spend being recorded. + - **Changes apply immediately.** Creating, updating or deleting a limit checks the period's spend in the same request: raising the limit above the spend, or removing it, lifts that period's block, and lowering it below the spend blocks the product at once. The `evaluation` object in the response says what happened. + - **Supported products.** Today only `inference` supports spend limits. A blocked account gets HTTP 403 with the error title `Inference spend limit reached` (code `10039`) on new billable chat completions, Responses, Anthropic Messages and classification requests; requests already running finish normally. Take the list of products from the list operation. + - **Limits set by Telnyx.** Telnyx support can also set a limit on your account. It is listed with `origin: operator` and you can update or delete it like your own. + """ + + @cached_property + def with_raw_response(self) -> AsyncSpendLimitsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/team-telnyx/telnyx-python#accessing-raw-response-data-eg-headers + """ + return AsyncSpendLimitsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncSpendLimitsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/team-telnyx/telnyx-python#with_streaming_response + """ + return AsyncSpendLimitsResourceWithStreamingResponse(self) + + @overload + async def create( + self, + *, + amount: float, + product: str, + period: SpendLimitPeriod | Omit = omit, + reason: str | Omit = omit, + unlimited: Literal[False] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> SpendLimitResponse: + """Sets a limit for a product and period that has none. + + Send exactly one of + `amount` and `unlimited: true`. The period's spend is checked at once: if it is + already above the new limit, the product is blocked immediately + (`evaluation.blocked_now`). Returns 409 when a limit already exists for the + product and period; update it instead. + + Args: + amount: Limit in USD. `0` blocks at the first cent of spend. + + product: Product to limit, as returned in `product` by the list operation. + + period: `daily` is the current UTC day; `monthly` is the current UTC calendar month. + + reason: Why the limit is set or changed, kept for audit. + + unlimited: Optional; only `false` is allowed together with `amount`. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + async def create( + self, + *, + product: str, + unlimited: Literal[True], + period: SpendLimitPeriod | Omit = omit, + reason: str | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> SpendLimitResponse: + """Sets a limit for a product and period that has none. + + Send exactly one of + `amount` and `unlimited: true`. The period's spend is checked at once: if it is + already above the new limit, the product is blocked immediately + (`evaluation.blocked_now`). Returns 409 when a limit already exists for the + product and period; update it instead. + + Args: + product: Product to limit, as returned in `product` by the list operation. + + unlimited: `true`: explicitly no cap. + + period: `daily` is the current UTC day; `monthly` is the current UTC calendar month. + + reason: Why the limit is set or changed, kept for audit. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @required_args(["amount", "product"], ["product", "unlimited"]) + async def create( + self, + *, + amount: float | Omit = omit, + product: str, + period: SpendLimitPeriod | Omit = omit, + reason: str | Omit = omit, + unlimited: Literal[False] | Literal[True] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> SpendLimitResponse: + return await self._post( + "/spend_limits", + body=await async_maybe_transform( + { + "amount": amount, + "product": product, + "period": period, + "reason": reason, + "unlimited": unlimited, + }, + spend_limit_create_params.SpendLimitCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=SpendLimitResponse, + ) + + @overload + async def update( + self, + product: str, + *, + amount: float, + period: SpendLimitPeriod | Omit = omit, + reason: str | Omit = omit, + unlimited: Literal[False] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> SpendLimitResponse: + """Replaces the value of the existing limit for the product and period. + + Send + exactly one of `amount` and `unlimited: true`. The period's spend is checked at + once: raising the limit above the spend lifts the period's block + (`evaluation.released`), and lowering it below the spend blocks the product + (`evaluation.blocked_now`). Returns 404 when no limit is set; create it instead. + + Args: + amount: Limit in USD. `0` blocks at the first cent of spend. + + period: Limit period. Defaults to `daily`; send it explicitly. + + reason: Why the limit is set or changed, kept for audit. + + unlimited: Optional; only `false` is allowed together with `amount`. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload + async def update( + self, + product: str, + *, + unlimited: Literal[True], + period: SpendLimitPeriod | Omit = omit, + reason: str | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> SpendLimitResponse: + """Replaces the value of the existing limit for the product and period. + + Send + exactly one of `amount` and `unlimited: true`. The period's spend is checked at + once: raising the limit above the spend lifts the period's block + (`evaluation.released`), and lowering it below the spend blocks the product + (`evaluation.blocked_now`). Returns 404 when no limit is set; create it instead. + + Args: + unlimited: `true`: explicitly no cap. + + period: Limit period. Defaults to `daily`; send it explicitly. + + reason: Why the limit is set or changed, kept for audit. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @required_args(["amount"], ["unlimited"]) + async def update( + self, + product: str, + *, + amount: float | Omit = omit, + period: SpendLimitPeriod | Omit = omit, + reason: str | Omit = omit, + unlimited: Literal[False] | Literal[True] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> SpendLimitResponse: + if not product: + raise ValueError(f"Expected a non-empty value for `product` but received {product!r}") + return await self._patch( + path_template("/spend_limits/{product}", product=product), + body=await async_maybe_transform( + { + "amount": amount, + "reason": reason, + "unlimited": unlimited, + }, + spend_limit_update_params.SpendLimitUpdateParams, + ), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform({"period": period}, spend_limit_update_params.SpendLimitUpdateParams), + ), + cast_to=SpendLimitResponse, + ) + + async def list( + self, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> SpendLimitListResponse: + """ + Returns one entry per product and period you can set a limit on, with the limit, + the spend so far in the period and whether the product is blocked. An entry + without a limit is still listed (`limit: null`). When the spend cannot be read, + the entry is returned with `spend_usd: null` and `spend_error` set. The list is + not paginated. + """ + return await self._get( + "/spend_limits", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=SpendLimitListResponse, + ) + + async def delete( + self, + product: str, + *, + period: SpendLimitPeriod | Omit = omit, + reason: str | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> SpendLimitResponse: + """Removes the limit for the product and period. + + For `inference`, which has no + default limit, the product becomes unlimited for the period and the period's + block is lifted (`evaluation.released`). The response carries `limit: null` and + the `effective_limit_usd` that applies after the removal. Returns 404 when no + limit is set. + + Args: + period: Limit period. Defaults to `daily`; send it explicitly. + + reason: Why the limit is removed, kept for audit. At most 500 characters. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not product: + raise ValueError(f"Expected a non-empty value for `product` but received {product!r}") + return await self._delete( + path_template("/spend_limits/{product}", product=product), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform( + { + "period": period, + "reason": reason, + }, + spend_limit_delete_params.SpendLimitDeleteParams, + ), + ), + cast_to=SpendLimitResponse, + ) + + +class SpendLimitsResourceWithRawResponse: + def __init__(self, spend_limits: SpendLimitsResource) -> None: + self._spend_limits = spend_limits + + self.create = to_raw_response_wrapper( + spend_limits.create, + ) + self.update = to_raw_response_wrapper( + spend_limits.update, + ) + self.list = to_raw_response_wrapper( + spend_limits.list, + ) + self.delete = to_raw_response_wrapper( + spend_limits.delete, + ) + + +class AsyncSpendLimitsResourceWithRawResponse: + def __init__(self, spend_limits: AsyncSpendLimitsResource) -> None: + self._spend_limits = spend_limits + + self.create = async_to_raw_response_wrapper( + spend_limits.create, + ) + self.update = async_to_raw_response_wrapper( + spend_limits.update, + ) + self.list = async_to_raw_response_wrapper( + spend_limits.list, + ) + self.delete = async_to_raw_response_wrapper( + spend_limits.delete, + ) + + +class SpendLimitsResourceWithStreamingResponse: + def __init__(self, spend_limits: SpendLimitsResource) -> None: + self._spend_limits = spend_limits + + self.create = to_streamed_response_wrapper( + spend_limits.create, + ) + self.update = to_streamed_response_wrapper( + spend_limits.update, + ) + self.list = to_streamed_response_wrapper( + spend_limits.list, + ) + self.delete = to_streamed_response_wrapper( + spend_limits.delete, + ) + + +class AsyncSpendLimitsResourceWithStreamingResponse: + def __init__(self, spend_limits: AsyncSpendLimitsResource) -> None: + self._spend_limits = spend_limits + + self.create = async_to_streamed_response_wrapper( + spend_limits.create, + ) + self.update = async_to_streamed_response_wrapper( + spend_limits.update, + ) + self.list = async_to_streamed_response_wrapper( + spend_limits.list, + ) + self.delete = async_to_streamed_response_wrapper( + spend_limits.delete, + ) diff --git a/src/telnyx/resources/whatsapp/phone_numbers/__init__.py b/src/telnyx/resources/whatsapp/phone_numbers/__init__.py index e2201d95d..32c2ec1d0 100644 --- a/src/telnyx/resources/whatsapp/phone_numbers/__init__.py +++ b/src/telnyx/resources/whatsapp/phone_numbers/__init__.py @@ -16,6 +16,14 @@ PhoneNumbersResourceWithStreamingResponse, AsyncPhoneNumbersResourceWithStreamingResponse, ) +from .calling_routing import ( + CallingRoutingResource, + AsyncCallingRoutingResource, + CallingRoutingResourceWithRawResponse, + AsyncCallingRoutingResourceWithRawResponse, + CallingRoutingResourceWithStreamingResponse, + AsyncCallingRoutingResourceWithStreamingResponse, +) from .calling_settings import ( CallingSettingsResource, AsyncCallingSettingsResource, @@ -52,6 +60,12 @@ "AsyncConversationalComponentsResourceWithRawResponse", "ConversationalComponentsResourceWithStreamingResponse", "AsyncConversationalComponentsResourceWithStreamingResponse", + "CallingRoutingResource", + "AsyncCallingRoutingResource", + "CallingRoutingResourceWithRawResponse", + "AsyncCallingRoutingResourceWithRawResponse", + "CallingRoutingResourceWithStreamingResponse", + "AsyncCallingRoutingResourceWithStreamingResponse", "PhoneNumbersResource", "AsyncPhoneNumbersResource", "PhoneNumbersResourceWithRawResponse", diff --git a/src/telnyx/resources/whatsapp/phone_numbers/calling_routing.py b/src/telnyx/resources/whatsapp/phone_numbers/calling_routing.py new file mode 100644 index 000000000..72e72c5ba --- /dev/null +++ b/src/telnyx/resources/whatsapp/phone_numbers/calling_routing.py @@ -0,0 +1,314 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Union + +import httpx + +from ...._types import Body, Query, Headers, NotGiven, not_given +from ...._utils import path_template, maybe_transform, async_maybe_transform +from ...._compat import cached_property +from ...._resource import SyncAPIResource, AsyncAPIResource +from ...._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ...._base_client import make_request_options +from ....types.whatsapp.phone_numbers import calling_routing_patch_all_params +from ....types.whatsapp.phone_numbers.calling_routing_list_response import CallingRoutingListResponse +from ....types.whatsapp.phone_numbers.calling_routing_patch_all_response import CallingRoutingPatchAllResponse + +__all__ = ["CallingRoutingResource", "AsyncCallingRoutingResource"] + + +class CallingRoutingResource(SyncAPIResource): + """Manage Whatsapp phone numbers""" + + @cached_property + def with_raw_response(self) -> CallingRoutingResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/team-telnyx/telnyx-python#accessing-raw-response-data-eg-headers + """ + return CallingRoutingResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> CallingRoutingResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/team-telnyx/telnyx-python#with_streaming_response + """ + return CallingRoutingResourceWithStreamingResponse(self) + + def list( + self, + id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> CallingRoutingListResponse: + """ + Retrieve the routing connection currently stored for a BYON (Bring Your Own + Number) phone number: the connection that inbound WhatsApp calls to the number + are delivered to. + + Use it to check the result of + `PATCH /whatsapp/phone_numbers/{id}/calling_routing`. A read made immediately + after an update can still return the previous value. + + Sub-users need read permission on connections. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return self._get( + path_template("/whatsapp/phone_numbers/{id}/calling_routing", id=id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=CallingRoutingListResponse, + ) + + def patch_all( + self, + id: str, + *, + connection_id: Union[str, int, None], + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> CallingRoutingPatchAllResponse: + """ + Set or clear the connection that inbound WhatsApp calls to a BYON (Bring Your + Own Number) phone number are delivered to. + + The update is processed asynchronously. A `202` response means the request was + accepted, not that the routing changed. Check the result with + `GET /whatsapp/phone_numbers/{id}/calling_routing`, which can return the + previous value immediately after an update. An update for a number that is not a + WhatsApp Calling number in the account returns 404. + + The connection must belong to the same account and must not be a WhatsApp + connection. Send `connection_id: null` to clear the routing; omitting + `connection_id` is rejected. Numbers active on Telnyx are rejected, because they + route through their own connection assignment. + + Sub-users need update permission on connections, and read permission to check + the result with `GET`. + + Args: + connection_id: ID of the connection to deliver inbound WhatsApp calls to: a positive integer up + to 9223372036854775807, sent as a decimal string or an integer. Send a string to + keep large IDs exact. Non-null values are returned as strings. `null` clears the + routing. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return self._patch( + path_template("/whatsapp/phone_numbers/{id}/calling_routing", id=id), + body=maybe_transform( + {"connection_id": connection_id}, calling_routing_patch_all_params.CallingRoutingPatchAllParams + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=CallingRoutingPatchAllResponse, + ) + + +class AsyncCallingRoutingResource(AsyncAPIResource): + """Manage Whatsapp phone numbers""" + + @cached_property + def with_raw_response(self) -> AsyncCallingRoutingResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/team-telnyx/telnyx-python#accessing-raw-response-data-eg-headers + """ + return AsyncCallingRoutingResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncCallingRoutingResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/team-telnyx/telnyx-python#with_streaming_response + """ + return AsyncCallingRoutingResourceWithStreamingResponse(self) + + async def list( + self, + id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> CallingRoutingListResponse: + """ + Retrieve the routing connection currently stored for a BYON (Bring Your Own + Number) phone number: the connection that inbound WhatsApp calls to the number + are delivered to. + + Use it to check the result of + `PATCH /whatsapp/phone_numbers/{id}/calling_routing`. A read made immediately + after an update can still return the previous value. + + Sub-users need read permission on connections. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return await self._get( + path_template("/whatsapp/phone_numbers/{id}/calling_routing", id=id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=CallingRoutingListResponse, + ) + + async def patch_all( + self, + id: str, + *, + connection_id: Union[str, int, None], + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> CallingRoutingPatchAllResponse: + """ + Set or clear the connection that inbound WhatsApp calls to a BYON (Bring Your + Own Number) phone number are delivered to. + + The update is processed asynchronously. A `202` response means the request was + accepted, not that the routing changed. Check the result with + `GET /whatsapp/phone_numbers/{id}/calling_routing`, which can return the + previous value immediately after an update. An update for a number that is not a + WhatsApp Calling number in the account returns 404. + + The connection must belong to the same account and must not be a WhatsApp + connection. Send `connection_id: null` to clear the routing; omitting + `connection_id` is rejected. Numbers active on Telnyx are rejected, because they + route through their own connection assignment. + + Sub-users need update permission on connections, and read permission to check + the result with `GET`. + + Args: + connection_id: ID of the connection to deliver inbound WhatsApp calls to: a positive integer up + to 9223372036854775807, sent as a decimal string or an integer. Send a string to + keep large IDs exact. Non-null values are returned as strings. `null` clears the + routing. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return await self._patch( + path_template("/whatsapp/phone_numbers/{id}/calling_routing", id=id), + body=await async_maybe_transform( + {"connection_id": connection_id}, calling_routing_patch_all_params.CallingRoutingPatchAllParams + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=CallingRoutingPatchAllResponse, + ) + + +class CallingRoutingResourceWithRawResponse: + def __init__(self, calling_routing: CallingRoutingResource) -> None: + self._calling_routing = calling_routing + + self.list = to_raw_response_wrapper( + calling_routing.list, + ) + self.patch_all = to_raw_response_wrapper( + calling_routing.patch_all, + ) + + +class AsyncCallingRoutingResourceWithRawResponse: + def __init__(self, calling_routing: AsyncCallingRoutingResource) -> None: + self._calling_routing = calling_routing + + self.list = async_to_raw_response_wrapper( + calling_routing.list, + ) + self.patch_all = async_to_raw_response_wrapper( + calling_routing.patch_all, + ) + + +class CallingRoutingResourceWithStreamingResponse: + def __init__(self, calling_routing: CallingRoutingResource) -> None: + self._calling_routing = calling_routing + + self.list = to_streamed_response_wrapper( + calling_routing.list, + ) + self.patch_all = to_streamed_response_wrapper( + calling_routing.patch_all, + ) + + +class AsyncCallingRoutingResourceWithStreamingResponse: + def __init__(self, calling_routing: AsyncCallingRoutingResource) -> None: + self._calling_routing = calling_routing + + self.list = async_to_streamed_response_wrapper( + calling_routing.list, + ) + self.patch_all = async_to_streamed_response_wrapper( + calling_routing.patch_all, + ) diff --git a/src/telnyx/resources/whatsapp/phone_numbers/phone_numbers.py b/src/telnyx/resources/whatsapp/phone_numbers/phone_numbers.py index 08a1c24ac..d801cdbf1 100644 --- a/src/telnyx/resources/whatsapp/phone_numbers/phone_numbers.py +++ b/src/telnyx/resources/whatsapp/phone_numbers/phone_numbers.py @@ -18,6 +18,14 @@ ) from ....pagination import SyncDefaultFlatPagination, AsyncDefaultFlatPagination from ...._base_client import AsyncPaginator, make_request_options +from .calling_routing import ( + CallingRoutingResource, + AsyncCallingRoutingResource, + CallingRoutingResourceWithRawResponse, + AsyncCallingRoutingResourceWithRawResponse, + CallingRoutingResourceWithStreamingResponse, + AsyncCallingRoutingResourceWithStreamingResponse, +) from .profile.profile import ( ProfileResource, AsyncProfileResource, @@ -77,6 +85,11 @@ def conversational_components(self) -> ConversationalComponentsResource: """Manage Whatsapp phone numbers""" return ConversationalComponentsResource(self._client) + @cached_property + def calling_routing(self) -> CallingRoutingResource: + """Manage Whatsapp phone numbers""" + return CallingRoutingResource(self._client) + @cached_property def with_raw_response(self) -> PhoneNumbersResourceWithRawResponse: """ @@ -389,6 +402,11 @@ def conversational_components(self) -> AsyncConversationalComponentsResource: """Manage Whatsapp phone numbers""" return AsyncConversationalComponentsResource(self._client) + @cached_property + def calling_routing(self) -> AsyncCallingRoutingResource: + """Manage Whatsapp phone numbers""" + return AsyncCallingRoutingResource(self._client) + @cached_property def with_raw_response(self) -> AsyncPhoneNumbersResourceWithRawResponse: """ @@ -724,6 +742,11 @@ def conversational_components(self) -> ConversationalComponentsResourceWithRawRe """Manage Whatsapp phone numbers""" return ConversationalComponentsResourceWithRawResponse(self._phone_numbers.conversational_components) + @cached_property + def calling_routing(self) -> CallingRoutingResourceWithRawResponse: + """Manage Whatsapp phone numbers""" + return CallingRoutingResourceWithRawResponse(self._phone_numbers.calling_routing) + class AsyncPhoneNumbersResourceWithRawResponse: def __init__(self, phone_numbers: AsyncPhoneNumbersResource) -> None: @@ -766,6 +789,11 @@ def conversational_components(self) -> AsyncConversationalComponentsResourceWith """Manage Whatsapp phone numbers""" return AsyncConversationalComponentsResourceWithRawResponse(self._phone_numbers.conversational_components) + @cached_property + def calling_routing(self) -> AsyncCallingRoutingResourceWithRawResponse: + """Manage Whatsapp phone numbers""" + return AsyncCallingRoutingResourceWithRawResponse(self._phone_numbers.calling_routing) + class PhoneNumbersResourceWithStreamingResponse: def __init__(self, phone_numbers: PhoneNumbersResource) -> None: @@ -808,6 +836,11 @@ def conversational_components(self) -> ConversationalComponentsResourceWithStrea """Manage Whatsapp phone numbers""" return ConversationalComponentsResourceWithStreamingResponse(self._phone_numbers.conversational_components) + @cached_property + def calling_routing(self) -> CallingRoutingResourceWithStreamingResponse: + """Manage Whatsapp phone numbers""" + return CallingRoutingResourceWithStreamingResponse(self._phone_numbers.calling_routing) + class AsyncPhoneNumbersResourceWithStreamingResponse: def __init__(self, phone_numbers: AsyncPhoneNumbersResource) -> None: @@ -849,3 +882,8 @@ def profile(self) -> AsyncProfileResourceWithStreamingResponse: def conversational_components(self) -> AsyncConversationalComponentsResourceWithStreamingResponse: """Manage Whatsapp phone numbers""" return AsyncConversationalComponentsResourceWithStreamingResponse(self._phone_numbers.conversational_components) + + @cached_property + def calling_routing(self) -> AsyncCallingRoutingResourceWithStreamingResponse: + """Manage Whatsapp phone numbers""" + return AsyncCallingRoutingResourceWithStreamingResponse(self._phone_numbers.calling_routing) diff --git a/src/telnyx/types/__init__.py b/src/telnyx/types/__init__.py index 81a32b344..9f7f9b270 100644 --- a/src/telnyx/types/__init__.py +++ b/src/telnyx/types/__init__.py @@ -82,6 +82,7 @@ from .offset_meta import OffsetMeta as OffsetMeta from .outbound_ip import OutboundIP as OutboundIP from .rcs_to_item import RcsToItem as RcsToItem +from .spend_limit import SpendLimit as SpendLimit from .uac_inbound import UacInbound as UacInbound from .call_bridged import CallBridged as CallBridged from .email_domain import EmailDomain as EmailDomain @@ -194,6 +195,7 @@ from .call_speak_started import CallSpeakStarted as CallSpeakStarted from .conference_created import ConferenceCreated as ConferenceCreated from .credential_inbound import CredentialInbound as CredentialInbound +from .dir_bpo_loa_params import DirBpoLoaParams as DirBpoLoaParams from .dir_new_loa_params import DirNewLoaParams as DirNewLoaParams from .doc_service_record import DocServiceRecord as DocServiceRecord from .email_dmarc_policy import EmailDmarcPolicy as EmailDmarcPolicy @@ -214,6 +216,7 @@ from .recording_response import RecordingResponse as RecordingResponse from .room_create_params import RoomCreateParams as RoomCreateParams from .room_update_params import RoomUpdateParams as RoomUpdateParams +from .spend_limit_period import SpendLimitPeriod as SpendLimitPeriod from .transport_protocol import TransportProtocol as TransportProtocol from .uac_outbound_param import UacOutboundParam as UacOutboundParam from .video_region_param import VideoRegionParam as VideoRegionParam @@ -225,6 +228,7 @@ from .call_siprec_stopped import CallSiprecStopped as CallSiprecStopped from .comment_list_params import CommentListParams as CommentListParams from .credential_outbound import CredentialOutbound as CredentialOutbound +from .dir_delete_response import DirDeleteResponse as DirDeleteResponse from .email_domain_status import EmailDomainStatus as EmailDomainStatus from .external_connection import ExternalConnection as ExternalConnection from .fax_create_response import FaxCreateResponse as FaxCreateResponse @@ -276,6 +280,7 @@ from .room_retrieve_params import RoomRetrieveParams as RoomRetrieveParams from .room_update_response import RoomUpdateResponse as RoomUpdateResponse from .sim_card_list_params import SimCardListParams as SimCardListParams +from .spend_limit_response import SpendLimitResponse as SpendLimitResponse from .suppressed_recipient import SuppressedRecipient as SuppressedRecipient from .telephony_credential import TelephonyCredential as TelephonyCredential from .texml_secrets_params import TexmlSecretsParams as TexmlSecretsParams @@ -397,6 +402,7 @@ from .report_list_mdrs_params import ReportListMdrsParams as ReportListMdrsParams from .report_list_wdrs_params import ReportListWdrsParams as ReportListWdrsParams from .requirement_list_params import RequirementListParams as RequirementListParams +from .signature_payload_param import SignaturePayloadParam as SignaturePayloadParam from .tracking_settings_param import TrackingSettingsParam as TrackingSettingsParam from .transcribe_client_event import TranscribeClientEvent as TranscribeClientEvent from .transcribe_server_event import TranscribeServerEvent as TranscribeServerEvent @@ -484,6 +490,10 @@ from .report_list_wdrs_response import ReportListWdrsResponse as ReportListWdrsResponse from .siprec_connector_response import SiprecConnectorResponse as SiprecConnectorResponse from .sound_modifications_param import SoundModificationsParam as SoundModificationsParam +from .spend_limit_create_params import SpendLimitCreateParams as SpendLimitCreateParams +from .spend_limit_delete_params import SpendLimitDeleteParams as SpendLimitDeleteParams +from .spend_limit_list_response import SpendLimitListResponse as SpendLimitListResponse +from .spend_limit_update_params import SpendLimitUpdateParams as SpendLimitUpdateParams from .stream_bidirectional_mode import StreamBidirectionalMode as StreamBidirectionalMode from .stream_client_event_param import StreamClientEventParam as StreamClientEventParam from .uac_inbound_request_param import UacInboundRequestParam as UacInboundRequestParam @@ -636,6 +646,7 @@ from .billing_group_delete_response import BillingGroupDeleteResponse as BillingGroupDeleteResponse from .billing_group_update_response import BillingGroupUpdateResponse as BillingGroupUpdateResponse from .bot_challenge_create_response import BotChallengeCreateResponse as BotChallengeCreateResponse +from .bpo_authorization_input_param import BpoAuthorizationInputParam as BpoAuthorizationInputParam from .bulk_sim_card_action_detailed import BulkSimCardActionDetailed as BulkSimCardActionDetailed from .call_left_queue_webhook_event import CallLeftQueueWebhookEvent as CallLeftQueueWebhookEvent from .call_reason_validate_response import CallReasonValidateResponse as CallReasonValidateResponse @@ -1132,6 +1143,9 @@ from .conference_speak_started_webhook_event import ( ConferenceSpeakStartedWebhookEvent as ConferenceSpeakStartedWebhookEvent, ) +from .dir_retrieve_bpo_authorizations_params import ( + DirRetrieveBpoAuthorizationsParams as DirRetrieveBpoAuthorizationsParams, +) from .dynamic_emergency_endpoint_list_params import ( DynamicEmergencyEndpointListParams as DynamicEmergencyEndpointListParams, ) @@ -1210,6 +1224,9 @@ from .call_control_application_outbound_param import ( CallControlApplicationOutboundParam as CallControlApplicationOutboundParam, ) +from .call_conversation_created_webhook_event import ( + CallConversationCreatedWebhookEvent as CallConversationCreatedWebhookEvent, +) from .conference_participant_playback_started import ( ConferenceParticipantPlaybackStarted as ConferenceParticipantPlaybackStarted, ) @@ -1318,6 +1335,9 @@ from .conversation_relay_embedded_config_param import ( ConversationRelayEmbeddedConfigParam as ConversationRelayEmbeddedConfigParam, ) +from .dir_retrieve_bpo_authorizations_response import ( + DirRetrieveBpoAuthorizationsResponse as DirRetrieveBpoAuthorizationsResponse, +) from .document_generate_download_link_response import ( DocumentGenerateDownloadLinkResponse as DocumentGenerateDownloadLinkResponse, ) @@ -1687,6 +1707,9 @@ from .call_ai_gather_message_history_updated_webhook_event import ( CallAIGatherMessageHistoryUpdatedWebhookEvent as CallAIGatherMessageHistoryUpdatedWebhookEvent, ) +from .call_machine_premium_detection_started_webhook_event import ( + CallMachinePremiumDetectionStartedWebhookEvent as CallMachinePremiumDetectionStartedWebhookEvent, +) from .managed_account_update_global_channel_limit_response import ( ManagedAccountUpdateGlobalChannelLimitResponse as ManagedAccountUpdateGlobalChannelLimitResponse, ) @@ -1723,6 +1746,9 @@ from .number_order_phone_number_update_requirement_group_params import ( NumberOrderPhoneNumberUpdateRequirementGroupParams as NumberOrderPhoneNumberUpdateRequirementGroupParams, ) +from .call_machine_premium_call_screening_detected_webhook_event import ( + CallMachinePremiumCallScreeningDetectedWebhookEvent as CallMachinePremiumCallScreeningDetectedWebhookEvent, +) from .well_known_retrieve_authorization_server_metadata_response import ( WellKnownRetrieveAuthorizationServerMetadataResponse as WellKnownRetrieveAuthorizationServerMetadataResponse, ) diff --git a/src/telnyx/types/ai/__init__.py b/src/telnyx/types/ai/__init__.py index f532cdc1b..1df63c49b 100644 --- a/src/telnyx/types/ai/__init__.py +++ b/src/telnyx/types/ai/__init__.py @@ -12,6 +12,7 @@ from .enabled_features import EnabledFeatures as EnabledFeatures from .tool_list_params import ToolListParams as ToolListParams from .hangup_tool_param import HangupToolParam as HangupToolParam +from .external_llm_param import ExternalLlmParam as ExternalLlmParam from .prompt_sync_status import PromptSyncStatus as PromptSyncStatus from .tool_create_params import ToolCreateParams as ToolCreateParams from .tool_update_params import ToolUpdateParams as ToolUpdateParams @@ -42,6 +43,7 @@ from .mcp_server_list_params import McpServerListParams as McpServerListParams from .privacy_settings_param import PrivacySettingsParam as PrivacySettingsParam from .assistant_create_params import AssistantCreateParams as AssistantCreateParams +from .assistant_delete_params import AssistantDeleteParams as AssistantDeleteParams from .assistant_update_params import AssistantUpdateParams as AssistantUpdateParams from .audio_transcribe_params import AudioTranscribeParams as AudioTranscribeParams from .cluster_retrieve_params import ClusterRetrieveParams as ClusterRetrieveParams @@ -56,8 +58,11 @@ from .mcp_server_update_params import McpServerUpdateParams as McpServerUpdateParams from .messaging_settings_param import MessagingSettingsParam as MessagingSettingsParam from .telephony_settings_param import TelephonySettingsParam as TelephonySettingsParam +from .websocket_settings_param import WebsocketSettingsParam as WebsocketSettingsParam from .assistant_retrieve_params import AssistantRetrieveParams as AssistantRetrieveParams from .assistant_send_sms_params import AssistantSendSMSParams as AssistantSendSMSParams +from .assistant_whatsapp_params import AssistantWhatsappParams as AssistantWhatsappParams +from .delegation_settings_param import DelegationSettingsParam as DelegationSettingsParam from .fallback_config_req_param import FallbackConfigReqParam as FallbackConfigReqParam from .start_speaking_plan_param import StartSpeakingPlanParam as StartSpeakingPlanParam from .assistant_a2_a_agent_param import AssistantA2AAgentParam as AssistantA2AAgentParam @@ -121,7 +126,9 @@ from .hangup_tool_params import HangupToolParams as HangupToolParams from .messaging_settings import MessagingSettings as MessagingSettings from .telephony_settings import TelephonySettings as TelephonySettings + from .websocket_settings import WebsocketSettings as WebsocketSettings from .collection_envelope import CollectionEnvelope as CollectionEnvelope + from .delegation_settings import DelegationSettings as DelegationSettings from .inference_embedding import InferenceEmbedding as InferenceEmbedding from .start_speaking_plan import StartSpeakingPlan as StartSpeakingPlan from .assistant_a2_a_agent import AssistantA2AAgent as AssistantA2AAgent @@ -142,6 +149,7 @@ from .conversation_list_response import ConversationListResponse as ConversationListResponse from .post_conversation_settings import PostConversationSettings as PostConversationSettings from .assistant_send_sms_response import AssistantSendSMSResponse as AssistantSendSMSResponse + from .assistant_whatsapp_response import AssistantWhatsappResponse as AssistantWhatsappResponse from .embedding_retrieve_response import EmbeddingRetrieveResponse as EmbeddingRetrieveResponse from .conversation_update_response import ConversationUpdateResponse as ConversationUpdateResponse from .transcription_settings_config import TranscriptionSettingsConfig as TranscriptionSettingsConfig @@ -191,6 +199,10 @@ def __getattr__(name: str) -> Any: from .conversation_flow import ConversationFlow return ConversationFlow + if name == "DelegationSettings": + from .delegation_settings import DelegationSettings + + return DelegationSettings if name == "ExternalLlm": from .external_llm import ExternalLlm @@ -287,6 +299,10 @@ def __getattr__(name: str) -> Any: from .transcription_settings_config import TranscriptionSettingsConfig return TranscriptionSettingsConfig + if name == "WebsocketSettings": + from .websocket_settings import WebsocketSettings + + return WebsocketSettings if name == "WidgetSettings": from .widget_settings import WidgetSettings @@ -303,6 +319,10 @@ def __getattr__(name: str) -> Any: from .assistant_send_sms_response import AssistantSendSMSResponse return AssistantSendSMSResponse + if name == "AssistantWhatsappResponse": + from .assistant_whatsapp_response import AssistantWhatsappResponse + + return AssistantWhatsappResponse if name == "AudioTranscriptionResponseWord": from .audio_transcription_response_word import AudioTranscriptionResponseWord diff --git a/src/telnyx/types/ai/assistant_create_params.py b/src/telnyx/types/ai/assistant_create_params.py index 3e8aee566..603678b29 100644 --- a/src/telnyx/types/ai/assistant_create_params.py +++ b/src/telnyx/types/ai/assistant_create_params.py @@ -7,24 +7,6 @@ from ..._types import SequenceNotStr from ..._utils import PropertyInfo -from .enabled_features import EnabledFeatures -from .assistant_tool_param import AssistantToolParam -from .widget_settings_param import WidgetSettingsParam -from .external_llm_req_param import ExternalLlmReqParam -from .insight_settings_param import InsightSettingsParam -from .privacy_settings_param import PrivacySettingsParam -from .observability_req_param import ObservabilityReqParam -from .messaging_settings_param import MessagingSettingsParam -from .telephony_settings_param import TelephonySettingsParam -from .fallback_config_req_param import FallbackConfigReqParam -from .assistant_a2_a_agent_param import AssistantA2AAgentParam -from .assistant_mcp_server_param import AssistantMcpServerParam -from .assistant_integration_param import AssistantIntegrationParam -from .conversation_flow_req_param import ConversationFlowReqParam -from .transcription_settings_param import TranscriptionSettingsParam -from .post_conversation_settings_req_param import PostConversationSettingsReqParam -from .inference_embedding_voice_settings_param import InferenceEmbeddingVoiceSettingsParam -from .inference_embedding_interruption_settings_param import InferenceEmbeddingInterruptionSettingsParam __all__ = ["AssistantCreateParams"] @@ -39,7 +21,7 @@ class AssistantCreateParams(TypedDict, total=False): name: Required[str] - a2a_agents: Iterable[AssistantA2AAgentParam] + a2a_agents: Iterable["AssistantA2AAgentParam"] """A2A agents this assistant can delegate to. Tools are not stored here: at the start of every conversation each agent's card @@ -52,7 +34,7 @@ class AssistantCreateParams(TypedDict, total=False): it does not fail the call. """ - conversation_flow: ConversationFlowReqParam + conversation_flow: "ConversationFlowReqParam" """Conversation flow as supplied by API clients (create / update). A directed graph of `FlowNodeReq` connected by `FlowEdge`s. Validation enforces @@ -60,6 +42,17 @@ class AssistantCreateParams(TypedDict, total=False): every edge's endpoints reference real nodes. """ + delegation_settings: "DelegationSettingsParam" + """ + Splits the conversation between a frontend model that talks to the caller and a + backend model that does the work. On the GPT-Live route the frontend model + cannot call tools at all — when it needs something done it raises a delegation + and waits. On the chat completion route the frontend keeps a single `delegate` + tool that returns immediately, so the conversation carries on while the backend + works. Either way the backend's answer is spoken as commentary or kept as silent + context, depending on `speak_results`. Beta feature. + """ + description: str dynamic_variables: Dict[str, object] @@ -85,11 +78,11 @@ class AssistantCreateParams(TypedDict, total=False): for the full request/response format and timeout behavior. """ - enabled_features: List[EnabledFeatures] + enabled_features: List["EnabledFeatures"] - external_llm: ExternalLlmReqParam + external_llm: "ExternalLlmReqParam" - fallback_config: FallbackConfigReqParam + fallback_config: "FallbackConfigReqParam" greeting: str """Text that the assistant will use to start the conversation. @@ -101,9 +94,9 @@ class AssistantCreateParams(TypedDict, total=False): have the assistant generate the greeting based on the system instructions. """ - insight_settings: InsightSettingsParam + insight_settings: "InsightSettingsParam" - integrations: Iterable[AssistantIntegrationParam] + integrations: Iterable["AssistantIntegrationParam"] """Connected integrations attached to the assistant. The catalog of available integrations is at `/ai/integrations`; the user's @@ -111,7 +104,7 @@ class AssistantCreateParams(TypedDict, total=False): references a catalog integration by `integration_id`. """ - interruption_settings: InferenceEmbeddingInterruptionSettingsParam + interruption_settings: "InferenceEmbeddingInterruptionSettingsParam" """ Settings for interruptions and how the assistant decides the user has finished speaking. These timings are most relevant when using non turn-taking @@ -131,13 +124,13 @@ class AssistantCreateParams(TypedDict, total=False): are unlikely to work with this integration. """ - mcp_servers: Iterable[AssistantMcpServerParam] + mcp_servers: Iterable["AssistantMcpServerParam"] """MCP servers attached to the assistant. Create MCP servers with `/ai/mcp_servers`, then reference them by `id` here. """ - messaging_settings: MessagingSettingsParam + messaging_settings: "MessagingSettingsParam" model: str """ID of the model to use when `external_llm` is not set. @@ -149,9 +142,9 @@ class AssistantCreateParams(TypedDict, total=False): provided, Telnyx applies the default model. """ - observability_settings: ObservabilityReqParam + observability_settings: "ObservabilityReqParam" - post_conversation_settings: PostConversationSettingsReqParam + post_conversation_settings: "PostConversationSettingsReqParam" """Configuration for post-conversation processing. When enabled, the assistant receives one additional LLM turn after the @@ -161,7 +154,7 @@ class AssistantCreateParams(TypedDict, total=False): hangup, transfer) are also unavailable. Beta feature. """ - privacy_settings: PrivacySettingsParam + privacy_settings: "PrivacySettingsParam" tags: SequenceNotStr[str] """Tags associated with the assistant. @@ -169,7 +162,7 @@ class AssistantCreateParams(TypedDict, total=False): Tags can also be managed with the assistant tag endpoints. """ - telephony_settings: TelephonySettingsParam + telephony_settings: "TelephonySettingsParam" tool_ids: SequenceNotStr[str] """IDs of shared tools to attach to the assistant. @@ -177,18 +170,49 @@ class AssistantCreateParams(TypedDict, total=False): New integrations should prefer `tool_ids` over inline `tools`. """ - tools: Iterable[AssistantToolParam] + tools: Iterable["AssistantToolParam"] """Deprecated for new integrations. Inline tool definitions available to the assistant. Prefer `tool_ids` to attach shared tools created with the AI Tools endpoints. """ - transcription: TranscriptionSettingsParam + transcription: "TranscriptionSettingsParam" + + voice_settings: "InferenceEmbeddingVoiceSettingsParam" - voice_settings: InferenceEmbeddingVoiceSettingsParam + websocket_settings: "WebsocketSettingsParam" + """ + Streams conversation and telephony events to a WebSocket server you host, and + accepts messages injected back into the conversation. Telnyx opens the + connection as a client, once per conversation. Delivery is best effort + throughout: while the connection is down events are dropped rather than queued, + and no socket failure is ever allowed to affect the call. Beta feature. + """ - widget_settings: WidgetSettingsParam + widget_settings: "WidgetSettingsParam" """Configuration settings for the assistant's web widget.""" idempotency_key: Annotated[str, PropertyInfo(alias="Idempotency-Key")] + + +from .enabled_features import EnabledFeatures +from .assistant_tool_param import AssistantToolParam +from .widget_settings_param import WidgetSettingsParam +from .external_llm_req_param import ExternalLlmReqParam +from .insight_settings_param import InsightSettingsParam +from .privacy_settings_param import PrivacySettingsParam +from .observability_req_param import ObservabilityReqParam +from .messaging_settings_param import MessagingSettingsParam +from .telephony_settings_param import TelephonySettingsParam +from .websocket_settings_param import WebsocketSettingsParam +from .delegation_settings_param import DelegationSettingsParam +from .fallback_config_req_param import FallbackConfigReqParam +from .assistant_a2_a_agent_param import AssistantA2AAgentParam +from .assistant_mcp_server_param import AssistantMcpServerParam +from .assistant_integration_param import AssistantIntegrationParam +from .conversation_flow_req_param import ConversationFlowReqParam +from .transcription_settings_param import TranscriptionSettingsParam +from .post_conversation_settings_req_param import PostConversationSettingsReqParam +from .inference_embedding_voice_settings_param import InferenceEmbeddingVoiceSettingsParam +from .inference_embedding_interruption_settings_param import InferenceEmbeddingInterruptionSettingsParam diff --git a/src/telnyx/types/ai/assistant_delete_params.py b/src/telnyx/types/ai/assistant_delete_params.py new file mode 100644 index 000000000..b7b7b290a --- /dev/null +++ b/src/telnyx/types/ai/assistant_delete_params.py @@ -0,0 +1,15 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import TypedDict + +__all__ = ["AssistantDeleteParams"] + + +class AssistantDeleteParams(TypedDict, total=False): + hard_delete: bool + """ + Permanently delete the assistant immediately instead of soft-deleting it to the + Recently Deleted list, where it stays restorable for 30 days. + """ diff --git a/src/telnyx/types/ai/assistant_param.py b/src/telnyx/types/ai/assistant_param.py index 6706a47d9..31eea639f 100644 --- a/src/telnyx/types/ai/assistant_param.py +++ b/src/telnyx/types/ai/assistant_param.py @@ -5,9 +5,6 @@ from typing import Union, Iterable from typing_extensions import TypeAlias, TypedDict -from .hangup_tool_param import HangupToolParam -from .webhook_tool_param import WebhookToolParam -from .transfer_tool_param import TransferToolParam from ..shared_params.book_appointment_tool import BookAppointmentTool from ..shared_params.check_availability_tool import CheckAvailabilityTool from ..shared_params.call_control_retrieval_tool import CallControlRetrievalTool @@ -17,9 +14,9 @@ Tool: TypeAlias = Union[ BookAppointmentTool, CheckAvailabilityTool, - WebhookToolParam, - HangupToolParam, - TransferToolParam, + "WebhookToolParam", + "HangupToolParam", + "TransferToolParam", CallControlRetrievalTool, ] @@ -46,3 +43,8 @@ class AssistantParam(TypedDict, total=False): tools: Iterable[Tool] """The tools that the voice assistant can use.""" + + +from .hangup_tool_param import HangupToolParam +from .webhook_tool_param import WebhookToolParam +from .transfer_tool_param import TransferToolParam diff --git a/src/telnyx/types/ai/assistant_tool_param.py b/src/telnyx/types/ai/assistant_tool_param.py index e9bf0d102..af4643a7d 100644 --- a/src/telnyx/types/ai/assistant_tool_param.py +++ b/src/telnyx/types/ai/assistant_tool_param.py @@ -6,12 +6,6 @@ from typing_extensions import Literal, Required, TypeAlias, TypedDict from ..._types import SequenceNotStr -from .retrieval_tool_param import RetrievalToolParam -from .pay_tool_params_param import PayToolParamsParam -from .hangup_tool_params_param import HangupToolParamsParam -from .openai.function_definition_param import FunctionDefinitionParam -from .update_dynamic_variables_tool_params_param import UpdateDynamicVariablesToolParamsParam -from .inference_embedding_webhook_tool_params_param import InferenceEmbeddingWebhookToolParamsParam __all__ = [ "AssistantToolParam", @@ -54,7 +48,7 @@ class Function(TypedDict, total=False): - function: Required[FunctionDefinitionParam] + function: Required["FunctionDefinitionParam"] type: Required[Literal["function"]] @@ -128,7 +122,7 @@ class Handoff(TypedDict, total=False): class Hangup(TypedDict, total=False): - hangup: Required[HangupToolParamsParam] + hangup: Required["HangupToolParamsParam"] type: Required[Literal["hangup"]] @@ -568,7 +562,7 @@ class Pay(TypedDict, total=False): (BETA) The pay tool allows the assistant to collect card payments from the caller via DTMF during the conversation. Recording is automatically paused while the pay tool is active and resumes when the payment flow completes. The connector_name must reference a pay connector configured in the Telnyx API. """ - pay: Required[PayToolParamsParam] + pay: Required["PayToolParamsParam"] type: Required[Literal["pay"]] @@ -580,15 +574,15 @@ class UpdateDynamicVariables(TypedDict, total=False): type: Required[Literal["update_dynamic_variables"]] - update_dynamic_variables: Required[UpdateDynamicVariablesToolParamsParam] + update_dynamic_variables: Required["UpdateDynamicVariablesToolParamsParam"] """Configuration for an update_dynamic_variables tool.""" AssistantToolParam: TypeAlias = Union[ Function, - InferenceEmbeddingWebhookToolParamsParam, + "InferenceEmbeddingWebhookToolParamsParam", ClientSideTool, - RetrievalToolParam, + "RetrievalToolParam", Handoff, Hangup, Transfer, @@ -600,3 +594,10 @@ class UpdateDynamicVariables(TypedDict, total=False): Pay, UpdateDynamicVariables, ] + +from .retrieval_tool_param import RetrievalToolParam +from .pay_tool_params_param import PayToolParamsParam +from .hangup_tool_params_param import HangupToolParamsParam +from .openai.function_definition_param import FunctionDefinitionParam +from .update_dynamic_variables_tool_params_param import UpdateDynamicVariablesToolParamsParam +from .inference_embedding_webhook_tool_params_param import InferenceEmbeddingWebhookToolParamsParam diff --git a/src/telnyx/types/ai/assistant_update_params.py b/src/telnyx/types/ai/assistant_update_params.py index 4032cc72a..7d544c985 100644 --- a/src/telnyx/types/ai/assistant_update_params.py +++ b/src/telnyx/types/ai/assistant_update_params.py @@ -6,30 +6,12 @@ from typing_extensions import TypedDict from ..._types import SequenceNotStr -from .enabled_features import EnabledFeatures -from .assistant_tool_param import AssistantToolParam -from .widget_settings_param import WidgetSettingsParam -from .external_llm_req_param import ExternalLlmReqParam -from .insight_settings_param import InsightSettingsParam -from .privacy_settings_param import PrivacySettingsParam -from .observability_req_param import ObservabilityReqParam -from .messaging_settings_param import MessagingSettingsParam -from .telephony_settings_param import TelephonySettingsParam -from .fallback_config_req_param import FallbackConfigReqParam -from .assistant_a2_a_agent_param import AssistantA2AAgentParam -from .assistant_mcp_server_param import AssistantMcpServerParam -from .assistant_integration_param import AssistantIntegrationParam -from .conversation_flow_req_param import ConversationFlowReqParam -from .transcription_settings_param import TranscriptionSettingsParam -from .post_conversation_settings_req_param import PostConversationSettingsReqParam -from .inference_embedding_voice_settings_param import InferenceEmbeddingVoiceSettingsParam -from .inference_embedding_interruption_settings_param import InferenceEmbeddingInterruptionSettingsParam __all__ = ["AssistantUpdateParams"] class AssistantUpdateParams(TypedDict, total=False): - a2a_agents: Iterable[AssistantA2AAgentParam] + a2a_agents: Iterable["AssistantA2AAgentParam"] """A2A agents this assistant can delegate to. Tools are not stored here: at the start of every conversation each agent's card @@ -43,7 +25,7 @@ class AssistantUpdateParams(TypedDict, total=False): unchanged; send an empty array to remove them all. """ - conversation_flow: ConversationFlowReqParam + conversation_flow: "ConversationFlowReqParam" """Conversation flow as supplied by API clients (create / update). A directed graph of `FlowNodeReq` connected by `FlowEdge`s. Validation enforces @@ -51,6 +33,17 @@ class AssistantUpdateParams(TypedDict, total=False): every edge's endpoints reference real nodes. """ + delegation_settings: "DelegationSettingsParam" + """ + Splits the conversation between a frontend model that talks to the caller and a + backend model that does the work. On the GPT-Live route the frontend model + cannot call tools at all — when it needs something done it raises a delegation + and waits. On the chat completion route the frontend keeps a single `delegate` + tool that returns immediately, so the conversation carries on while the backend + works. Either way the backend's answer is spoken as commentary or kept as silent + context, depending on `speak_results`. Beta feature. + """ + description: str dynamic_variables: Dict[str, object] @@ -76,11 +69,11 @@ class AssistantUpdateParams(TypedDict, total=False): for the full request/response format and timeout behavior. """ - enabled_features: List[EnabledFeatures] + enabled_features: List["EnabledFeatures"] - external_llm: ExternalLlmReqParam + external_llm: "ExternalLlmReqParam" - fallback_config: FallbackConfigReqParam + fallback_config: "FallbackConfigReqParam" greeting: str """Text that the assistant will use to start the conversation. @@ -92,7 +85,7 @@ class AssistantUpdateParams(TypedDict, total=False): have the assistant generate the greeting based on the system instructions. """ - insight_settings: InsightSettingsParam + insight_settings: "InsightSettingsParam" instructions: str """System instructions for the assistant. @@ -101,7 +94,7 @@ class AssistantUpdateParams(TypedDict, total=False): [dynamic variables](https://developers.telnyx.com/docs/inference/ai-assistants/dynamic-variables) """ - integrations: Iterable[AssistantIntegrationParam] + integrations: Iterable["AssistantIntegrationParam"] """Connected integrations attached to the assistant. The catalog of available integrations is at `/ai/integrations`; the user's @@ -109,7 +102,7 @@ class AssistantUpdateParams(TypedDict, total=False): references a catalog integration by `integration_id`. """ - interruption_settings: InferenceEmbeddingInterruptionSettingsParam + interruption_settings: "InferenceEmbeddingInterruptionSettingsParam" """ Settings for interruptions and how the assistant decides the user has finished speaking. These timings are most relevant when using non turn-taking @@ -129,13 +122,13 @@ class AssistantUpdateParams(TypedDict, total=False): are unlikely to work with this integration. """ - mcp_servers: Iterable[AssistantMcpServerParam] + mcp_servers: Iterable["AssistantMcpServerParam"] """MCP servers attached to the assistant. Create MCP servers with `/ai/mcp_servers`, then reference them by `id` here. """ - messaging_settings: MessagingSettingsParam + messaging_settings: "MessagingSettingsParam" model: str """ID of the model to use when `external_llm` is not set. @@ -149,9 +142,9 @@ class AssistantUpdateParams(TypedDict, total=False): name: str - observability_settings: ObservabilityReqParam + observability_settings: "ObservabilityReqParam" - post_conversation_settings: PostConversationSettingsReqParam + post_conversation_settings: "PostConversationSettingsReqParam" """Configuration for post-conversation processing. When enabled, the assistant receives one additional LLM turn after the @@ -161,7 +154,7 @@ class AssistantUpdateParams(TypedDict, total=False): hangup, transfer) are also unavailable. Beta feature. """ - privacy_settings: PrivacySettingsParam + privacy_settings: "PrivacySettingsParam" promote_to_main: bool """Indicates whether the assistant should be promoted to the main version. @@ -175,7 +168,7 @@ class AssistantUpdateParams(TypedDict, total=False): Tags can also be managed with the assistant tag endpoints. """ - telephony_settings: TelephonySettingsParam + telephony_settings: "TelephonySettingsParam" tool_ids: SequenceNotStr[str] """IDs of shared tools to attach to the assistant. @@ -187,7 +180,7 @@ class AssistantUpdateParams(TypedDict, total=False): type when an instance already exists returns HTTP 400 with error code 10015. """ - tools: Iterable[AssistantToolParam] + tools: Iterable["AssistantToolParam"] """Deprecated for new integrations. Inline tool definitions available to the assistant. Prefer `tool_ids` to attach @@ -201,12 +194,43 @@ class AssistantUpdateParams(TypedDict, total=False): array and manage them through `tool_ids` instead. """ - transcription: TranscriptionSettingsParam + transcription: "TranscriptionSettingsParam" version_name: str """Human-readable name for the assistant version.""" - voice_settings: InferenceEmbeddingVoiceSettingsParam + voice_settings: "InferenceEmbeddingVoiceSettingsParam" + + websocket_settings: "WebsocketSettingsParam" + """ + Streams conversation and telephony events to a WebSocket server you host, and + accepts messages injected back into the conversation. Telnyx opens the + connection as a client, once per conversation. Delivery is best effort + throughout: while the connection is down events are dropped rather than queued, + and no socket failure is ever allowed to affect the call. Beta feature. + """ - widget_settings: WidgetSettingsParam + widget_settings: "WidgetSettingsParam" """Configuration settings for the assistant's web widget.""" + + +from .enabled_features import EnabledFeatures +from .assistant_tool_param import AssistantToolParam +from .widget_settings_param import WidgetSettingsParam +from .external_llm_req_param import ExternalLlmReqParam +from .insight_settings_param import InsightSettingsParam +from .privacy_settings_param import PrivacySettingsParam +from .observability_req_param import ObservabilityReqParam +from .messaging_settings_param import MessagingSettingsParam +from .telephony_settings_param import TelephonySettingsParam +from .websocket_settings_param import WebsocketSettingsParam +from .delegation_settings_param import DelegationSettingsParam +from .fallback_config_req_param import FallbackConfigReqParam +from .assistant_a2_a_agent_param import AssistantA2AAgentParam +from .assistant_mcp_server_param import AssistantMcpServerParam +from .assistant_integration_param import AssistantIntegrationParam +from .conversation_flow_req_param import ConversationFlowReqParam +from .transcription_settings_param import TranscriptionSettingsParam +from .post_conversation_settings_req_param import PostConversationSettingsReqParam +from .inference_embedding_voice_settings_param import InferenceEmbeddingVoiceSettingsParam +from .inference_embedding_interruption_settings_param import InferenceEmbeddingInterruptionSettingsParam diff --git a/src/telnyx/types/ai/assistant_whatsapp_params.py b/src/telnyx/types/ai/assistant_whatsapp_params.py new file mode 100644 index 000000000..dab5c4502 --- /dev/null +++ b/src/telnyx/types/ai/assistant_whatsapp_params.py @@ -0,0 +1,38 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Dict, Union +from typing_extensions import Required, Annotated, TypedDict + +from ..._utils import PropertyInfo + +__all__ = ["AssistantWhatsappParams"] + + +class AssistantWhatsappParams(TypedDict, total=False): + content: Required[str] + """ + Instruction for the assistant, including the values for the template variables, + e.g. `Send the login verification code 482913 to the customer.` + """ + + from_: Required[Annotated[str, PropertyInfo(alias="from")]] + """WhatsApp number on your account to send from, in E.164 format. + + Its messaging profile must have this assistant configured. + """ + + to: Required[str] + """ + Customer to message, as an E.164 phone number or a WhatsApp business-scoped user + ID (BSUID). + """ + + conversation_metadata: Dict[str, Union[str, int, bool]] + """Metadata stored on the conversation. + + Keys starting with `telnyx_` and the `assistant_id` key are reserved. + """ + + idempotency_key: Annotated[str, PropertyInfo(alias="Idempotency-Key")] diff --git a/src/telnyx/types/ai/assistant_whatsapp_response.py b/src/telnyx/types/ai/assistant_whatsapp_response.py new file mode 100644 index 000000000..5eab9f3ba --- /dev/null +++ b/src/telnyx/types/ai/assistant_whatsapp_response.py @@ -0,0 +1,15 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from ..._models import BaseModel + +__all__ = ["AssistantWhatsappResponse"] + + +class AssistantWhatsappResponse(BaseModel): + conversation_id: str + """ID of the conversation created for this WhatsApp chat.""" + + message_id: str + """ID of the WhatsApp template message that was sent.""" diff --git a/src/telnyx/types/ai/assistants/__init__.py b/src/telnyx/types/ai/assistants/__init__.py index 1f42629d2..20376ccca 100644 --- a/src/telnyx/types/ai/assistants/__init__.py +++ b/src/telnyx/types/ai/assistants/__init__.py @@ -11,9 +11,11 @@ from .rule_input_param import RuleInputParam as RuleInputParam from .test_list_params import TestListParams as TestListParams from .tool_test_params import ToolTestParams as ToolTestParams +from .deleted_assistant import DeletedAssistant as DeletedAssistant from .rollout_slot_param import RolloutSlotParam as RolloutSlotParam from .test_create_params import TestCreateParams as TestCreateParams from .test_update_params import TestUpdateParams as TestUpdateParams +from .deleted_list_params import DeletedListParams as DeletedListParams from .version_update_params import VersionUpdateParams as VersionUpdateParams from .version_retrieve_params import VersionRetrieveParams as VersionRetrieveParams from .scheduled_event_response import ScheduledEventResponse as ScheduledEventResponse diff --git a/src/telnyx/types/ai/assistants/canary_deploy_create_params.py b/src/telnyx/types/ai/assistants/canary_deploy_create_params.py index 0023dc077..eaffe4f37 100644 --- a/src/telnyx/types/ai/assistants/canary_deploy_create_params.py +++ b/src/telnyx/types/ai/assistants/canary_deploy_create_params.py @@ -6,12 +6,14 @@ from typing_extensions import Annotated, TypedDict from ...._utils import PropertyInfo -from .rule_input_param import RuleInputParam __all__ = ["CanaryDeployCreateParams"] class CanaryDeployCreateParams(TypedDict, total=False): - rules: Iterable[RuleInputParam] + rules: Iterable["RuleInputParam"] idempotency_key: Annotated[str, PropertyInfo(alias="Idempotency-Key")] + + +from .rule_input_param import RuleInputParam diff --git a/src/telnyx/types/ai/assistants/canary_deploy_update_params.py b/src/telnyx/types/ai/assistants/canary_deploy_update_params.py index 281484154..feb712ff6 100644 --- a/src/telnyx/types/ai/assistants/canary_deploy_update_params.py +++ b/src/telnyx/types/ai/assistants/canary_deploy_update_params.py @@ -5,10 +5,11 @@ from typing import Iterable from typing_extensions import TypedDict -from .rule_input_param import RuleInputParam - __all__ = ["CanaryDeployUpdateParams"] class CanaryDeployUpdateParams(TypedDict, total=False): - rules: Iterable[RuleInputParam] + rules: Iterable["RuleInputParam"] + + +from .rule_input_param import RuleInputParam diff --git a/src/telnyx/types/ai/assistants/deleted_assistant.py b/src/telnyx/types/ai/assistants/deleted_assistant.py new file mode 100644 index 000000000..a8f08bde8 --- /dev/null +++ b/src/telnyx/types/ai/assistants/deleted_assistant.py @@ -0,0 +1,24 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from datetime import datetime + +from ..inference_embedding import InferenceEmbedding + +__all__ = ["DeletedAssistant"] + + +class DeletedAssistant(InferenceEmbedding): + """ + A soft-deleted assistant in the Recently Deleted list: the full assistant configuration plus deletion metadata. + """ + + deleted_at: datetime + """Timestamp of the soft delete.""" + + permanently_deleted_at: datetime + """ + Point after which the assistant is permanently deleted automatically and can no + longer be restored. + """ diff --git a/src/telnyx/types/ai/assistants/deleted_list_params.py b/src/telnyx/types/ai/assistants/deleted_list_params.py new file mode 100644 index 000000000..408c9bdc0 --- /dev/null +++ b/src/telnyx/types/ai/assistants/deleted_list_params.py @@ -0,0 +1,17 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Annotated, TypedDict + +from ...._utils import PropertyInfo + +__all__ = ["DeletedListParams"] + + +class DeletedListParams(TypedDict, total=False): + page_number: Annotated[int, PropertyInfo(alias="page[number]")] + """Page number to retrieve (1-based).""" + + page_size: Annotated[int, PropertyInfo(alias="page[size]")] + """Number of items to return per page.""" diff --git a/src/telnyx/types/ai/assistants/rule_input_param.py b/src/telnyx/types/ai/assistants/rule_input_param.py index 05f3d15dd..1e7acc19d 100644 --- a/src/telnyx/types/ai/assistants/rule_input_param.py +++ b/src/telnyx/types/ai/assistants/rule_input_param.py @@ -5,9 +5,6 @@ from typing import Iterable from typing_extensions import Required, TypedDict -from .serve_param import ServeParam -from .clause_param import ClauseParam - __all__ = ["RuleInputParam"] @@ -17,7 +14,7 @@ class RuleInputParam(TypedDict, total=False): An empty ``match`` is a catch-all (always fires). """ - serve: Required[ServeParam] + serve: Required["ServeParam"] """What a rule serves when matched. Exactly one of: @@ -27,4 +24,8 @@ class RuleInputParam(TypedDict, total=False): 100, with the leftover routing to the main version """ - match: Iterable[ClauseParam] + match: Iterable["ClauseParam"] + + +from .serve_param import ServeParam +from .clause_param import ClauseParam diff --git a/src/telnyx/types/ai/assistants/scheduled_event_create_params.py b/src/telnyx/types/ai/assistants/scheduled_event_create_params.py index deb343ceb..216ae0429 100644 --- a/src/telnyx/types/ai/assistants/scheduled_event_create_params.py +++ b/src/telnyx/types/ai/assistants/scheduled_event_create_params.py @@ -7,8 +7,6 @@ from typing_extensions import Required, Annotated, TypedDict from ...._utils import PropertyInfo -from .conversation_channel_type import ConversationChannelType -from .scheduled_call_settings_param import ScheduledCallSettingsParam __all__ = ["ScheduledEventCreateParams"] @@ -20,12 +18,12 @@ class ScheduledEventCreateParams(TypedDict, total=False): telnyx_agent_target: Required[str] """The phone number, SIP URI, to schedule the call or text from.""" - telnyx_conversation_channel: Required[ConversationChannelType] + telnyx_conversation_channel: Required["ConversationChannelType"] telnyx_end_user_target: Required[str] """The phone number, SIP URI, to schedule the call or text to.""" - call_settings: ScheduledCallSettingsParam + call_settings: "ScheduledCallSettingsParam" """ Per-call telephony overrides applied when a scheduled phone-call event dispatches. Phone-call events only. New per-call dispatch options should be @@ -58,3 +56,7 @@ class ScheduledEventCreateParams(TypedDict, total=False): """Required for sms scheduled events. The text to be sent to the end user.""" idempotency_key: Annotated[str, PropertyInfo(alias="Idempotency-Key")] + + +from .conversation_channel_type import ConversationChannelType +from .scheduled_call_settings_param import ScheduledCallSettingsParam diff --git a/src/telnyx/types/ai/assistants/scheduled_event_list_params.py b/src/telnyx/types/ai/assistants/scheduled_event_list_params.py index c2397537e..11cdd4e19 100644 --- a/src/telnyx/types/ai/assistants/scheduled_event_list_params.py +++ b/src/telnyx/types/ai/assistants/scheduled_event_list_params.py @@ -7,13 +7,12 @@ from typing_extensions import Annotated, TypedDict from ...._utils import PropertyInfo -from .conversation_channel_type import ConversationChannelType __all__ = ["ScheduledEventListParams"] class ScheduledEventListParams(TypedDict, total=False): - conversation_channel: ConversationChannelType + conversation_channel: "ConversationChannelType" """Filter results by conversation channel.""" from_date: Annotated[Union[str, datetime], PropertyInfo(format="iso8601")] @@ -25,3 +24,6 @@ class ScheduledEventListParams(TypedDict, total=False): to_date: Annotated[Union[str, datetime], PropertyInfo(format="iso8601")] """End of the date range filter (inclusive, ISO 8601).""" + + +from .conversation_channel_type import ConversationChannelType diff --git a/src/telnyx/types/ai/assistants/serve_param.py b/src/telnyx/types/ai/assistants/serve_param.py index 167c02a7a..9b6756801 100644 --- a/src/telnyx/types/ai/assistants/serve_param.py +++ b/src/telnyx/types/ai/assistants/serve_param.py @@ -5,8 +5,6 @@ from typing import Iterable from typing_extensions import TypedDict -from .rollout_slot_param import RolloutSlotParam - __all__ = ["ServeParam"] @@ -19,6 +17,9 @@ class ServeParam(TypedDict, total=False): less than 100, with the leftover routing to the main version """ - rollout: Iterable[RolloutSlotParam] + rollout: Iterable["RolloutSlotParam"] version_id: str + + +from .rollout_slot_param import RolloutSlotParam diff --git a/src/telnyx/types/ai/assistants/test_create_params.py b/src/telnyx/types/ai/assistants/test_create_params.py index b3a8de842..479be32a7 100644 --- a/src/telnyx/types/ai/assistants/test_create_params.py +++ b/src/telnyx/types/ai/assistants/test_create_params.py @@ -6,7 +6,6 @@ from typing_extensions import Required, Annotated, TypedDict from ...._utils import PropertyInfo -from .telnyx_conversation_channel import TelnyxConversationChannel __all__ = ["TestCreateParams", "Rubric"] @@ -49,7 +48,7 @@ class TestCreateParams(TypedDict, total=False): out. If not specified, uses system default timeout. """ - telnyx_conversation_channel: TelnyxConversationChannel + telnyx_conversation_channel: "TelnyxConversationChannel" """The communication channel through which the test will be conducted. Determines how the assistant will receive and respond to test messages. @@ -73,3 +72,6 @@ class Rubric(TypedDict, total=False): name: Required[str] """Label for the evaluation criterion, e.g., Empathy, Accuracy, Clarity.""" + + +from .telnyx_conversation_channel import TelnyxConversationChannel diff --git a/src/telnyx/types/ai/assistants/test_update_params.py b/src/telnyx/types/ai/assistants/test_update_params.py index ec1a65555..37e95ebe7 100644 --- a/src/telnyx/types/ai/assistants/test_update_params.py +++ b/src/telnyx/types/ai/assistants/test_update_params.py @@ -5,8 +5,6 @@ from typing import Iterable from typing_extensions import Required, TypedDict -from .telnyx_conversation_channel import TelnyxConversationChannel - __all__ = ["TestUpdateParams", "Rubric"] @@ -29,7 +27,7 @@ class TestUpdateParams(TypedDict, total=False): rubric: Iterable[Rubric] """Updated evaluation criteria for assessing assistant performance.""" - telnyx_conversation_channel: TelnyxConversationChannel + telnyx_conversation_channel: "TelnyxConversationChannel" """Updated communication channel for the test execution.""" test_suite: str @@ -45,3 +43,6 @@ class Rubric(TypedDict, total=False): name: Required[str] """Label for the evaluation criterion, e.g., Empathy, Accuracy, Clarity.""" + + +from .telnyx_conversation_channel import TelnyxConversationChannel diff --git a/src/telnyx/types/ai/assistants/version_update_params.py b/src/telnyx/types/ai/assistants/version_update_params.py index e01eff95a..7d7c5a0b2 100644 --- a/src/telnyx/types/ai/assistants/version_update_params.py +++ b/src/telnyx/types/ai/assistants/version_update_params.py @@ -15,6 +15,8 @@ from ..observability_req_param import ObservabilityReqParam from ..messaging_settings_param import MessagingSettingsParam from ..telephony_settings_param import TelephonySettingsParam +from ..websocket_settings_param import WebsocketSettingsParam +from ..delegation_settings_param import DelegationSettingsParam from ..fallback_config_req_param import FallbackConfigReqParam from ..assistant_a2_a_agent_param import AssistantA2AAgentParam from ..assistant_mcp_server_param import AssistantMcpServerParam @@ -53,6 +55,17 @@ class VersionUpdateParams(TypedDict, total=False): every edge's endpoints reference real nodes. """ + delegation_settings: DelegationSettingsParam + """ + Splits the conversation between a frontend model that talks to the caller and a + backend model that does the work. On the GPT-Live route the frontend model + cannot call tools at all — when it needs something done it raises a delegation + and waits. On the chat completion route the frontend keeps a single `delegate` + tool that returns immediately, so the conversation carries on while the backend + works. Either way the backend's answer is spoken as commentary or kept as silent + context, depending on `speak_results`. Beta feature. + """ + description: str dynamic_variables: Dict[str, object] @@ -204,5 +217,14 @@ class VersionUpdateParams(TypedDict, total=False): voice_settings: InferenceEmbeddingVoiceSettingsParam + websocket_settings: WebsocketSettingsParam + """ + Streams conversation and telephony events to a WebSocket server you host, and + accepts messages injected back into the conversation. Telnyx opens the + connection as a client, once per conversation. Delivery is best effort + throughout: while the connection is down events are dropped rather than queued, + and no socket failure is ever allowed to affect the call. Beta feature. + """ + widget_settings: WidgetSettingsParam """Configuration settings for the assistant's web widget.""" diff --git a/src/telnyx/types/ai/collection_create_params.py b/src/telnyx/types/ai/collection_create_params.py index 0359e4114..b9f2e13ec 100644 --- a/src/telnyx/types/ai/collection_create_params.py +++ b/src/telnyx/types/ai/collection_create_params.py @@ -5,9 +5,6 @@ from typing import Iterable from typing_extensions import Required, TypedDict -from .collections.source_request_param import SourceRequestParam -from .collections.retrieval_settings_wrapper_param import RetrievalSettingsWrapperParam - __all__ = ["CollectionCreateParams"] @@ -18,11 +15,15 @@ class CollectionCreateParams(TypedDict, total=False): description: str """Optional description.""" - settings: RetrievalSettingsWrapperParam + settings: "RetrievalSettingsWrapperParam" """Optional retrieval settings.""" slug: str """Optional slug (unique per organization). Derived from `name` when omitted.""" - sources: Iterable[SourceRequestParam] + sources: Iterable["SourceRequestParam"] """Optional sources to attach at creation time.""" + + +from .collections.source_request_param import SourceRequestParam +from .collections.retrieval_settings_wrapper_param import RetrievalSettingsWrapperParam diff --git a/src/telnyx/types/ai/collections/retrieval_settings_wrapper_param.py b/src/telnyx/types/ai/collections/retrieval_settings_wrapper_param.py index 0930db9d1..0bc3865b1 100644 --- a/src/telnyx/types/ai/collections/retrieval_settings_wrapper_param.py +++ b/src/telnyx/types/ai/collections/retrieval_settings_wrapper_param.py @@ -4,11 +4,12 @@ from typing_extensions import TypedDict -from .retrieval_settings_param import RetrievalSettingsParam - __all__ = ["RetrievalSettingsWrapperParam"] class RetrievalSettingsWrapperParam(TypedDict, total=False): - retrieval: RetrievalSettingsParam + retrieval: "RetrievalSettingsParam" """How documents are retrieved when searching the collection.""" + + +from .retrieval_settings_param import RetrievalSettingsParam diff --git a/src/telnyx/types/ai/collections/setting_create_params.py b/src/telnyx/types/ai/collections/setting_create_params.py index baa2e70a8..19ba6dc23 100644 --- a/src/telnyx/types/ai/collections/setting_create_params.py +++ b/src/telnyx/types/ai/collections/setting_create_params.py @@ -4,11 +4,12 @@ from typing_extensions import TypedDict -from .retrieval_settings_param import RetrievalSettingsParam - __all__ = ["SettingCreateParams"] class SettingCreateParams(TypedDict, total=False): - retrieval: RetrievalSettingsParam + retrieval: "RetrievalSettingsParam" """How documents are retrieved when searching the collection.""" + + +from .retrieval_settings_param import RetrievalSettingsParam diff --git a/src/telnyx/types/ai/collections/setting_patch_all_params.py b/src/telnyx/types/ai/collections/setting_patch_all_params.py index 28c5c7690..82c273e02 100644 --- a/src/telnyx/types/ai/collections/setting_patch_all_params.py +++ b/src/telnyx/types/ai/collections/setting_patch_all_params.py @@ -4,11 +4,12 @@ from typing_extensions import TypedDict -from .retrieval_settings_param import RetrievalSettingsParam - __all__ = ["SettingPatchAllParams"] class SettingPatchAllParams(TypedDict, total=False): - retrieval: RetrievalSettingsParam + retrieval: "RetrievalSettingsParam" """How documents are retrieved when searching the collection.""" + + +from .retrieval_settings_param import RetrievalSettingsParam diff --git a/src/telnyx/types/ai/collections/source_create_params.py b/src/telnyx/types/ai/collections/source_create_params.py index d8389d023..5c8f9b05e 100644 --- a/src/telnyx/types/ai/collections/source_create_params.py +++ b/src/telnyx/types/ai/collections/source_create_params.py @@ -4,13 +4,11 @@ from typing_extensions import Required, TypedDict -from .source_type import SourceType - __all__ = ["SourceCreateParams"] class SourceCreateParams(TypedDict, total=False): - source_type: Required[SourceType] + source_type: Required["SourceType"] """The type of Telnyx data attached as a source. `bucket` requires an additional `bucket_id`. Only `voice` is searchable today; @@ -23,3 +21,6 @@ class SourceCreateParams(TypedDict, total=False): Required when `source_type` is `bucket`; ignored otherwise. """ + + +from .source_type import SourceType diff --git a/src/telnyx/types/ai/collections/source_replace_params.py b/src/telnyx/types/ai/collections/source_replace_params.py index 27f5267e6..27d164183 100644 --- a/src/telnyx/types/ai/collections/source_replace_params.py +++ b/src/telnyx/types/ai/collections/source_replace_params.py @@ -5,10 +5,11 @@ from typing import Iterable from typing_extensions import Required, TypedDict -from .source_request_param import SourceRequestParam - __all__ = ["SourceReplaceParams"] class SourceReplaceParams(TypedDict, total=False): - sources: Required[Iterable[SourceRequestParam]] + sources: Required[Iterable["SourceRequestParam"]] + + +from .source_request_param import SourceRequestParam diff --git a/src/telnyx/types/ai/collections/source_request_param.py b/src/telnyx/types/ai/collections/source_request_param.py index 799448e37..6a8df0891 100644 --- a/src/telnyx/types/ai/collections/source_request_param.py +++ b/src/telnyx/types/ai/collections/source_request_param.py @@ -4,13 +4,11 @@ from typing_extensions import Required, TypedDict -from .source_type import SourceType - __all__ = ["SourceRequestParam"] class SourceRequestParam(TypedDict, total=False): - source_type: Required[SourceType] + source_type: Required["SourceType"] """The type of Telnyx data attached as a source. `bucket` requires an additional `bucket_id`. Only `voice` is searchable today; @@ -23,3 +21,6 @@ class SourceRequestParam(TypedDict, total=False): Required when `source_type` is `bucket`; ignored otherwise. """ + + +from .source_type import SourceType diff --git a/src/telnyx/types/ai/conversation_flow_req_param.py b/src/telnyx/types/ai/conversation_flow_req_param.py index 5bc9ae746..d7d9b2037 100644 --- a/src/telnyx/types/ai/conversation_flow_req_param.py +++ b/src/telnyx/types/ai/conversation_flow_req_param.py @@ -5,14 +5,9 @@ from typing import Union, Iterable from typing_extensions import Required, TypeAlias, TypedDict -from .flow_edge_param import FlowEdgeParam -from .flow_node_req_param import FlowNodeReqParam -from .tool_node_req_param import ToolNodeReqParam -from .speak_node_req_param import SpeakNodeReqParam - __all__ = ["ConversationFlowReqParam", "Node"] -Node: TypeAlias = Union[FlowNodeReqParam, ToolNodeReqParam, SpeakNodeReqParam] +Node: TypeAlias = Union["FlowNodeReqParam", "ToolNodeReqParam", "SpeakNodeReqParam"] class ConversationFlowReqParam(TypedDict, total=False): @@ -26,12 +21,18 @@ class ConversationFlowReqParam(TypedDict, total=False): nodes: Required[Iterable[Node]] """All nodes in the flow. - Must contain `start_node_id`. Each node is a prompt node (`type: prompt`) or a - tool node (`type: tool`). + Must contain `start_node_id`. Each node is a prompt node (`type: prompt`), a + tool node (`type: tool`), or a speak node (`type: speak`). """ start_node_id: Required[str] """ID of the node where the conversation begins.""" - edges: Iterable[FlowEdgeParam] + edges: Iterable["FlowEdgeParam"] """Directed transitions between nodes. May be empty for a single-node flow.""" + + +from .flow_edge_param import FlowEdgeParam +from .flow_node_req_param import FlowNodeReqParam +from .tool_node_req_param import ToolNodeReqParam +from .speak_node_req_param import SpeakNodeReqParam diff --git a/src/telnyx/types/ai/delegation_settings.py b/src/telnyx/types/ai/delegation_settings.py new file mode 100644 index 000000000..cf0fcbc53 --- /dev/null +++ b/src/telnyx/types/ai/delegation_settings.py @@ -0,0 +1,75 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Optional +from typing_extensions import Literal + +from ..._models import BaseModel +from .external_llm import ExternalLlm + +__all__ = ["DelegationSettings"] + + +class DelegationSettings(BaseModel): + """ + Splits the conversation between a frontend model that talks to the caller and a backend model that does the work. On the GPT-Live route the frontend model cannot call tools at all — when it needs something done it raises a delegation and waits. On the chat completion route the frontend keeps a single `delegate` tool that returns immediately, so the conversation carries on while the backend works. Either way the backend's answer is spoken as commentary or kept as silent context, depending on `speak_results`. Beta feature. + """ + + enabled: Optional[bool] = None + """Whether the assistant delegates work to a backend model. + + Defaults to `true`: a GPT-Live assistant with delegation disabled can hold a + conversation but can never look anything up or run a tool. + """ + + external_llm: Optional[ExternalLlm] = None + """ + Run the backend on your own OpenAI-compatible endpoint instead of a + Telnyx-hosted model. As above, a raw `api_key` here is rejected — reference an + integration secret with `external_llm.llm_api_key_ref` instead. + """ + + instructions: Optional[str] = None + """Extra instructions for the backend model, in addition to the assistant's own. + + Use this for the business rules the backend needs and the talking model does + not. + """ + + llm_api_key_ref: Optional[str] = None + """Integration secret identifier for the backend model's API key. + + Required for models from providers other than Telnyx, OpenAI and Anthropic. A + raw `api_key` is rejected rather than ignored, so that no plaintext credential + is stored on the assistant. + """ + + mode: Optional[Literal["telnyx", "client"]] = None + """Who answers a delegation. + + `telnyx` runs the backend model on Telnyx with the assistant's own tools, MCP + servers and observability. `client` relays the delegation to a server you host + over the WebSocket configured in `websocket_settings`: Telnyx sends a + `session.delegation.created` frame and waits for your + `session.delegation.completed` answer. That answer is text only, since the + socket offers no tool vocabulary. If no socket is connected the delegation is + refused and the assistant tells the caller it cannot look things up right now. + Defaults to `telnyx`. + """ + + model: Optional[str] = None + """The backend model that answers delegations. + + Must be a model available for AI Assistants. When enabling `telnyx` delegation, + explicitly set this field or `external_llm.model`; a configuration without + either backend model is rejected. Only applies when `mode` is `telnyx`. + """ + + speak_results: Optional[bool] = None + """Whether the backend's answer is spoken to the caller. + + When `true` the result is appended as commentary and paraphrased aloud; when + `false` it is kept as silent context that informs later answers without being + read out. Defaults to `true`. + """ diff --git a/src/telnyx/types/ai/delegation_settings_param.py b/src/telnyx/types/ai/delegation_settings_param.py new file mode 100644 index 000000000..6d363f515 --- /dev/null +++ b/src/telnyx/types/ai/delegation_settings_param.py @@ -0,0 +1,74 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal, TypedDict + +__all__ = ["DelegationSettingsParam"] + + +class DelegationSettingsParam(TypedDict, total=False): + """ + Splits the conversation between a frontend model that talks to the caller and a backend model that does the work. On the GPT-Live route the frontend model cannot call tools at all — when it needs something done it raises a delegation and waits. On the chat completion route the frontend keeps a single `delegate` tool that returns immediately, so the conversation carries on while the backend works. Either way the backend's answer is spoken as commentary or kept as silent context, depending on `speak_results`. Beta feature. + """ + + enabled: bool + """Whether the assistant delegates work to a backend model. + + Defaults to `true`: a GPT-Live assistant with delegation disabled can hold a + conversation but can never look anything up or run a tool. + """ + + external_llm: "ExternalLlmParam" + """ + Run the backend on your own OpenAI-compatible endpoint instead of a + Telnyx-hosted model. As above, a raw `api_key` here is rejected — reference an + integration secret with `external_llm.llm_api_key_ref` instead. + """ + + instructions: str + """Extra instructions for the backend model, in addition to the assistant's own. + + Use this for the business rules the backend needs and the talking model does + not. + """ + + llm_api_key_ref: str + """Integration secret identifier for the backend model's API key. + + Required for models from providers other than Telnyx, OpenAI and Anthropic. A + raw `api_key` is rejected rather than ignored, so that no plaintext credential + is stored on the assistant. + """ + + mode: Literal["telnyx", "client"] + """Who answers a delegation. + + `telnyx` runs the backend model on Telnyx with the assistant's own tools, MCP + servers and observability. `client` relays the delegation to a server you host + over the WebSocket configured in `websocket_settings`: Telnyx sends a + `session.delegation.created` frame and waits for your + `session.delegation.completed` answer. That answer is text only, since the + socket offers no tool vocabulary. If no socket is connected the delegation is + refused and the assistant tells the caller it cannot look things up right now. + Defaults to `telnyx`. + """ + + model: str + """The backend model that answers delegations. + + Must be a model available for AI Assistants. When enabling `telnyx` delegation, + explicitly set this field or `external_llm.model`; a configuration without + either backend model is rejected. Only applies when `mode` is `telnyx`. + """ + + speak_results: bool + """Whether the backend's answer is spoken to the caller. + + When `true` the result is appended as commentary and paraphrased aloud; when + `false` it is kept as silent context that informs later answers without being + read out. Defaults to `true`. + """ + + +from .external_llm_param import ExternalLlmParam diff --git a/src/telnyx/types/ai/external_llm_param.py b/src/telnyx/types/ai/external_llm_param.py new file mode 100644 index 000000000..38cb33288 --- /dev/null +++ b/src/telnyx/types/ai/external_llm_param.py @@ -0,0 +1,46 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, TypedDict + +__all__ = ["ExternalLlmParam"] + + +class ExternalLlmParam(TypedDict, total=False): + base_url: Required[str] + """Base URL for the external LLM endpoint.""" + + model: Required[str] + """Model identifier to use with the external LLM endpoint.""" + + authentication_method: "AuthenticationMethod" + """Authentication method used when connecting to the external LLM endpoint.""" + + certificate_ref: str + """ + Integration secret identifier for the client certificate used with certificate + authentication. + """ + + forward_metadata: bool + """ + When `true`, Telnyx forwards the assistant's dynamic variables to the external + LLM endpoint as a top-level `extra_metadata` object on the chat completion + request body. Defaults to `false`. Example payload sent to the external + endpoint: + `{"extra_metadata": {"customer_name": "Jane", "account_id": "acct_789", "telnyx_agent_target": "+13125550100", "telnyx_end_user_target": "+13125550123"}}`. + Distinct from OpenAI's native `metadata` field, which has its own size and type + limits. + """ + + llm_api_key_ref: str + """Integration secret identifier for the external LLM API key.""" + + token_retrieval_url: str + """ + URL used to retrieve an access token when certificate authentication is enabled. + """ + + +from .authentication_method import AuthenticationMethod diff --git a/src/telnyx/types/ai/external_llm_req_param.py b/src/telnyx/types/ai/external_llm_req_param.py index c85f63a63..0b4bf932d 100644 --- a/src/telnyx/types/ai/external_llm_req_param.py +++ b/src/telnyx/types/ai/external_llm_req_param.py @@ -4,8 +4,6 @@ from typing_extensions import Required, TypedDict -from .authentication_method import AuthenticationMethod - __all__ = ["ExternalLlmReqParam"] @@ -16,7 +14,7 @@ class ExternalLlmReqParam(TypedDict, total=False): model: Required[str] """Model identifier to use with the external LLM endpoint.""" - authentication_method: AuthenticationMethod + authentication_method: "AuthenticationMethod" """Authentication method used when connecting to the external LLM endpoint.""" certificate_ref: str @@ -43,3 +41,6 @@ class ExternalLlmReqParam(TypedDict, total=False): """ URL used to retrieve an access token when certificate authentication is enabled. """ + + +from .authentication_method import AuthenticationMethod diff --git a/src/telnyx/types/ai/fallback_config_req_param.py b/src/telnyx/types/ai/fallback_config_req_param.py index 69b14470d..5bc753384 100644 --- a/src/telnyx/types/ai/fallback_config_req_param.py +++ b/src/telnyx/types/ai/fallback_config_req_param.py @@ -4,13 +4,11 @@ from typing_extensions import TypedDict -from .external_llm_req_param import ExternalLlmReqParam - __all__ = ["FallbackConfigReqParam"] class FallbackConfigReqParam(TypedDict, total=False): - external_llm: ExternalLlmReqParam + external_llm: "ExternalLlmReqParam" llm_api_key_ref: str """Integration secret identifier for the fallback model API key.""" @@ -20,3 +18,6 @@ class FallbackConfigReqParam(TypedDict, total=False): Fallback Telnyx-hosted model to use when the primary LLM provider is unavailable. """ + + +from .external_llm_req_param import ExternalLlmReqParam diff --git a/src/telnyx/types/ai/flow_edge.py b/src/telnyx/types/ai/flow_edge.py index 9dc819e1f..83553f489 100644 --- a/src/telnyx/types/ai/flow_edge.py +++ b/src/telnyx/types/ai/flow_edge.py @@ -22,15 +22,26 @@ class ConditionLlmCondition(BaseModel): - """Edge condition evaluated by the LLM from a natural-language prompt. - - The model is asked to judge the prompt against conversation context and - returns true/false. Use this for fuzzy intents that aren't expressible as - a deterministic expression (e.g. 'user wants to escalate to a human'). + """Edge condition routed by the assistant's LLM from a natural-language + prompt. + + How the edge is decided depends on the channel. On calls, each outgoing + `llm` condition is offered to the assistant's model as a transition tool + alongside the assistant's tools, and the edge fires when the model + selects it; the platform does not evaluate the prompt itself, and + instructions that forbid or discourage tool calls can stop these edges + from firing. On chat channels, the edge prompts are evaluated in a + separate model call after the reply, which does not use the assistant's + instructions. Use this for fuzzy intents that aren't expressible as a + deterministic expression (e.g. 'user wants to escalate to a human'). """ prompt: str - """Natural-language criterion the LLM judges as true/false.""" + """Natural-language criterion the model routes on. + + On calls this is offered to the model as the transition tool's description; on + chat channels it is judged as a statement in the post-reply evaluation call. + """ type: Literal["llm"] @@ -129,8 +140,14 @@ class FlowEdge(BaseModel): The target is either another node in the same flow (`NodeTarget`) or a different assistant (`AssistantTarget`). Multiple edges may share a - `start_node_id`; the runtime evaluates them in the order they're - declared and takes the first whose condition is true. + `start_node_id`. On calls, `expression` conditions are evaluated before + the model turn and take precedence over `llm` conditions regardless of + declaration order, while `llm` conditions are offered to the assistant's + model as transition tools and fire when the model selects one. On chat + channels, an `expression` condition that is true when the turn begins + routes before the reply is generated; all conditioned edges that remain + are considered together in declaration order after the reply, and the + first true one wins. """ id: str diff --git a/src/telnyx/types/ai/flow_edge_param.py b/src/telnyx/types/ai/flow_edge_param.py index c91ba818f..884994283 100644 --- a/src/telnyx/types/ai/flow_edge_param.py +++ b/src/telnyx/types/ai/flow_edge_param.py @@ -5,8 +5,6 @@ from typing import Union from typing_extensions import Literal, Required, TypeAlias, TypedDict -from .node_position_param import NodePositionParam - __all__ = [ "FlowEdgeParam", "Condition", @@ -20,15 +18,26 @@ class ConditionLlmCondition(TypedDict, total=False): - """Edge condition evaluated by the LLM from a natural-language prompt. - - The model is asked to judge the prompt against conversation context and - returns true/false. Use this for fuzzy intents that aren't expressible as - a deterministic expression (e.g. 'user wants to escalate to a human'). + """Edge condition routed by the assistant's LLM from a natural-language + prompt. + + How the edge is decided depends on the channel. On calls, each outgoing + `llm` condition is offered to the assistant's model as a transition tool + alongside the assistant's tools, and the edge fires when the model + selects it; the platform does not evaluate the prompt itself, and + instructions that forbid or discourage tool calls can stop these edges + from firing. On chat channels, the edge prompts are evaluated in a + separate model call after the reply, which does not use the assistant's + instructions. Use this for fuzzy intents that aren't expressible as a + deterministic expression (e.g. 'user wants to escalate to a human'). """ prompt: Required[str] - """Natural-language criterion the LLM judges as true/false.""" + """Natural-language criterion the model routes on. + + On calls this is offered to the model as the transition tool's description; on + chat channels it is judged as a statement in the post-reply evaluation call. + """ type: Required[Literal["llm"]] @@ -97,7 +106,7 @@ class TargetAssistantTarget(TypedDict, total=False): type: Required[Literal["assistant"]] - position: NodePositionParam + position: "NodePositionParam" """ Optional canvas coordinates for rendering the target assistant as a node in authoring UIs. Pure presentation — the runtime ignores it; round-trips so @@ -124,8 +133,14 @@ class FlowEdgeParam(TypedDict, total=False): The target is either another node in the same flow (`NodeTarget`) or a different assistant (`AssistantTarget`). Multiple edges may share a - `start_node_id`; the runtime evaluates them in the order they're - declared and takes the first whose condition is true. + `start_node_id`. On calls, `expression` conditions are evaluated before + the model turn and take precedence over `llm` conditions regardless of + declaration order, while `llm` conditions are offered to the assistant's + model as transition tools and fire when the model selects one. On chat + channels, an `expression` condition that is true when the turn begins + routes before the reply is generated; all conditioned edges that remain + are considered together in declaration order after the reply, and the + first true one wins. """ id: Required[str] @@ -146,3 +161,6 @@ class FlowEdgeParam(TypedDict, total=False): Discriminated by `type`: `node` (jump to another node in this flow) or `assistant` (hand off to a different assistant). """ + + +from .node_position_param import NodePositionParam diff --git a/src/telnyx/types/ai/flow_node_req_param.py b/src/telnyx/types/ai/flow_node_req_param.py index b2e187275..0f00b374a 100644 --- a/src/telnyx/types/ai/flow_node_req_param.py +++ b/src/telnyx/types/ai/flow_node_req_param.py @@ -5,10 +5,6 @@ from typing_extensions import Literal, Required, TypedDict from ..._types import SequenceNotStr -from .node_position_param import NodePositionParam -from .external_llm_req_param import ExternalLlmReqParam -from .transcription_settings_param import TranscriptionSettingsParam -from .inference_embedding_voice_settings_param import InferenceEmbeddingVoiceSettingsParam __all__ = ["FlowNodeReqParam"] @@ -26,7 +22,7 @@ class FlowNodeReqParam(TypedDict, total=False): instructions: Required[str] """Prompt that drives the LLM while this node is active. Required.""" - external_llm: ExternalLlmReqParam + external_llm: "ExternalLlmReqParam" """Override for `Assistant.external_llm` while this node is active. Use this to route a node's turns to a different external LLM (different `model`, @@ -60,7 +56,7 @@ class FlowNodeReqParam(TypedDict, total=False): name: str """Optional human-readable label, displayed in authoring UIs.""" - position: NodePositionParam + position: "NodePositionParam" """Optional canvas coordinates used by authoring UIs to lay out the graph. Ignored by the runtime; round-trips so frontends can persist graph layout across @@ -82,7 +78,7 @@ class FlowNodeReqParam(TypedDict, total=False): null. """ - transcription: TranscriptionSettingsParam + transcription: "TranscriptionSettingsParam" """Per-node transcription override (model/language/region). Unset fields cascade from the assistant-level transcription. @@ -92,12 +88,18 @@ class FlowNodeReqParam(TypedDict, total=False): """Node kind discriminator. `prompt` (default) is an LLM-driven step; `tool` is a standalone tool execution - (see `ToolNodeReq`). + and `speak` a scripted message (see `ToolNodeReq` / `SpeakNodeReq`). """ - voice_settings: InferenceEmbeddingVoiceSettingsParam + voice_settings: "InferenceEmbeddingVoiceSettingsParam" """Per-node voice override. Only fields set here override the assistant-level voice settings; unset fields cascade. """ + + +from .node_position_param import NodePositionParam +from .external_llm_req_param import ExternalLlmReqParam +from .transcription_settings_param import TranscriptionSettingsParam +from .inference_embedding_voice_settings_param import InferenceEmbeddingVoiceSettingsParam diff --git a/src/telnyx/types/ai/hangup_tool_param.py b/src/telnyx/types/ai/hangup_tool_param.py index 9680aadd3..2300412f9 100644 --- a/src/telnyx/types/ai/hangup_tool_param.py +++ b/src/telnyx/types/ai/hangup_tool_param.py @@ -4,12 +4,13 @@ from typing_extensions import Literal, Required, TypedDict -from .hangup_tool_params_param import HangupToolParamsParam - __all__ = ["HangupToolParam"] class HangupToolParam(TypedDict, total=False): - hangup: Required[HangupToolParamsParam] + hangup: Required["HangupToolParamsParam"] type: Required[Literal["hangup"]] + + +from .hangup_tool_params_param import HangupToolParamsParam diff --git a/src/telnyx/types/ai/inference_embedding.py b/src/telnyx/types/ai/inference_embedding.py index 5f73a72f2..587494129 100644 --- a/src/telnyx/types/ai/inference_embedding.py +++ b/src/telnyx/types/ai/inference_embedding.py @@ -18,6 +18,8 @@ from .conversation_flow import ConversationFlow from .messaging_settings import MessagingSettings from .telephony_settings import TelephonySettings +from .websocket_settings import WebsocketSettings +from .delegation_settings import DelegationSettings from .assistant_a2_a_agent import AssistantA2AAgent from .assistant_mcp_server import AssistantMcpServer from .assistant_integration import AssistantIntegration @@ -69,6 +71,17 @@ class InferenceEmbedding(BaseModel): conversation_flow: Optional[ConversationFlow] = None """Conversation flow as returned by the API.""" + delegation_settings: Optional[DelegationSettings] = None + """ + Splits the conversation between a frontend model that talks to the caller and a + backend model that does the work. On the GPT-Live route the frontend model + cannot call tools at all — when it needs something done it raises a delegation + and waits. On the chat completion route the frontend keeps a single `delegate` + tool that returns immediately, so the conversation carries on while the backend + works. Either way the backend's answer is spoken as commentary or kept as silent + context, depending on `speak_results`. Beta feature. + """ + description: Optional[str] = None dynamic_variables: Optional[Dict[str, object]] = None @@ -202,5 +215,14 @@ class InferenceEmbedding(BaseModel): voice_settings: Optional[InferenceEmbeddingVoiceSettings] = None + websocket_settings: Optional[WebsocketSettings] = None + """ + Streams conversation and telephony events to a WebSocket server you host, and + accepts messages injected back into the conversation. Telnyx opens the + connection as a client, once per conversation. Delivery is best effort + throughout: while the connection is down events are dropped rather than queued, + and no socket failure is ever allowed to affect the call. Beta feature. + """ + widget_settings: Optional[WidgetSettings] = None """Configuration settings for the assistant's web widget.""" diff --git a/src/telnyx/types/ai/inference_embedding_interruption_settings_param.py b/src/telnyx/types/ai/inference_embedding_interruption_settings_param.py index 31917d7f4..89d7409b3 100644 --- a/src/telnyx/types/ai/inference_embedding_interruption_settings_param.py +++ b/src/telnyx/types/ai/inference_embedding_interruption_settings_param.py @@ -5,8 +5,6 @@ from typing import Optional from typing_extensions import TypedDict -from .start_speaking_plan_param import StartSpeakingPlanParam - __all__ = ["InferenceEmbeddingInterruptionSettingsParam"] @@ -27,10 +25,13 @@ class InferenceEmbeddingInterruptionSettingsParam(TypedDict, total=False): Set to null or 0.0 to disable interrupt prediction. """ - start_speaking_plan: StartSpeakingPlanParam + start_speaking_plan: "StartSpeakingPlanParam" """Controls when the assistant starts speaking after the user stops. These thresholds primarily apply to non turn-taking transcription models. For turn-taking models like `deepgram/flux`, end-of-turn detection is driven by the transcription end-of-turn settings under `transcription.settings` instead. """ + + +from .start_speaking_plan_param import StartSpeakingPlanParam diff --git a/src/telnyx/types/ai/inference_embedding_voice_settings.py b/src/telnyx/types/ai/inference_embedding_voice_settings.py index f0208c7d4..2ae2b675d 100644 --- a/src/telnyx/types/ai/inference_embedding_voice_settings.py +++ b/src/telnyx/types/ai/inference_embedding_voice_settings.py @@ -182,9 +182,10 @@ class InferenceEmbeddingVoiceSettings(BaseModel): """ voice_speed: Optional[float] = None - """The speed of the voice in the range [0.25, 2.0]. + """The speed of the voice in the range [0.6, 1.5]. - 1.0 is deafult speed. Larger numbers make the voice faster, smaller numbers make - it slower. This is only applicable for Telnyx Natural voices and Soniox voices - (0.7 to 1.3 for Soniox). + 1.0 is the default speed. Larger numbers make the voice faster, smaller numbers + make it slower. Applies to Telnyx `Ultra` voices; values outside this range are + rejected by the synthesis engine. Soniox voices support a speed range of 0.7 to + 1.3. """ diff --git a/src/telnyx/types/ai/inference_embedding_voice_settings_param.py b/src/telnyx/types/ai/inference_embedding_voice_settings_param.py index 5ec50a8ca..92c1757b4 100644 --- a/src/telnyx/types/ai/inference_embedding_voice_settings_param.py +++ b/src/telnyx/types/ai/inference_embedding_voice_settings_param.py @@ -180,9 +180,10 @@ class InferenceEmbeddingVoiceSettingsParam(TypedDict, total=False): """ voice_speed: float - """The speed of the voice in the range [0.25, 2.0]. + """The speed of the voice in the range [0.6, 1.5]. - 1.0 is deafult speed. Larger numbers make the voice faster, smaller numbers make - it slower. This is only applicable for Telnyx Natural voices and Soniox voices - (0.7 to 1.3 for Soniox). + 1.0 is the default speed. Larger numbers make the voice faster, smaller numbers + make it slower. Applies to Telnyx `Ultra` voices; values outside this range are + rejected by the synthesis engine. Soniox voices support a speed range of 0.7 to + 1.3. """ diff --git a/src/telnyx/types/ai/inference_embedding_webhook_tool_params.py b/src/telnyx/types/ai/inference_embedding_webhook_tool_params.py index 6a4f28a0c..92432807f 100644 --- a/src/telnyx/types/ai/inference_embedding_webhook_tool_params.py +++ b/src/telnyx/types/ai/inference_embedding_webhook_tool_params.py @@ -223,12 +223,6 @@ class Webhook(BaseModel): dot-notation path to the value in the response body. """ - timeout_ms: Optional[int] = None - """The maximum number of milliseconds to wait for the webhook to respond. - - Only applicable when async is false. - """ - class InferenceEmbeddingWebhookToolParams(BaseModel): type: Literal["webhook"] @@ -245,3 +239,11 @@ class InferenceEmbeddingWebhookToolParams(BaseModel): creates an inline duplicate (rejected with error code 10015 when the type allows only one instance per assistant). """ + + timeout_ms: Optional[int] = None + """ + The maximum number of milliseconds to wait for the webhook to respond before the + tool call is aborted. Set this at the tool level, as a sibling of `type` — a + `timeout_ms` nested inside the `webhook` object is stored but not applied, and + the tool runs at this default instead. Applies when `webhook.async` is false. + """ diff --git a/src/telnyx/types/ai/inference_embedding_webhook_tool_params_param.py b/src/telnyx/types/ai/inference_embedding_webhook_tool_params_param.py index 92ef036d6..810c50e51 100644 --- a/src/telnyx/types/ai/inference_embedding_webhook_tool_params_param.py +++ b/src/telnyx/types/ai/inference_embedding_webhook_tool_params_param.py @@ -224,14 +224,16 @@ class Webhook(_WebhookReservedKeywords, total=False): dot-notation path to the value in the response body. """ - timeout_ms: int - """The maximum number of milliseconds to wait for the webhook to respond. - - Only applicable when async is false. - """ - class InferenceEmbeddingWebhookToolParamsParam(TypedDict, total=False): type: Required[Literal["webhook"]] webhook: Required[Webhook] + + timeout_ms: int + """ + The maximum number of milliseconds to wait for the webhook to respond before the + tool call is aborted. Set this at the tool level, as a sibling of `type` — a + `timeout_ms` nested inside the `webhook` object is stored but not applied, and + the tool runs at this default instead. Applies when `webhook.async` is false. + """ diff --git a/src/telnyx/types/ai/memory/__init__.py b/src/telnyx/types/ai/memory/__init__.py index ffe1dc349..9d43f66b9 100644 --- a/src/telnyx/types/ai/memory/__init__.py +++ b/src/telnyx/types/ai/memory/__init__.py @@ -4,13 +4,30 @@ from typing import TYPE_CHECKING, Any +from .namespace_create_params import NamespaceCreateParams as NamespaceCreateParams + if TYPE_CHECKING: + from .namespace import Namespace as Namespace + from .namespace_list_response import NamespaceListResponse as NamespaceListResponse + from .namespace_create_response import NamespaceCreateResponse as NamespaceCreateResponse from .namespace_retrieve_response import NamespaceRetrieveResponse as NamespaceRetrieveResponse def __getattr__(name: str) -> Any: + if name == "Namespace": + from .namespace import Namespace + + return Namespace + if name == "NamespaceCreateResponse": + from .namespace_create_response import NamespaceCreateResponse + + return NamespaceCreateResponse if name == "NamespaceRetrieveResponse": from .namespace_retrieve_response import NamespaceRetrieveResponse return NamespaceRetrieveResponse + if name == "NamespaceListResponse": + from .namespace_list_response import NamespaceListResponse + + return NamespaceListResponse raise AttributeError(f"module {__name__!r} has no attribute {name!r}") diff --git a/src/telnyx/types/ai/memory/namespace.py b/src/telnyx/types/ai/memory/namespace.py new file mode 100644 index 000000000..cf9f25eb2 --- /dev/null +++ b/src/telnyx/types/ai/memory/namespace.py @@ -0,0 +1,20 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from ...._models import BaseModel + +__all__ = ["Namespace"] + + +class Namespace(BaseModel): + """An isolated memory store within your organization.""" + + id: str + """The namespace's unique identifier.""" + + name: str + """The namespace's name, used in the path. + + `default` exists for every organization. + """ diff --git a/src/telnyx/types/ai/memory/namespace_create_params.py b/src/telnyx/types/ai/memory/namespace_create_params.py new file mode 100644 index 000000000..bc6d932fa --- /dev/null +++ b/src/telnyx/types/ai/memory/namespace_create_params.py @@ -0,0 +1,12 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, TypedDict + +__all__ = ["NamespaceCreateParams"] + + +class NamespaceCreateParams(TypedDict, total=False): + name: Required[str] + """A name for the new namespace, unique within your organization.""" diff --git a/src/telnyx/types/ai/memory/namespace_create_response.py b/src/telnyx/types/ai/memory/namespace_create_response.py new file mode 100644 index 000000000..8d4ccf139 --- /dev/null +++ b/src/telnyx/types/ai/memory/namespace_create_response.py @@ -0,0 +1,13 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from .namespace import Namespace +from ...._models import BaseModel + +__all__ = ["NamespaceCreateResponse"] + + +class NamespaceCreateResponse(BaseModel): + data: Namespace + """An isolated memory store within your organization.""" diff --git a/src/telnyx/types/ai/memory/namespace_list_response.py b/src/telnyx/types/ai/memory/namespace_list_response.py new file mode 100644 index 000000000..cc714aacb --- /dev/null +++ b/src/telnyx/types/ai/memory/namespace_list_response.py @@ -0,0 +1,14 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import List + +from .namespace import Namespace +from ...._models import BaseModel + +__all__ = ["NamespaceListResponse"] + + +class NamespaceListResponse(BaseModel): + data: List[Namespace] diff --git a/src/telnyx/types/ai/mission_create_params.py b/src/telnyx/types/ai/mission_create_params.py index 26667874e..be10099ac 100644 --- a/src/telnyx/types/ai/mission_create_params.py +++ b/src/telnyx/types/ai/mission_create_params.py @@ -5,8 +5,6 @@ from typing import Dict from typing_extensions import Required, TypedDict -from .execution_mode import ExecutionMode - __all__ = ["MissionCreateParams"] @@ -15,10 +13,13 @@ class MissionCreateParams(TypedDict, total=False): description: str - execution_mode: ExecutionMode + execution_mode: "ExecutionMode" instructions: str metadata: Dict[str, object] model: str + + +from .execution_mode import ExecutionMode diff --git a/src/telnyx/types/ai/mission_update_mission_params.py b/src/telnyx/types/ai/mission_update_mission_params.py index c7ff1ce90..ca35dbbd7 100644 --- a/src/telnyx/types/ai/mission_update_mission_params.py +++ b/src/telnyx/types/ai/mission_update_mission_params.py @@ -5,15 +5,13 @@ from typing import Dict from typing_extensions import TypedDict -from .execution_mode import ExecutionMode - __all__ = ["MissionUpdateMissionParams"] class MissionUpdateMissionParams(TypedDict, total=False): description: str - execution_mode: ExecutionMode + execution_mode: "ExecutionMode" instructions: str @@ -22,3 +20,6 @@ class MissionUpdateMissionParams(TypedDict, total=False): model: str name: str + + +from .execution_mode import ExecutionMode diff --git a/src/telnyx/types/ai/missions/run_update_params.py b/src/telnyx/types/ai/missions/run_update_params.py index 92b74b7bf..223d9e3c6 100644 --- a/src/telnyx/types/ai/missions/run_update_params.py +++ b/src/telnyx/types/ai/missions/run_update_params.py @@ -5,8 +5,6 @@ from typing import Dict from typing_extensions import Required, TypedDict -from .run_status import RunStatus - __all__ = ["RunUpdateParams"] @@ -21,4 +19,7 @@ class RunUpdateParams(TypedDict, total=False): result_summary: str - status: RunStatus + status: "RunStatus" + + +from .run_status import RunStatus diff --git a/src/telnyx/types/ai/missions/runs/event_log_params.py b/src/telnyx/types/ai/missions/runs/event_log_params.py index 34fb45c74..cb167e876 100644 --- a/src/telnyx/types/ai/missions/runs/event_log_params.py +++ b/src/telnyx/types/ai/missions/runs/event_log_params.py @@ -5,8 +5,6 @@ from typing import Dict from typing_extensions import Required, TypedDict -from .event_type import EventType - __all__ = ["EventLogParams"] @@ -15,7 +13,7 @@ class EventLogParams(TypedDict, total=False): summary: Required[str] - type: Required[EventType] + type: Required["EventType"] agent_id: str @@ -25,3 +23,6 @@ class EventLogParams(TypedDict, total=False): payload: Dict[str, object] step_id: str + + +from .event_type import EventType diff --git a/src/telnyx/types/ai/missions/runs/plan_add_steps_to_plan_params.py b/src/telnyx/types/ai/missions/runs/plan_add_steps_to_plan_params.py index b13a94dcd..bb3be1afe 100644 --- a/src/telnyx/types/ai/missions/runs/plan_add_steps_to_plan_params.py +++ b/src/telnyx/types/ai/missions/runs/plan_add_steps_to_plan_params.py @@ -5,12 +5,13 @@ from typing import Iterable from typing_extensions import Required, TypedDict -from .create_plan_step_request_param import CreatePlanStepRequestParam - __all__ = ["PlanAddStepsToPlanParams"] class PlanAddStepsToPlanParams(TypedDict, total=False): mission_id: Required[str] - steps: Required[Iterable[CreatePlanStepRequestParam]] + steps: Required[Iterable["CreatePlanStepRequestParam"]] + + +from .create_plan_step_request_param import CreatePlanStepRequestParam diff --git a/src/telnyx/types/ai/missions/runs/plan_create_params.py b/src/telnyx/types/ai/missions/runs/plan_create_params.py index a04d3e698..ad6454e91 100644 --- a/src/telnyx/types/ai/missions/runs/plan_create_params.py +++ b/src/telnyx/types/ai/missions/runs/plan_create_params.py @@ -5,12 +5,13 @@ from typing import Iterable from typing_extensions import Required, TypedDict -from .create_plan_step_request_param import CreatePlanStepRequestParam - __all__ = ["PlanCreateParams"] class PlanCreateParams(TypedDict, total=False): mission_id: Required[str] - steps: Required[Iterable[CreatePlanStepRequestParam]] + steps: Required[Iterable["CreatePlanStepRequestParam"]] + + +from .create_plan_step_request_param import CreatePlanStepRequestParam diff --git a/src/telnyx/types/ai/missions/runs/plan_update_step_params.py b/src/telnyx/types/ai/missions/runs/plan_update_step_params.py index eed0bc951..34c4b3e19 100644 --- a/src/telnyx/types/ai/missions/runs/plan_update_step_params.py +++ b/src/telnyx/types/ai/missions/runs/plan_update_step_params.py @@ -5,8 +5,6 @@ from typing import Dict from typing_extensions import Required, TypedDict -from .step_status import StepStatus - __all__ = ["PlanUpdateStepParams"] @@ -17,4 +15,7 @@ class PlanUpdateStepParams(TypedDict, total=False): metadata: Dict[str, object] - status: StepStatus + status: "StepStatus" + + +from .step_status import StepStatus diff --git a/src/telnyx/types/ai/observability_req_param.py b/src/telnyx/types/ai/observability_req_param.py index 73fae261a..9678dc420 100644 --- a/src/telnyx/types/ai/observability_req_param.py +++ b/src/telnyx/types/ai/observability_req_param.py @@ -4,9 +4,6 @@ from typing_extensions import TypedDict -from .prompt_sync_status import PromptSyncStatus -from .observability_status import ObservabilityStatus - __all__ = ["ObservabilityReqParam"] @@ -17,7 +14,7 @@ class ObservabilityReqParam(TypedDict, total=False): prompt_name: str - prompt_sync: PromptSyncStatus + prompt_sync: "PromptSyncStatus" """Whether to auto-publish the assistant's instructions as a Langfuse prompt. When ENABLED + prompt_name set, every assistant create/update pushes @@ -31,4 +28,8 @@ class ObservabilityReqParam(TypedDict, total=False): secret_key_ref: str - status: ObservabilityStatus + status: "ObservabilityStatus" + + +from .prompt_sync_status import PromptSyncStatus +from .observability_status import ObservabilityStatus diff --git a/src/telnyx/types/ai/openai/chat_create_completion_params.py b/src/telnyx/types/ai/openai/chat_create_completion_params.py index 8595202f5..3ceef2a07 100644 --- a/src/telnyx/types/ai/openai/chat_create_completion_params.py +++ b/src/telnyx/types/ai/openai/chat_create_completion_params.py @@ -2,12 +2,11 @@ from __future__ import annotations -from typing import Dict, Union, Iterable +from typing import Dict, Union, Iterable, Optional from typing_extensions import Literal, Required, TypeAlias, TypedDict from ...._types import SequenceNotStr from ..bucket_ids_param import BucketIDsParam -from .function_definition_param import FunctionDefinitionParam __all__ = [ "ChatCreateCompletionParams", @@ -70,8 +69,15 @@ class ChatCreateCompletionParams(TypedDict, total=False): `content` of `message`. """ - max_tokens: int - """Maximum number of completion tokens the model should generate.""" + max_tokens: Optional[int] + """Maximum number of completion (output) tokens the model may generate per request. + + Defaults to 8192 when omitted or `null`. Set a higher value to allow longer + completions. The model's `max_completion_tokens` metadata (see + `GET /ai/models`), when set, caps both the default and any larger explicit + value. Reasoning models consume this budget across reasoning and answer tokens + combined. + """ min_p: float """ @@ -268,7 +274,7 @@ class ResponseFormatResponseFormatJsonSchemaParam(TypedDict, total=False): class ToolFunction(TypedDict, total=False): - function: Required[FunctionDefinitionParam] + function: Required["FunctionDefinitionParam"] type: Required[Literal["function"]] @@ -280,3 +286,5 @@ class ToolRetrieval(TypedDict, total=False): Tool: TypeAlias = Union[ToolFunction, ToolRetrieval] + +from .function_definition_param import FunctionDefinitionParam diff --git a/src/telnyx/types/ai/retrieval_tool_param.py b/src/telnyx/types/ai/retrieval_tool_param.py index 3d283bfcb..35413dd53 100644 --- a/src/telnyx/types/ai/retrieval_tool_param.py +++ b/src/telnyx/types/ai/retrieval_tool_param.py @@ -4,12 +4,13 @@ from typing_extensions import Literal, Required, TypedDict -from .bucket_ids_param import BucketIDsParam - __all__ = ["RetrievalToolParam"] class RetrievalToolParam(TypedDict, total=False): - retrieval: Required[BucketIDsParam] + retrieval: Required["BucketIDsParam"] type: Required[Literal["retrieval"]] + + +from .bucket_ids_param import BucketIDsParam diff --git a/src/telnyx/types/ai/speak_node_req_param.py b/src/telnyx/types/ai/speak_node_req_param.py index 652ff3c5b..c13c277ca 100644 --- a/src/telnyx/types/ai/speak_node_req_param.py +++ b/src/telnyx/types/ai/speak_node_req_param.py @@ -4,8 +4,6 @@ from typing_extensions import Literal, Required, TypedDict -from .node_position_param import NodePositionParam - __all__ = ["SpeakNodeReqParam"] @@ -34,7 +32,7 @@ class SpeakNodeReqParam(TypedDict, total=False): name: str """Optional human-readable label, displayed in authoring UIs.""" - position: NodePositionParam + position: "NodePositionParam" """Optional canvas coordinates used by authoring UIs to lay out the graph. Ignored by the runtime; round-trips so frontends can persist graph layout across @@ -43,3 +41,6 @@ class SpeakNodeReqParam(TypedDict, total=False): type: Literal["speak"] """Node kind discriminator. Always `speak` for a speak node.""" + + +from .node_position_param import NodePositionParam diff --git a/src/telnyx/types/ai/start_speaking_plan_param.py b/src/telnyx/types/ai/start_speaking_plan_param.py index eddc939ee..a6ff31619 100644 --- a/src/telnyx/types/ai/start_speaking_plan_param.py +++ b/src/telnyx/types/ai/start_speaking_plan_param.py @@ -4,8 +4,6 @@ from typing_extensions import TypedDict -from .transcription_endpointing_plan_param import TranscriptionEndpointingPlanParam - __all__ = ["StartSpeakingPlanParam"] @@ -15,7 +13,7 @@ class StartSpeakingPlanParam(TypedDict, total=False): These thresholds primarily apply to non turn-taking transcription models. For turn-taking models like `deepgram/flux`, end-of-turn detection is driven by the transcription end-of-turn settings under `transcription.settings` instead. """ - transcription_endpointing_plan: TranscriptionEndpointingPlanParam + transcription_endpointing_plan: "TranscriptionEndpointingPlanParam" """Endpointing thresholds used to decide when the user has finished speaking. Applies to non turn-taking transcription models. For `deepgram/flux`, use @@ -25,3 +23,6 @@ class StartSpeakingPlanParam(TypedDict, total=False): wait_seconds: float """Minimum seconds to wait before the assistant starts speaking.""" + + +from .transcription_endpointing_plan_param import TranscriptionEndpointingPlanParam diff --git a/src/telnyx/types/ai/tool_create_params.py b/src/telnyx/types/ai/tool_create_params.py index 6fde35dd3..ebe2d296f 100644 --- a/src/telnyx/types/ai/tool_create_params.py +++ b/src/telnyx/types/ai/tool_create_params.py @@ -6,8 +6,6 @@ from typing_extensions import Required, Annotated, TypedDict from ..._utils import PropertyInfo -from .pay_tool_params_param import PayToolParamsParam -from .update_dynamic_variables_tool_params_param import UpdateDynamicVariablesToolParamsParam __all__ = ["ToolCreateParams"] @@ -25,15 +23,19 @@ class ToolCreateParams(TypedDict, total=False): invite: Dict[str, object] - pay: PayToolParamsParam + pay: "PayToolParamsParam" retrieval: Dict[str, object] timeout_ms: int - update_dynamic_variables: UpdateDynamicVariablesToolParamsParam + update_dynamic_variables: "UpdateDynamicVariablesToolParamsParam" """Configuration for an update_dynamic_variables tool.""" webhook: Dict[str, object] idempotency_key: Annotated[str, PropertyInfo(alias="Idempotency-Key")] + + +from .pay_tool_params_param import PayToolParamsParam +from .update_dynamic_variables_tool_params_param import UpdateDynamicVariablesToolParamsParam diff --git a/src/telnyx/types/ai/tool_node.py b/src/telnyx/types/ai/tool_node.py index 370cec47b..33afa7cf9 100644 --- a/src/telnyx/types/ai/tool_node.py +++ b/src/telnyx/types/ai/tool_node.py @@ -22,10 +22,21 @@ class ToolNode(BaseModel): """ID of the single shared (org-level) tool this node executes. When the flow reaches this node the tool runs as a deliberate step (no LLM - turn); its outgoing `tool_result` edges then route on the outcome. Arguments are - filled from the conversation's dynamic variables by name — a dynamic variable - whose name matches one of the tool's parameters supplies that argument. - Cross-validated against the org's shared tools on write. + turn); its outgoing `llm` / `expression` edges route the flow on the tool's + outcome. Arguments are filled from the conversation's dynamic variables by name + — a dynamic variable whose name matches one of the tool's parameters supplies + that argument. Cross-validated against the org's shared tools on write. + """ + + message: Optional[str] = None + """ + Optional message delivered to the user verbatim immediately before the tool + executes — an announcement such as 'One moment while I look that up.' No LLM + turn and no customer turn: the message is spoken/sent, then the tool runs, in + the same deterministic step. `{{variable}}` placeholders are interpolated from + the conversation's dynamic variables (unresolved → empty string); the tool's own + result is not yet available when the message is rendered. Omit for a silent tool + step. """ name: Optional[str] = None diff --git a/src/telnyx/types/ai/tool_node_req_param.py b/src/telnyx/types/ai/tool_node_req_param.py index c95d643f8..f13232e43 100644 --- a/src/telnyx/types/ai/tool_node_req_param.py +++ b/src/telnyx/types/ai/tool_node_req_param.py @@ -4,8 +4,6 @@ from typing_extensions import Literal, Required, TypedDict -from .node_position_param import NodePositionParam - __all__ = ["ToolNodeReqParam"] @@ -15,7 +13,10 @@ class ToolNodeReqParam(TypedDict, total=False): Unlike a prompt node, a tool node has no instructions or model — it isn't an LLM turn. Reaching it deterministically runs one shared tool (arguments filled from matching dynamic variables by name), then routes - on the result via outgoing `tool_result` edges. + via outgoing `llm` / `expression` edges, with exactly one `default` + fallback edge required when the node has any outgoing edges (the + tool's outcome is readable as `telnyx_last_tool_status_code` in + `expression` conditions). """ id: Required[str] @@ -25,16 +26,27 @@ class ToolNodeReqParam(TypedDict, total=False): """ID of the single shared (org-level) tool this node executes. When the flow reaches this node the tool runs as a deliberate step (no LLM - turn); its outgoing `tool_result` edges then route on the outcome. Arguments are - filled from the conversation's dynamic variables by name — a dynamic variable - whose name matches one of the tool's parameters supplies that argument. - Cross-validated against the org's shared tools on write. + turn); its outgoing `llm` / `expression` edges route the flow on the tool's + outcome. Arguments are filled from the conversation's dynamic variables by name + — a dynamic variable whose name matches one of the tool's parameters supplies + that argument. Cross-validated against the org's shared tools on write. + """ + + message: str + """ + Optional message delivered to the user verbatim immediately before the tool + executes — an announcement such as 'One moment while I look that up.' No LLM + turn and no customer turn: the message is spoken/sent, then the tool runs, in + the same deterministic step. `{{variable}}` placeholders are interpolated from + the conversation's dynamic variables (unresolved → empty string); the tool's own + result is not yet available when the message is rendered. Omit for a silent tool + step. """ name: str """Optional human-readable label, displayed in authoring UIs.""" - position: NodePositionParam + position: "NodePositionParam" """Optional canvas coordinates used by authoring UIs to lay out the graph. Ignored by the runtime; round-trips so frontends can persist graph layout across @@ -43,3 +55,6 @@ class ToolNodeReqParam(TypedDict, total=False): type: Literal["tool"] """Node kind discriminator. Always `tool` for a tool node.""" + + +from .node_position_param import NodePositionParam diff --git a/src/telnyx/types/ai/tool_update_params.py b/src/telnyx/types/ai/tool_update_params.py index 323e9d22d..08d3b2b9d 100644 --- a/src/telnyx/types/ai/tool_update_params.py +++ b/src/telnyx/types/ai/tool_update_params.py @@ -5,9 +5,6 @@ from typing import Dict from typing_extensions import TypedDict -from .pay_tool_params_param import PayToolParamsParam -from .update_dynamic_variables_tool_params_param import UpdateDynamicVariablesToolParamsParam - __all__ = ["ToolUpdateParams"] @@ -22,7 +19,7 @@ class ToolUpdateParams(TypedDict, total=False): invite: Dict[str, object] - pay: PayToolParamsParam + pay: "PayToolParamsParam" retrieval: Dict[str, object] @@ -30,7 +27,11 @@ class ToolUpdateParams(TypedDict, total=False): type: str - update_dynamic_variables: UpdateDynamicVariablesToolParamsParam + update_dynamic_variables: "UpdateDynamicVariablesToolParamsParam" """Configuration for an update_dynamic_variables tool.""" webhook: Dict[str, object] + + +from .pay_tool_params_param import PayToolParamsParam +from .update_dynamic_variables_tool_params_param import UpdateDynamicVariablesToolParamsParam diff --git a/src/telnyx/types/ai/transcription_settings_param.py b/src/telnyx/types/ai/transcription_settings_param.py index 6635850e4..22d4f5866 100644 --- a/src/telnyx/types/ai/transcription_settings_param.py +++ b/src/telnyx/types/ai/transcription_settings_param.py @@ -4,8 +4,6 @@ from typing_extensions import Literal, TypedDict -from .transcription_settings_config_param import TranscriptionSettingsConfigParam - __all__ = ["TranscriptionSettingsParam"] @@ -88,4 +86,7 @@ class TranscriptionSettingsParam(TypedDict, total=False): models. Some regions require `api_key_ref`. """ - settings: TranscriptionSettingsConfigParam + settings: "TranscriptionSettingsConfigParam" + + +from .transcription_settings_config_param import TranscriptionSettingsConfigParam diff --git a/src/telnyx/types/ai/voice_settings_param.py b/src/telnyx/types/ai/voice_settings_param.py index ed2da26aa..85df001cd 100644 --- a/src/telnyx/types/ai/voice_settings_param.py +++ b/src/telnyx/types/ai/voice_settings_param.py @@ -176,8 +176,9 @@ class VoiceSettingsParam(TypedDict, total=False): """ voice_speed: float - """The speed of the voice in the range [0.25, 2.0]. + """The speed of the voice in the range [0.6, 1.5]. - 1.0 is deafult speed. Larger numbers make the voice faster, smaller numbers make - it slower. This is only applicable for Telnyx Natural voices. + 1.0 is the default speed. Larger numbers make the voice faster, smaller numbers + make it slower. Applies to Telnyx `Ultra` voices; values outside this range are + rejected by the synthesis engine. """ diff --git a/src/telnyx/types/ai/webhook_tool_param.py b/src/telnyx/types/ai/webhook_tool_param.py index 33c87cf9f..949b523df 100644 --- a/src/telnyx/types/ai/webhook_tool_param.py +++ b/src/telnyx/types/ai/webhook_tool_param.py @@ -127,3 +127,11 @@ class WebhookToolParam(TypedDict, total=False): type: Required[Literal["webhook"]] webhook: Required[Webhook] + + timeout_ms: int + """ + The maximum number of milliseconds to wait for the webhook to respond before the + tool call is aborted. Set this at the tool level, as a sibling of `type` — a + `timeout_ms` nested inside the `webhook` object is not applied, and the tool + runs at this default instead. + """ diff --git a/src/telnyx/types/ai/websocket_settings.py b/src/telnyx/types/ai/websocket_settings.py new file mode 100644 index 000000000..21250b236 --- /dev/null +++ b/src/telnyx/types/ai/websocket_settings.py @@ -0,0 +1,35 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Optional + +from ..._models import BaseModel + +__all__ = ["WebsocketSettings"] + + +class WebsocketSettings(BaseModel): + """ + Streams conversation and telephony events to a WebSocket server you host, and accepts messages injected back into the conversation. Telnyx opens the connection as a client, once per conversation. Delivery is best effort throughout: while the connection is down events are dropped rather than queued, and no socket failure is ever allowed to affect the call. Beta feature. + """ + + auth_ref: Optional[str] = None + """ + Integration secret identifier whose value Telnyx sends as an + `Authorization: Bearer ` header on the upgrade request. Resolved on every + connection attempt, so a rotated secret is picked up by the next reconnect. + """ + + enabled: Optional[bool] = None + """ + Whether Telnyx opens a WebSocket to `url` for each of this assistant's + conversations. Defaults to `false`. + """ + + url: Optional[str] = None + """The `ws://` or `wss://` endpoint Telnyx connects to. + + Required when `enabled` is `true`. Must be externally reachable — localhost, + private IP ranges and `.local` domains are rejected. + """ diff --git a/src/telnyx/types/ai/websocket_settings_param.py b/src/telnyx/types/ai/websocket_settings_param.py new file mode 100644 index 000000000..7f27ec6a1 --- /dev/null +++ b/src/telnyx/types/ai/websocket_settings_param.py @@ -0,0 +1,33 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import TypedDict + +__all__ = ["WebsocketSettingsParam"] + + +class WebsocketSettingsParam(TypedDict, total=False): + """ + Streams conversation and telephony events to a WebSocket server you host, and accepts messages injected back into the conversation. Telnyx opens the connection as a client, once per conversation. Delivery is best effort throughout: while the connection is down events are dropped rather than queued, and no socket failure is ever allowed to affect the call. Beta feature. + """ + + auth_ref: str + """ + Integration secret identifier whose value Telnyx sends as an + `Authorization: Bearer ` header on the upgrade request. Resolved on every + connection attempt, so a rotated secret is picked up by the next reconnect. + """ + + enabled: bool + """ + Whether Telnyx opens a WebSocket to `url` for each of this assistant's + conversations. Defaults to `false`. + """ + + url: str + """The `ws://` or `wss://` endpoint Telnyx connects to. + + Required when `enabled` is `true`. Must be externally reachable — localhost, + private IP ranges and `.local` domains are rejected. + """ diff --git a/src/telnyx/types/ai/widget_settings_param.py b/src/telnyx/types/ai/widget_settings_param.py index 516fda727..1ab84af0d 100644 --- a/src/telnyx/types/ai/widget_settings_param.py +++ b/src/telnyx/types/ai/widget_settings_param.py @@ -5,8 +5,6 @@ from typing import Optional from typing_extensions import Literal, TypedDict -from .audio_visualizer_config_param import AudioVisualizerConfigParam - __all__ = ["WidgetSettingsParam"] @@ -16,7 +14,7 @@ class WidgetSettingsParam(TypedDict, total=False): agent_thinking_text: str """Text displayed while the agent is processing.""" - audio_visualizer_config: AudioVisualizerConfigParam + audio_visualizer_config: "AudioVisualizerConfigParam" default_state: Literal["expanded", "collapsed"] """The default state of the widget.""" @@ -44,3 +42,6 @@ class WidgetSettingsParam(TypedDict, total=False): view_history_url: Optional[str] """URL to view conversation history.""" + + +from .audio_visualizer_config_param import AudioVisualizerConfigParam diff --git a/src/telnyx/types/authentication_provider_create_params.py b/src/telnyx/types/authentication_provider_create_params.py index 64c838a95..5ad26ad4d 100644 --- a/src/telnyx/types/authentication_provider_create_params.py +++ b/src/telnyx/types/authentication_provider_create_params.py @@ -4,8 +4,6 @@ from typing_extensions import Required, TypedDict -from .settings_param import SettingsParam - __all__ = ["AuthenticationProviderCreateParams"] @@ -13,7 +11,7 @@ class AuthenticationProviderCreateParams(TypedDict, total=False): name: Required[str] """The name associated with the authentication provider.""" - settings: Required[SettingsParam] + settings: Required["SettingsParam"] """The settings associated with the authentication provider.""" short_name: Required[str] @@ -30,3 +28,6 @@ class AuthenticationProviderCreateParams(TypedDict, total=False): The URL for the identity provider metadata file to populate the settings automatically. If the settings attribute is provided, that will be used instead. """ + + +from .settings_param import SettingsParam diff --git a/src/telnyx/types/authentication_provider_update_params.py b/src/telnyx/types/authentication_provider_update_params.py index c1d9aa9e5..d0c8635a6 100644 --- a/src/telnyx/types/authentication_provider_update_params.py +++ b/src/telnyx/types/authentication_provider_update_params.py @@ -4,8 +4,6 @@ from typing_extensions import TypedDict -from .settings_param import SettingsParam - __all__ = ["AuthenticationProviderUpdateParams"] @@ -16,7 +14,7 @@ class AuthenticationProviderUpdateParams(TypedDict, total=False): name: str """The name associated with the authentication provider.""" - settings: SettingsParam + settings: "SettingsParam" """The settings associated with the authentication provider.""" settings_url: str @@ -30,3 +28,6 @@ class AuthenticationProviderUpdateParams(TypedDict, total=False): This must be unique and URL-friendly, as it's going to be part of the login URL. """ + + +from .settings_param import SettingsParam diff --git a/src/telnyx/types/billing_contact.py b/src/telnyx/types/billing_contact.py index 7141fb0ec..7284fe856 100644 --- a/src/telnyx/types/billing_contact.py +++ b/src/telnyx/types/billing_contact.py @@ -9,10 +9,25 @@ class BillingContact(BaseModel): email: str + """ + The email address of the person Telnyx should contact about billing for this + account. + """ first_name: str + """ + The first name of the person Telnyx should contact about billing for this + account. + """ last_name: str + """ + The last name of the person Telnyx should contact about billing for this + account. + """ phone_number: str - """E.164 format with leading `+`.""" + """ + The phone number of the billing contact, in E.164 format, for example + +12125551234. + """ diff --git a/src/telnyx/types/billing_contact_param.py b/src/telnyx/types/billing_contact_param.py index bbe2c83fb..522a43350 100644 --- a/src/telnyx/types/billing_contact_param.py +++ b/src/telnyx/types/billing_contact_param.py @@ -9,10 +9,25 @@ class BillingContactParam(TypedDict, total=False): email: Required[str] + """ + The email address of the person Telnyx should contact about billing for this + account. + """ first_name: Required[str] + """ + The first name of the person Telnyx should contact about billing for this + account. + """ last_name: Required[str] + """ + The last name of the person Telnyx should contact about billing for this + account. + """ phone_number: Required[str] - """E.164 format with leading `+`.""" + """ + The phone number of the billing contact, in E.164 format, for example + +12125551234. + """ diff --git a/src/telnyx/types/bpo_authorization_input_param.py b/src/telnyx/types/bpo_authorization_input_param.py new file mode 100644 index 000000000..d7b11e47d --- /dev/null +++ b/src/telnyx/types/bpo_authorization_input_param.py @@ -0,0 +1,25 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, TypedDict + +__all__ = ["BpoAuthorizationInputParam"] + + +class BpoAuthorizationInputParam(TypedDict, total=False): + """ + One authorization to include when creating or updating a DIR: an approved BPO (Business Process Outsourcer) account plus the signed Letter of Authorization the Brand Owner granted it. + """ + + bpo_enterprise_id: Required[str] + """ + Enterprise id of an approved BPO (Business Process Outsourcer) account on your + organization to authorize for this DIR. + """ + + loa_document_id: Required[str] + """ + Id of the signed Letter of Authorization document (uploaded via the Telnyx + Documents API) in which the Brand Owner authorizes this BPO. + """ diff --git a/src/telnyx/types/call_assistant_request_param.py b/src/telnyx/types/call_assistant_request_param.py index 45187efa5..16c6305e2 100644 --- a/src/telnyx/types/call_assistant_request_param.py +++ b/src/telnyx/types/call_assistant_request_param.py @@ -5,14 +5,6 @@ from typing import Dict, Union, Iterable from typing_extensions import Literal, Required, TypeAlias, TypedDict -from .ai.hangup_tool_param import HangupToolParam -from .ai.webhook_tool_param import WebhookToolParam -from .ai.transfer_tool_param import TransferToolParam -from .ai.voice_settings_param import VoiceSettingsParam -from .shared_params.book_appointment_tool import BookAppointmentTool -from .shared_params.check_availability_tool import CheckAvailabilityTool -from .shared_params.call_control_retrieval_tool import CallControlRetrievalTool - __all__ = ["CallAssistantRequestParam", "ExternalLlm", "FallbackConfig", "FallbackConfigExternalLlm", "Tool"] @@ -105,19 +97,19 @@ class FallbackConfig(TypedDict, total=False, extra_items=object): # type: ignor Tool: TypeAlias = Union[ - BookAppointmentTool, - CheckAvailabilityTool, - WebhookToolParam, - HangupToolParam, - TransferToolParam, - CallControlRetrievalTool, + "BookAppointmentTool", + "CheckAvailabilityTool", + "WebhookToolParam", + "HangupToolParam", + "TransferToolParam", + "CallControlRetrievalTool", ] class CallAssistantRequestParam(TypedDict, total=False): - """AI Assistant configuration. + """AI Assistant configuration and per-call overrides. - All fields except `id` are optional — the assistant's stored configuration will be used as fallback for any omitted fields. + All fields except `id` are optional. Omitted assistant fields use the stored configuration. Supplied `voice_settings` and `transcription` objects replace their stored objects rather than merging individual settings; include every setting you want to retain. `dynamic_variables` are merged, with request values taking precedence. """ id: Required[str] @@ -198,4 +190,27 @@ class CallAssistantRequestParam(TypedDict, total=False): transfer, hangup, etc.). Overrides the assistant's stored tools if provided. """ - voice_settings: VoiceSettingsParam + transcription: "TranscriptionConfigParam" + """Per-call speech-to-text configuration for the assistant. + + If omitted, the stored assistant transcription configuration is used. If + supplied, this object replaces the stored transcription settings. This is + separate from the top-level `transcription` boolean on answer and dial commands. + """ + + voice_settings: "VoiceSettingsParam" + """Per-call voice configuration. + + Set the voice identifier in `voice_settings.voice`, not in `assistant.voice`. If + supplied, this object replaces the stored voice settings. + """ + + +from .ai.hangup_tool_param import HangupToolParam +from .ai.webhook_tool_param import WebhookToolParam +from .ai.transfer_tool_param import TransferToolParam +from .ai.voice_settings_param import VoiceSettingsParam +from .calls.transcription_config_param import TranscriptionConfigParam +from .shared_params.book_appointment_tool import BookAppointmentTool +from .shared_params.check_availability_tool import CheckAvailabilityTool +from .shared_params.call_control_retrieval_tool import CallControlRetrievalTool diff --git a/src/telnyx/types/call_control_application_create_params.py b/src/telnyx/types/call_control_application_create_params.py index c26b3e34c..91b23c9c3 100644 --- a/src/telnyx/types/call_control_application_create_params.py +++ b/src/telnyx/types/call_control_application_create_params.py @@ -5,9 +5,6 @@ from typing import Optional from typing_extensions import Literal, Required, TypedDict -from .call_control_application_inbound_param import CallControlApplicationInboundParam -from .call_control_application_outbound_param import CallControlApplicationOutboundParam - __all__ = ["CallControlApplicationCreateParams"] @@ -63,9 +60,9 @@ class CallControlApplicationCreateParams(TypedDict, total=False): first_command_timeout_secs: int """Specifies how many seconds to wait before timing out a dial command.""" - inbound: CallControlApplicationInboundParam + inbound: "CallControlApplicationInboundParam" - outbound: CallControlApplicationOutboundParam + outbound: "CallControlApplicationOutboundParam" redact_dtmf_debug_logging: bool """ @@ -84,3 +81,7 @@ class CallControlApplicationCreateParams(TypedDict, total=False): webhook_timeout_secs: Optional[int] """Specifies how many seconds to wait before timing out a webhook.""" + + +from .call_control_application_inbound_param import CallControlApplicationInboundParam +from .call_control_application_outbound_param import CallControlApplicationOutboundParam diff --git a/src/telnyx/types/call_control_application_update_params.py b/src/telnyx/types/call_control_application_update_params.py index b8aa2f5a7..e2d93344b 100644 --- a/src/telnyx/types/call_control_application_update_params.py +++ b/src/telnyx/types/call_control_application_update_params.py @@ -6,8 +6,6 @@ from typing_extensions import Literal, Required, TypedDict from .._types import SequenceNotStr -from .call_control_application_inbound_param import CallControlApplicationInboundParam -from .call_control_application_outbound_param import CallControlApplicationOutboundParam __all__ = ["CallControlApplicationUpdateParams"] @@ -64,9 +62,9 @@ class CallControlApplicationUpdateParams(TypedDict, total=False): first_command_timeout_secs: int """Specifies how many seconds to wait before timing out a dial command.""" - inbound: CallControlApplicationInboundParam + inbound: "CallControlApplicationInboundParam" - outbound: CallControlApplicationOutboundParam + outbound: "CallControlApplicationOutboundParam" redact_dtmf_debug_logging: bool """ @@ -88,3 +86,7 @@ class CallControlApplicationUpdateParams(TypedDict, total=False): webhook_timeout_secs: Optional[int] """Specifies how many seconds to wait before timing out a webhook.""" + + +from .call_control_application_inbound_param import CallControlApplicationInboundParam +from .call_control_application_outbound_param import CallControlApplicationOutboundParam diff --git a/src/telnyx/types/call_conversation_created_webhook_event.py b/src/telnyx/types/call_conversation_created_webhook_event.py new file mode 100644 index 000000000..92181086f --- /dev/null +++ b/src/telnyx/types/call_conversation_created_webhook_event.py @@ -0,0 +1,74 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Optional +from datetime import datetime +from typing_extensions import Literal + +from pydantic import Field as FieldInfo + +from .._models import BaseModel + +__all__ = ["CallConversationCreatedWebhookEvent", "Data", "DataPayload"] + + +class DataPayload(BaseModel): + call_control_id: Optional[str] = None + """Call ID used to issue commands via Call Control API.""" + + call_leg_id: Optional[str] = None + """ID that is unique to the call leg.""" + + call_session_id: Optional[str] = None + """ID that is unique to the call session (group of related call legs).""" + + calling_party_type: Optional[Literal["pstn", "sip"]] = None + """The type of calling party connection.""" + + client_state: Optional[str] = None + """Base64-encoded state received from a command.""" + + connection_id: Optional[str] = None + """Call Control App ID (formerly Telnyx connection ID) used in the call.""" + + conversation_id: Optional[str] = None + """Unique identifier of the conversation created for this call.""" + + from_: Optional[str] = FieldInfo(alias="from", default=None) + """The caller's number or identifier.""" + + to: Optional[str] = None + """The callee's number or SIP address.""" + + +class Data(BaseModel): + """A conversation has been created for the call. + + Use the conversation ID to correlate subsequent conversation events. + """ + + id: Optional[str] = None + """Unique identifier for the event.""" + + created_at: Optional[datetime] = None + """Timestamp when the event was created in the system.""" + + event_type: Optional[Literal["call.conversation.created"]] = None + """The type of event being delivered.""" + + occurred_at: Optional[datetime] = None + """ISO 8601 datetime of when the event occurred.""" + + payload: Optional[DataPayload] = None + + record_type: Optional[Literal["event"]] = None + """Identifies the type of the resource.""" + + +class CallConversationCreatedWebhookEvent(BaseModel): + data: Optional[Data] = None + """A conversation has been created for the call. + + Use the conversation ID to correlate subsequent conversation events. + """ diff --git a/src/telnyx/types/call_conversation_created_webhook_event1.py b/src/telnyx/types/call_conversation_created_webhook_event1.py new file mode 100644 index 000000000..92181086f --- /dev/null +++ b/src/telnyx/types/call_conversation_created_webhook_event1.py @@ -0,0 +1,74 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Optional +from datetime import datetime +from typing_extensions import Literal + +from pydantic import Field as FieldInfo + +from .._models import BaseModel + +__all__ = ["CallConversationCreatedWebhookEvent", "Data", "DataPayload"] + + +class DataPayload(BaseModel): + call_control_id: Optional[str] = None + """Call ID used to issue commands via Call Control API.""" + + call_leg_id: Optional[str] = None + """ID that is unique to the call leg.""" + + call_session_id: Optional[str] = None + """ID that is unique to the call session (group of related call legs).""" + + calling_party_type: Optional[Literal["pstn", "sip"]] = None + """The type of calling party connection.""" + + client_state: Optional[str] = None + """Base64-encoded state received from a command.""" + + connection_id: Optional[str] = None + """Call Control App ID (formerly Telnyx connection ID) used in the call.""" + + conversation_id: Optional[str] = None + """Unique identifier of the conversation created for this call.""" + + from_: Optional[str] = FieldInfo(alias="from", default=None) + """The caller's number or identifier.""" + + to: Optional[str] = None + """The callee's number or SIP address.""" + + +class Data(BaseModel): + """A conversation has been created for the call. + + Use the conversation ID to correlate subsequent conversation events. + """ + + id: Optional[str] = None + """Unique identifier for the event.""" + + created_at: Optional[datetime] = None + """Timestamp when the event was created in the system.""" + + event_type: Optional[Literal["call.conversation.created"]] = None + """The type of event being delivered.""" + + occurred_at: Optional[datetime] = None + """ISO 8601 datetime of when the event occurred.""" + + payload: Optional[DataPayload] = None + + record_type: Optional[Literal["event"]] = None + """Identifies the type of the resource.""" + + +class CallConversationCreatedWebhookEvent(BaseModel): + data: Optional[Data] = None + """A conversation has been created for the call. + + Use the conversation ID to correlate subsequent conversation events. + """ diff --git a/src/telnyx/types/call_dial_params.py b/src/telnyx/types/call_dial_params.py index 713fe8ea6..37131160b 100644 --- a/src/telnyx/types/call_dial_params.py +++ b/src/telnyx/types/call_dial_params.py @@ -7,18 +7,6 @@ from .._types import SequenceNotStr from .._utils import PropertyInfo -from .stream_codec import StreamCodec -from .sip_header_param import SipHeaderParam -from .custom_sip_header_param import CustomSipHeaderParam -from .dialogflow_config_param import DialogflowConfigParam -from .sound_modifications_param import SoundModificationsParam -from .stream_bidirectional_mode import StreamBidirectionalMode -from .stream_bidirectional_codec import StreamBidirectionalCodec -from .call_assistant_request_param import CallAssistantRequestParam -from .stream_bidirectional_target_legs import StreamBidirectionalTargetLegs -from .stream_bidirectional_sampling_rate import StreamBidirectionalSamplingRate -from .calls.transcription_start_request_param import TranscriptionStartRequestParam -from .conversation_relay_embedded_config_param import ConversationRelayEmbeddedConfigParam __all__ = [ "CallDialParams", @@ -57,7 +45,15 @@ class CallDialParams(TypedDict, total=False): is not supported when `to` is an array. """ - answering_machine_detection: Literal["premium", "detect", "detect_beep", "detect_words", "greeting_end", "disabled"] + answering_machine_detection: Literal[ + "premium", + "premium_ios_call_screening_detection", + "detect", + "detect_beep", + "detect_words", + "greeting_end", + "disabled", + ] """Enables Answering Machine Detection. Telnyx offers Premium and Standard detections. With Premium detection, when a @@ -76,7 +72,16 @@ class CallDialParams(TypedDict, total=False): `greeting_end` or `detect_words` is used and a `machine` is detected, you will receive another `call.machine.greeting.ended` webhook when the answering machine greeting ends with a beep or silence. If `detect_beep` is used, you will only - receive `call.machine.greeting.ended` if a beep is detected. + receive `call.machine.greeting.ended` if a beep is detected. If + `answering_machine_detection` is set to `premium_ios_call_screening_detection`, + Premium AMD runs with iOS Call Screening support: after an initial `machine` + result, Telnyx listens for the iOS call-screening prompt to end or for an Apple + Call Screening tone, sends `call.machine.premium.greeting.ended` with + `result=prompt_ended` or `call.machine.premium.call_screening.detected` with + `result=screening` respectively. When the Apple Call Screening tone is detected, + Premium AMD is restarted on the screened call and a + `call.machine.premium.detection.ended` webhook with the post-screening + classification follows. """ answering_machine_detection_config: AnsweringMachineDetectionConfig @@ -84,14 +89,18 @@ class CallDialParams(TypedDict, total=False): Optional configuration parameters to modify 'answering_machine_detection' performance. Only `total_analysis_time_millis` and `greeting_duration_millis` parameters are applicable when `premium` is selected as - answering_machine_detection. + answering_machine_detection. `prompt_end_timeout_millis` is additionally + applicable when `premium_ios_call_screening_detection` is selected. """ - assistant: CallAssistantRequestParam - """AI Assistant configuration. + assistant: "CallAssistantRequestParam" + """AI Assistant configuration and per-call overrides. - All fields except `id` are optional — the assistant's stored configuration will - be used as fallback for any omitted fields. + All fields except `id` are optional. Omitted assistant fields use the stored + configuration. Supplied `voice_settings` and `transcription` objects replace + their stored objects rather than merging individual settings; include every + setting you want to retain. `dynamic_variables` are merged, with request values + taking precedence. """ audio_url: str @@ -135,7 +144,7 @@ class CallDialParams(TypedDict, total=False): conference_config: ConferenceConfig """Optional configuration parameters to dial new participant into a conference.""" - conversation_relay_config: ConversationRelayEmbeddedConfigParam + conversation_relay_config: "ConversationRelayEmbeddedConfigParam" """ Starts a Conversation Relay session automatically when the answered/dialed call is answered. This embedded shape is supported on `answer` and `dial`. It uses @@ -145,7 +154,7 @@ class CallDialParams(TypedDict, total=False): the parent command's `client_state` and `command_id` fields instead. """ - custom_headers: Iterable[CustomSipHeaderParam] + custom_headers: Iterable["CustomSipHeaderParam"] """Custom headers to be added to the SIP INVITE.""" deepfake_detection: DeepfakeDetection @@ -156,7 +165,7 @@ class CallDialParams(TypedDict, total=False): `call.deepfake_detection.result` webhook. """ - dialogflow_config: DialogflowConfigParam + dialogflow_config: "DialogflowConfigParam" diversion: str """The `to` number of an active inbound call, in +E164 format. @@ -317,7 +326,7 @@ class CallDialParams(TypedDict, total=False): sip_auth_username: str """SIP Authentication username used for SIP challenges.""" - sip_headers: Iterable[SipHeaderParam] + sip_headers: Iterable["SipHeaderParam"] """SIP headers to be added to the SIP INVITE request. Currently only User-to-User header is supported. @@ -329,7 +338,7 @@ class CallDialParams(TypedDict, total=False): sip_transport_protocol: Literal["UDP", "TCP", "TLS"] """Defines SIP transport protocol to be used on the call.""" - sound_modifications: SoundModificationsParam + sound_modifications: "SoundModificationsParam" """Use this field to modify sound effects, for example adjust the pitch.""" stream_auth_token: str @@ -338,22 +347,22 @@ class CallDialParams(TypedDict, total=False): using streaming. Maximum length is 4000 characters. """ - stream_bidirectional_codec: StreamBidirectionalCodec + stream_bidirectional_codec: "StreamBidirectionalCodec" """Indicates codec for bidirectional streaming RTP payloads. Used only with stream_bidirectional_mode=rtp. Case sensitive. """ - stream_bidirectional_mode: StreamBidirectionalMode + stream_bidirectional_mode: "StreamBidirectionalMode" """Configures method of bidirectional streaming (mp3, rtp).""" - stream_bidirectional_sampling_rate: StreamBidirectionalSamplingRate + stream_bidirectional_sampling_rate: "StreamBidirectionalSamplingRate" """Audio sampling rate.""" - stream_bidirectional_target_legs: StreamBidirectionalTargetLegs + stream_bidirectional_target_legs: "StreamBidirectionalTargetLegs" """Specifies which call legs should receive the bidirectional stream audio.""" - stream_codec: StreamCodec + stream_codec: "StreamCodec" """Specifies the codec to be used for the streamed audio. When set to 'default' or when transcoding is not possible, the codec from the @@ -407,7 +416,7 @@ class CallDialParams(TypedDict, total=False): transcription: bool """Enable transcription upon call answer. The default value is false.""" - transcription_config: TranscriptionStartRequestParam + transcription_config: "TranscriptionStartRequestParam" webhook_retries_policies: Dict[str, WebhookRetriesPolicies] """A map of event types to retry policies. @@ -440,7 +449,7 @@ class CallDialParams(TypedDict, total=False): class AnsweringMachineDetectionConfig(TypedDict, total=False): """ - Optional configuration parameters to modify 'answering_machine_detection' performance. Only `total_analysis_time_millis` and `greeting_duration_millis` parameters are applicable when `premium` is selected as answering_machine_detection. + Optional configuration parameters to modify 'answering_machine_detection' performance. Only `total_analysis_time_millis` and `greeting_duration_millis` parameters are applicable when `premium` is selected as answering_machine_detection. `prompt_end_timeout_millis` is additionally applicable when `premium_ios_call_screening_detection` is selected. """ after_greeting_silence_millis: int @@ -533,6 +542,14 @@ class AnsweringMachineDetectionConfig(TypedDict, total=False): maximum_word_length_millis: int """If a single word lasts longer than this threshold, consider it a machine.""" + prompt_end_timeout_millis: int + """ + Maximum time Telnyx waits, in milliseconds, for the iOS call-screening prompt to + end after Premium AMD initially detects a `machine`. Used when + `answering_machine_detection` is `premium_ios_call_screening_detection`. + Defaults to 5000 milliseconds. + """ + silence_threshold: int """Minimum noise threshold for any analysis.""" @@ -661,3 +678,17 @@ class WebhookRetriesPolicies(TypedDict, total=False): Total sum cannot exceed 60000ms. """ + + +from .stream_codec import StreamCodec +from .sip_header_param import SipHeaderParam +from .custom_sip_header_param import CustomSipHeaderParam +from .dialogflow_config_param import DialogflowConfigParam +from .sound_modifications_param import SoundModificationsParam +from .stream_bidirectional_mode import StreamBidirectionalMode +from .stream_bidirectional_codec import StreamBidirectionalCodec +from .call_assistant_request_param import CallAssistantRequestParam +from .stream_bidirectional_target_legs import StreamBidirectionalTargetLegs +from .stream_bidirectional_sampling_rate import StreamBidirectionalSamplingRate +from .calls.transcription_start_request_param import TranscriptionStartRequestParam +from .conversation_relay_embedded_config_param import ConversationRelayEmbeddedConfigParam diff --git a/src/telnyx/types/call_machine_premium_call_screening_detected_webhook_event.py b/src/telnyx/types/call_machine_premium_call_screening_detected_webhook_event.py new file mode 100644 index 000000000..26c8d7ff2 --- /dev/null +++ b/src/telnyx/types/call_machine_premium_call_screening_detected_webhook_event.py @@ -0,0 +1,67 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Optional +from datetime import datetime +from typing_extensions import Literal + +from pydantic import Field as FieldInfo + +from .._models import BaseModel + +__all__ = ["CallMachinePremiumCallScreeningDetectedWebhookEvent", "Data", "DataPayload"] + + +class DataPayload(BaseModel): + call_control_id: Optional[str] = None + """Call ID used to issue commands via Call Control API.""" + + call_leg_id: Optional[str] = None + """ID that is unique to the call and can be used to correlate webhook events.""" + + call_session_id: Optional[str] = None + """ + ID that is unique to the call session and can be used to correlate webhook + events. Call session is a group of related call legs that logically belong to + the same phone call, e.g. an inbound and outbound leg of a transferred call. + """ + + client_state: Optional[str] = None + """State received from a command.""" + + connection_id: Optional[str] = None + """Call Control App ID (formerly Telnyx connection ID) used in the call.""" + + from_: Optional[str] = FieldInfo(alias="from", default=None) + """Number or SIP URI placing the call.""" + + result: Optional[Literal["screening"]] = None + """Apple Call Screening detection result. + + Sent when an Apple Call Screening tone is detected; Premium Answering Machine + Detection is restarted on the screened call afterwards. + """ + + to: Optional[str] = None + """Destination number or SIP URI of the call.""" + + +class Data(BaseModel): + id: Optional[str] = None + """Identifies the type of resource.""" + + event_type: Optional[Literal["call.machine.premium.call_screening.detected"]] = None + """The type of event being delivered.""" + + occurred_at: Optional[datetime] = None + """ISO 8601 datetime of when the event occurred.""" + + payload: Optional[DataPayload] = None + + record_type: Optional[Literal["event"]] = None + """Identifies the type of the resource.""" + + +class CallMachinePremiumCallScreeningDetectedWebhookEvent(BaseModel): + data: Optional[Data] = None diff --git a/src/telnyx/types/call_machine_premium_call_screening_detected_webhook_event1.py b/src/telnyx/types/call_machine_premium_call_screening_detected_webhook_event1.py new file mode 100644 index 000000000..26c8d7ff2 --- /dev/null +++ b/src/telnyx/types/call_machine_premium_call_screening_detected_webhook_event1.py @@ -0,0 +1,67 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Optional +from datetime import datetime +from typing_extensions import Literal + +from pydantic import Field as FieldInfo + +from .._models import BaseModel + +__all__ = ["CallMachinePremiumCallScreeningDetectedWebhookEvent", "Data", "DataPayload"] + + +class DataPayload(BaseModel): + call_control_id: Optional[str] = None + """Call ID used to issue commands via Call Control API.""" + + call_leg_id: Optional[str] = None + """ID that is unique to the call and can be used to correlate webhook events.""" + + call_session_id: Optional[str] = None + """ + ID that is unique to the call session and can be used to correlate webhook + events. Call session is a group of related call legs that logically belong to + the same phone call, e.g. an inbound and outbound leg of a transferred call. + """ + + client_state: Optional[str] = None + """State received from a command.""" + + connection_id: Optional[str] = None + """Call Control App ID (formerly Telnyx connection ID) used in the call.""" + + from_: Optional[str] = FieldInfo(alias="from", default=None) + """Number or SIP URI placing the call.""" + + result: Optional[Literal["screening"]] = None + """Apple Call Screening detection result. + + Sent when an Apple Call Screening tone is detected; Premium Answering Machine + Detection is restarted on the screened call afterwards. + """ + + to: Optional[str] = None + """Destination number or SIP URI of the call.""" + + +class Data(BaseModel): + id: Optional[str] = None + """Identifies the type of resource.""" + + event_type: Optional[Literal["call.machine.premium.call_screening.detected"]] = None + """The type of event being delivered.""" + + occurred_at: Optional[datetime] = None + """ISO 8601 datetime of when the event occurred.""" + + payload: Optional[DataPayload] = None + + record_type: Optional[Literal["event"]] = None + """Identifies the type of the resource.""" + + +class CallMachinePremiumCallScreeningDetectedWebhookEvent(BaseModel): + data: Optional[Data] = None diff --git a/src/telnyx/types/call_machine_premium_detection_started_webhook_event.py b/src/telnyx/types/call_machine_premium_detection_started_webhook_event.py new file mode 100644 index 000000000..384b430ad --- /dev/null +++ b/src/telnyx/types/call_machine_premium_detection_started_webhook_event.py @@ -0,0 +1,60 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Optional +from datetime import datetime +from typing_extensions import Literal + +from pydantic import Field as FieldInfo + +from .._models import BaseModel + +__all__ = ["CallMachinePremiumDetectionStartedWebhookEvent", "Data", "DataPayload"] + + +class DataPayload(BaseModel): + call_control_id: Optional[str] = None + """Call ID used to issue commands via Call Control API.""" + + call_leg_id: Optional[str] = None + """ID that is unique to the call and can be used to correlate webhook events.""" + + call_session_id: Optional[str] = None + """ + ID that is unique to the call session and can be used to correlate webhook + events. Call session is a group of related call legs that logically belong to + the same phone call, e.g. an inbound and outbound leg of a transferred call. + """ + + client_state: Optional[str] = None + """State received from a command.""" + + connection_id: Optional[str] = None + """Call Control App ID (formerly Telnyx connection ID) used in the call.""" + + from_: Optional[str] = FieldInfo(alias="from", default=None) + """Number or SIP URI placing the call.""" + + to: Optional[str] = None + """Destination number or SIP URI of the call.""" + + +class Data(BaseModel): + id: Optional[str] = None + """Identifies the type of resource.""" + + event_type: Optional[Literal["call.machine.premium.detection.started"]] = None + """The type of event being delivered.""" + + occurred_at: Optional[datetime] = None + """ISO 8601 datetime of when the event occurred.""" + + payload: Optional[DataPayload] = None + + record_type: Optional[Literal["event"]] = None + """Identifies the type of the resource.""" + + +class CallMachinePremiumDetectionStartedWebhookEvent(BaseModel): + data: Optional[Data] = None diff --git a/src/telnyx/types/call_machine_premium_detection_started_webhook_event1.py b/src/telnyx/types/call_machine_premium_detection_started_webhook_event1.py new file mode 100644 index 000000000..384b430ad --- /dev/null +++ b/src/telnyx/types/call_machine_premium_detection_started_webhook_event1.py @@ -0,0 +1,60 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Optional +from datetime import datetime +from typing_extensions import Literal + +from pydantic import Field as FieldInfo + +from .._models import BaseModel + +__all__ = ["CallMachinePremiumDetectionStartedWebhookEvent", "Data", "DataPayload"] + + +class DataPayload(BaseModel): + call_control_id: Optional[str] = None + """Call ID used to issue commands via Call Control API.""" + + call_leg_id: Optional[str] = None + """ID that is unique to the call and can be used to correlate webhook events.""" + + call_session_id: Optional[str] = None + """ + ID that is unique to the call session and can be used to correlate webhook + events. Call session is a group of related call legs that logically belong to + the same phone call, e.g. an inbound and outbound leg of a transferred call. + """ + + client_state: Optional[str] = None + """State received from a command.""" + + connection_id: Optional[str] = None + """Call Control App ID (formerly Telnyx connection ID) used in the call.""" + + from_: Optional[str] = FieldInfo(alias="from", default=None) + """Number or SIP URI placing the call.""" + + to: Optional[str] = None + """Destination number or SIP URI of the call.""" + + +class Data(BaseModel): + id: Optional[str] = None + """Identifies the type of resource.""" + + event_type: Optional[Literal["call.machine.premium.detection.started"]] = None + """The type of event being delivered.""" + + occurred_at: Optional[datetime] = None + """ISO 8601 datetime of when the event occurred.""" + + payload: Optional[DataPayload] = None + + record_type: Optional[Literal["event"]] = None + """Identifies the type of the resource.""" + + +class CallMachinePremiumDetectionStartedWebhookEvent(BaseModel): + data: Optional[Data] = None diff --git a/src/telnyx/types/call_machine_premium_greeting_ended.py b/src/telnyx/types/call_machine_premium_greeting_ended.py index cd2fd9580..2b3a5c6f0 100644 --- a/src/telnyx/types/call_machine_premium_greeting_ended.py +++ b/src/telnyx/types/call_machine_premium_greeting_ended.py @@ -36,8 +36,13 @@ class Payload(BaseModel): from_: Optional[str] = FieldInfo(alias="from", default=None) """Number or SIP URI placing the call.""" - result: Optional[Literal["beep_detected", "no_beep_detected"]] = None - """Premium Answering Machine Greeting Ended result.""" + result: Optional[Literal["beep_detected", "no_beep_detected", "prompt_ended"]] = None + """Premium Answering Machine Greeting Ended result. + + `prompt_ended` is only sent when `answering_machine_detection` is + `premium_ios_call_screening_detection` and the iOS call-screening prompt ends + without a beep. + """ to: Optional[str] = None """Destination number or SIP URI of the call.""" diff --git a/src/telnyx/types/calls/action_add_ai_assistant_messages_params.py b/src/telnyx/types/calls/action_add_ai_assistant_messages_params.py index c932cbc8d..4da9df2f0 100644 --- a/src/telnyx/types/calls/action_add_ai_assistant_messages_params.py +++ b/src/telnyx/types/calls/action_add_ai_assistant_messages_params.py @@ -5,12 +5,6 @@ from typing import Union, Iterable from typing_extensions import TypeAlias, TypedDict -from .tool_message_param import ToolMessageParam -from .user_message_param import UserMessageParam -from .system_message_param import SystemMessageParam -from .assistant_message_param import AssistantMessageParam -from .developer_message_param import DeveloperMessageParam - __all__ = ["ActionAddAIAssistantMessagesParams", "Message"] @@ -40,5 +34,11 @@ class ActionAddAIAssistantMessagesParams(TypedDict, total=False): Message: TypeAlias = Union[ - UserMessageParam, AssistantMessageParam, ToolMessageParam, SystemMessageParam, DeveloperMessageParam + "UserMessageParam", "AssistantMessageParam", "ToolMessageParam", "SystemMessageParam", "DeveloperMessageParam" ] + +from .tool_message_param import ToolMessageParam +from .user_message_param import UserMessageParam +from .system_message_param import SystemMessageParam +from .assistant_message_param import AssistantMessageParam +from .developer_message_param import DeveloperMessageParam diff --git a/src/telnyx/types/calls/action_answer_params.py b/src/telnyx/types/calls/action_answer_params.py index f691253c9..258c7bc85 100644 --- a/src/telnyx/types/calls/action_answer_params.py +++ b/src/telnyx/types/calls/action_answer_params.py @@ -14,7 +14,6 @@ from ..stream_bidirectional_codec import StreamBidirectionalCodec from ..call_assistant_request_param import CallAssistantRequestParam from ..stream_bidirectional_target_legs import StreamBidirectionalTargetLegs -from .transcription_start_request_param import TranscriptionStartRequestParam from ..conversation_relay_embedded_config_param import ConversationRelayEmbeddedConfigParam __all__ = ["ActionAnswerParams", "DeepfakeDetection", "WebhookRetriesPolicies"] @@ -22,10 +21,13 @@ class ActionAnswerParams(TypedDict, total=False): assistant: CallAssistantRequestParam - """AI Assistant configuration. + """AI Assistant configuration and per-call overrides. - All fields except `id` are optional — the assistant's stored configuration will - be used as fallback for any omitted fields. + All fields except `id` are optional. Omitted assistant fields use the stored + configuration. Supplied `voice_settings` and `transcription` objects replace + their stored objects rather than merging individual settings; include every + setting you want to retain. `dynamic_variables` are merged, with request values + taking precedence. """ billing_group_id: str @@ -162,9 +164,14 @@ class ActionAnswerParams(TypedDict, total=False): """The destination WebSocket address where the stream is going to be delivered.""" transcription: bool - """Enable transcription upon call answer. The default value is false.""" + """Enable standalone call transcription upon call answer. + + The default value is false. Configure this feature with `transcription_config`. + To configure speech recognition for an AI assistant, use + `assistant.transcription` instead. + """ - transcription_config: TranscriptionStartRequestParam + transcription_config: "TranscriptionStartRequestParam" webhook_retries_policies: Dict[str, WebhookRetriesPolicies] """A map of event types to retry policies. @@ -220,3 +227,6 @@ class WebhookRetriesPolicies(TypedDict, total=False): Total sum cannot exceed 60000ms. """ + + +from .transcription_start_request_param import TranscriptionStartRequestParam diff --git a/src/telnyx/types/calls/action_gather_using_ai_params.py b/src/telnyx/types/calls/action_gather_using_ai_params.py index 75a479f4a..35757bb70 100644 --- a/src/telnyx/types/calls/action_gather_using_ai_params.py +++ b/src/telnyx/types/calls/action_gather_using_ai_params.py @@ -6,13 +6,6 @@ from typing_extensions import Literal, Required, TypeAlias, TypedDict from ..ai.assistant_param import AssistantParam -from .aws_voice_settings_param import AwsVoiceSettingsParam -from .transcription_config_param import TranscriptionConfigParam -from .interruption_settings_param import InterruptionSettingsParam -from .soniox_voice_settings_param import SonioxVoiceSettingsParam -from .telnyx_voice_settings_param import TelnyxVoiceSettingsParam -from .google_transcription_language import GoogleTranscriptionLanguage -from .eleven_labs_voice_settings_param import ElevenLabsVoiceSettingsParam from ..shared_params.xai_voice_settings import XaiVoiceSettings from ..shared_params.azure_voice_settings import AzureVoiceSettings from ..shared_params.resemble_voice_settings import ResembleVoiceSettings @@ -60,10 +53,10 @@ class ActionGatherUsingAIParams(TypedDict, total=False): for `AWS.Polly.` voices. There is a 3,000 character limit. """ - interruption_settings: InterruptionSettingsParam + interruption_settings: "InterruptionSettingsParam" """Settings for handling user interruptions during assistant speech""" - language: GoogleTranscriptionLanguage + language: "GoogleTranscriptionLanguage" """Language to use for speech recognition""" message_history: Iterable[MessageHistory] @@ -90,7 +83,7 @@ class ActionGatherUsingAIParams(TypedDict, total=False): via the `call.ai_gather.ended` callback. """ - transcription: TranscriptionConfigParam + transcription: "TranscriptionConfigParam" """The settings associated with speech to text for the voice assistant. This is only relevant if the assistant uses a text-to-text language model. Any @@ -158,11 +151,19 @@ class MessageHistory(TypedDict, total=False): VoiceSettings: TypeAlias = Union[ - ElevenLabsVoiceSettingsParam, - TelnyxVoiceSettingsParam, - AwsVoiceSettingsParam, + "ElevenLabsVoiceSettingsParam", + "TelnyxVoiceSettingsParam", + "AwsVoiceSettingsParam", AzureVoiceSettings, ResembleVoiceSettings, XaiVoiceSettings, - SonioxVoiceSettingsParam, + "SonioxVoiceSettingsParam", ] + +from .aws_voice_settings_param import AwsVoiceSettingsParam +from .transcription_config_param import TranscriptionConfigParam +from .interruption_settings_param import InterruptionSettingsParam +from .soniox_voice_settings_param import SonioxVoiceSettingsParam +from .telnyx_voice_settings_param import TelnyxVoiceSettingsParam +from .google_transcription_language import GoogleTranscriptionLanguage +from .eleven_labs_voice_settings_param import ElevenLabsVoiceSettingsParam diff --git a/src/telnyx/types/calls/action_gather_using_speak_params.py b/src/telnyx/types/calls/action_gather_using_speak_params.py index 290197e61..ffff33eaf 100644 --- a/src/telnyx/types/calls/action_gather_using_speak_params.py +++ b/src/telnyx/types/calls/action_gather_using_speak_params.py @@ -5,10 +5,6 @@ from typing import Union from typing_extensions import Literal, Required, TypeAlias, TypedDict -from .aws_voice_settings_param import AwsVoiceSettingsParam -from .soniox_voice_settings_param import SonioxVoiceSettingsParam -from .telnyx_voice_settings_param import TelnyxVoiceSettingsParam -from .eleven_labs_voice_settings_param import ElevenLabsVoiceSettingsParam from ..shared_params.xai_voice_settings import XaiVoiceSettings from ..shared_params.azure_voice_settings import AzureVoiceSettings from ..shared_params.inworld_voice_settings import InworldVoiceSettings @@ -193,13 +189,18 @@ class ActionGatherUsingSpeakParams(TypedDict, total=False): VoiceSettings: TypeAlias = Union[ - ElevenLabsVoiceSettingsParam, - TelnyxVoiceSettingsParam, - AwsVoiceSettingsParam, + "ElevenLabsVoiceSettingsParam", + "TelnyxVoiceSettingsParam", + "AwsVoiceSettingsParam", MinimaxVoiceSettings, AzureVoiceSettings, ResembleVoiceSettings, InworldVoiceSettings, XaiVoiceSettings, - SonioxVoiceSettingsParam, + "SonioxVoiceSettingsParam", ] + +from .aws_voice_settings_param import AwsVoiceSettingsParam +from .soniox_voice_settings_param import SonioxVoiceSettingsParam +from .telnyx_voice_settings_param import TelnyxVoiceSettingsParam +from .eleven_labs_voice_settings_param import ElevenLabsVoiceSettingsParam diff --git a/src/telnyx/types/calls/action_join_ai_assistant_params.py b/src/telnyx/types/calls/action_join_ai_assistant_params.py index f5346e3e5..71f216c6e 100644 --- a/src/telnyx/types/calls/action_join_ai_assistant_params.py +++ b/src/telnyx/types/calls/action_join_ai_assistant_params.py @@ -4,8 +4,6 @@ from typing_extensions import Required, TypedDict -from .ai_assistant_join_participant_param import AIAssistantJoinParticipantParam - __all__ = ["ActionJoinAIAssistantParams"] @@ -13,7 +11,7 @@ class ActionJoinAIAssistantParams(TypedDict, total=False): conversation_id: Required[str] """The ID of the AI assistant conversation to join.""" - participant: Required[AIAssistantJoinParticipantParam] + participant: Required["AIAssistantJoinParticipantParam"] client_state: str """Use this field to add state to every subsequent webhook. @@ -27,3 +25,6 @@ class ActionJoinAIAssistantParams(TypedDict, total=False): Telnyx will ignore any command with the same `command_id` for the same `call_control_id`. """ + + +from .ai_assistant_join_participant_param import AIAssistantJoinParticipantParam diff --git a/src/telnyx/types/calls/action_pay_params.py b/src/telnyx/types/calls/action_pay_params.py index 90159d6cc..a4dd655a9 100644 --- a/src/telnyx/types/calls/action_pay_params.py +++ b/src/telnyx/types/calls/action_pay_params.py @@ -6,7 +6,6 @@ from typing_extensions import Literal, Annotated, TypedDict from ..._utils import PropertyInfo -from .pay_prompt_value_param import PayPromptValueParam __all__ = ["ActionPayParams", "Prompts"] @@ -95,20 +94,23 @@ class ActionPayParams(TypedDict, total=False): class Prompts(TypedDict, total=False): """Custom text-to-speech prompts keyed by payment collection step.""" - bank_account_number: Annotated[PayPromptValueParam, PropertyInfo(alias="bank-account-number")] + bank_account_number: Annotated["PayPromptValueParam", PropertyInfo(alias="bank-account-number")] """A default prompt string or an ordered list of qualified prompts.""" - bank_routing_number: Annotated[PayPromptValueParam, PropertyInfo(alias="bank-routing-number")] + bank_routing_number: Annotated["PayPromptValueParam", PropertyInfo(alias="bank-routing-number")] """A default prompt string or an ordered list of qualified prompts.""" - expiration_date: Annotated[PayPromptValueParam, PropertyInfo(alias="expiration-date")] + expiration_date: Annotated["PayPromptValueParam", PropertyInfo(alias="expiration-date")] """A default prompt string or an ordered list of qualified prompts.""" - payment_card_number: Annotated[PayPromptValueParam, PropertyInfo(alias="payment-card-number")] + payment_card_number: Annotated["PayPromptValueParam", PropertyInfo(alias="payment-card-number")] """A default prompt string or an ordered list of qualified prompts.""" - postal_code: Annotated[PayPromptValueParam, PropertyInfo(alias="postal-code")] + postal_code: Annotated["PayPromptValueParam", PropertyInfo(alias="postal-code")] """A default prompt string or an ordered list of qualified prompts.""" - security_code: Annotated[PayPromptValueParam, PropertyInfo(alias="security-code")] + security_code: Annotated["PayPromptValueParam", PropertyInfo(alias="security-code")] """A default prompt string or an ordered list of qualified prompts.""" + + +from .pay_prompt_value_param import PayPromptValueParam diff --git a/src/telnyx/types/calls/action_reject_params.py b/src/telnyx/types/calls/action_reject_params.py index 5f92111a5..7f3381e06 100644 --- a/src/telnyx/types/calls/action_reject_params.py +++ b/src/telnyx/types/calls/action_reject_params.py @@ -8,8 +8,13 @@ class ActionRejectParams(TypedDict, total=False): - cause: Required[Literal["CALL_REJECTED", "USER_BUSY"]] - """Cause for call rejection.""" + cause: Required[Literal["CALL_REJECTED", "NOT_FOUND", "TEMPORARILY_UNAVAILABLE", "USER_BUSY"]] + """Cause for call rejection. + + The cause sets the SIP response the caller receives: `USER_BUSY` sends 486 User + Busy, `CALL_REJECTED` sends 603 Decline, `NOT_FOUND` sends 404 Not Found, and + `TEMPORARILY_UNAVAILABLE` sends 480 Temporarily Unavailable. + """ client_state: str """Use this field to add state to every subsequent webhook. diff --git a/src/telnyx/types/calls/action_speak_params.py b/src/telnyx/types/calls/action_speak_params.py index ee4c56a3e..6f75d498e 100644 --- a/src/telnyx/types/calls/action_speak_params.py +++ b/src/telnyx/types/calls/action_speak_params.py @@ -5,11 +5,6 @@ from typing import Union from typing_extensions import Literal, Required, TypeAlias, TypedDict -from .loopcount_param import LoopcountParam -from .aws_voice_settings_param import AwsVoiceSettingsParam -from .soniox_voice_settings_param import SonioxVoiceSettingsParam -from .telnyx_voice_settings_param import TelnyxVoiceSettingsParam -from .eleven_labs_voice_settings_param import ElevenLabsVoiceSettingsParam from ..shared_params.xai_voice_settings import XaiVoiceSettings from ..shared_params.azure_voice_settings import AzureVoiceSettings from ..shared_params.inworld_voice_settings import InworldVoiceSettings @@ -134,7 +129,7 @@ class ActionSpeakParams(TypedDict, total=False): This parameter is ignored when a `Polly.*` voice is specified. """ - loop: LoopcountParam + loop: "LoopcountParam" """The number of times to play the audio file. Use `infinity` to loop indefinitely. Defaults to 1. @@ -170,13 +165,19 @@ class ActionSpeakParams(TypedDict, total=False): VoiceSettings: TypeAlias = Union[ - ElevenLabsVoiceSettingsParam, - TelnyxVoiceSettingsParam, - AwsVoiceSettingsParam, + "ElevenLabsVoiceSettingsParam", + "TelnyxVoiceSettingsParam", + "AwsVoiceSettingsParam", MinimaxVoiceSettings, AzureVoiceSettings, ResembleVoiceSettings, InworldVoiceSettings, XaiVoiceSettings, - SonioxVoiceSettingsParam, + "SonioxVoiceSettingsParam", ] + +from .loopcount_param import LoopcountParam +from .aws_voice_settings_param import AwsVoiceSettingsParam +from .soniox_voice_settings_param import SonioxVoiceSettingsParam +from .telnyx_voice_settings_param import TelnyxVoiceSettingsParam +from .eleven_labs_voice_settings_param import ElevenLabsVoiceSettingsParam diff --git a/src/telnyx/types/calls/action_start_ai_assistant_params.py b/src/telnyx/types/calls/action_start_ai_assistant_params.py index b649f591b..2710fb311 100644 --- a/src/telnyx/types/calls/action_start_ai_assistant_params.py +++ b/src/telnyx/types/calls/action_start_ai_assistant_params.py @@ -5,25 +5,20 @@ from typing import Union, Iterable from typing_extensions import TypeAlias, TypedDict -from .tool_message_param import ToolMessageParam -from .user_message_param import UserMessageParam -from .system_message_param import SystemMessageParam -from .assistant_message_param import AssistantMessageParam -from .developer_message_param import DeveloperMessageParam -from .transcription_config_param import TranscriptionConfigParam -from .interruption_settings_param import InterruptionSettingsParam from ..call_assistant_request_param import CallAssistantRequestParam -from .ai_assistant_join_participant_param import AIAssistantJoinParticipantParam __all__ = ["ActionStartAIAssistantParams", "MessageHistory"] class ActionStartAIAssistantParams(TypedDict, total=False): assistant: CallAssistantRequestParam - """AI Assistant configuration. + """AI Assistant configuration and per-call overrides. - All fields except `id` are optional — the assistant's stored configuration will - be used as fallback for any omitted fields. + All fields except `id` are optional. Omitted assistant fields use the stored + configuration. Supplied `voice_settings` and `transcription` objects replace + their stored objects rather than merging individual settings; include every + setting you want to retain. `dynamic_variables` are merged, with request values + taking precedence. """ client_state: str @@ -46,7 +41,7 @@ class ActionStartAIAssistantParams(TypedDict, total=False): for `AWS.Polly.` voices. There is a 3,000 character limit. """ - interruption_settings: InterruptionSettingsParam + interruption_settings: "InterruptionSettingsParam" """Settings for handling user interruptions during assistant speech""" message_history: Iterable[MessageHistory] @@ -55,7 +50,7 @@ class ActionStartAIAssistantParams(TypedDict, total=False): Follows the same message format as the `ai_assistant_add_messages` command. """ - participants: Iterable[AIAssistantJoinParticipantParam] + participants: Iterable["AIAssistantJoinParticipantParam"] """A list of participants to add to the conversation when it starts.""" send_message_history_updates: bool @@ -66,7 +61,7 @@ class ActionStartAIAssistantParams(TypedDict, total=False): overrides this value when it is set. """ - transcription: TranscriptionConfigParam + transcription: "TranscriptionConfigParam" """The settings associated with speech to text for the voice assistant. This is only relevant if the assistant uses a text-to-text language model. Any @@ -76,5 +71,14 @@ class ActionStartAIAssistantParams(TypedDict, total=False): MessageHistory: TypeAlias = Union[ - UserMessageParam, AssistantMessageParam, ToolMessageParam, SystemMessageParam, DeveloperMessageParam + "UserMessageParam", "AssistantMessageParam", "ToolMessageParam", "SystemMessageParam", "DeveloperMessageParam" ] + +from .tool_message_param import ToolMessageParam +from .user_message_param import UserMessageParam +from .system_message_param import SystemMessageParam +from .assistant_message_param import AssistantMessageParam +from .developer_message_param import DeveloperMessageParam +from .transcription_config_param import TranscriptionConfigParam +from .interruption_settings_param import InterruptionSettingsParam +from .ai_assistant_join_participant_param import AIAssistantJoinParticipantParam diff --git a/src/telnyx/types/calls/action_start_conversation_relay_params.py b/src/telnyx/types/calls/action_start_conversation_relay_params.py index 9a0d45803..2f7bfbbe5 100644 --- a/src/telnyx/types/calls/action_start_conversation_relay_params.py +++ b/src/telnyx/types/calls/action_start_conversation_relay_params.py @@ -5,11 +5,6 @@ from typing import Dict, Union, Iterable from typing_extensions import Literal, Required, TypeAlias, TypedDict -from .aws_voice_settings_param import AwsVoiceSettingsParam -from .soniox_voice_settings_param import SonioxVoiceSettingsParam -from .telnyx_voice_settings_param import TelnyxVoiceSettingsParam -from .conversation_relay_interruptible import ConversationRelayInterruptible -from .eleven_labs_voice_settings_param import ElevenLabsVoiceSettingsParam from ..shared_params.xai_voice_settings import XaiVoiceSettings from ..conversation_relay_language_param import ConversationRelayLanguageParam from ..shared_params.azure_voice_settings import AzureVoiceSettings @@ -75,14 +70,14 @@ class ActionStartConversationRelayParams(TypedDict, total=False): greeting: str """Text played when the relay session starts.""" - interruptible: ConversationRelayInterruptible + interruptible: "ConversationRelayInterruptible" """Controls when caller input can interrupt assistant speech. `any` allows speech or DTMF interruptions; `none` disables interruptions; `speech` allows speech only; `dtmf` allows DTMF only. """ - interruptible_greeting: ConversationRelayInterruptible + interruptible_greeting: "ConversationRelayInterruptible" """Controls when caller input can interrupt assistant speech. `any` allows speech or DTMF interruptions; `none` disables interruptions; @@ -223,14 +218,14 @@ class ConversationRelaySettings(TypedDict, total=False): dtmf_detection: bool """Whether to enable DTMF detection during the relay session.""" - interruptible: ConversationRelayInterruptible + interruptible: "ConversationRelayInterruptible" """Controls when caller input can interrupt assistant speech. `any` allows speech or DTMF interruptions; `none` disables interruptions; `speech` allows speech only; `dtmf` allows DTMF only. """ - interruptible_greeting: ConversationRelayInterruptible + interruptible_greeting: "ConversationRelayInterruptible" """Controls when caller input can interrupt assistant speech. `any` allows speech or DTMF interruptions; `none` disables interruptions; @@ -242,13 +237,19 @@ class ConversationRelaySettings(TypedDict, total=False): VoiceSettings: TypeAlias = Union[ - ElevenLabsVoiceSettingsParam, - TelnyxVoiceSettingsParam, - AwsVoiceSettingsParam, + "ElevenLabsVoiceSettingsParam", + "TelnyxVoiceSettingsParam", + "AwsVoiceSettingsParam", MinimaxVoiceSettings, AzureVoiceSettings, ResembleVoiceSettings, InworldVoiceSettings, XaiVoiceSettings, - SonioxVoiceSettingsParam, + "SonioxVoiceSettingsParam", ] + +from .aws_voice_settings_param import AwsVoiceSettingsParam +from .soniox_voice_settings_param import SonioxVoiceSettingsParam +from .telnyx_voice_settings_param import TelnyxVoiceSettingsParam +from .conversation_relay_interruptible import ConversationRelayInterruptible +from .eleven_labs_voice_settings_param import ElevenLabsVoiceSettingsParam diff --git a/src/telnyx/types/calls/action_start_playback_params.py b/src/telnyx/types/calls/action_start_playback_params.py index c2da4c1eb..541feaee3 100644 --- a/src/telnyx/types/calls/action_start_playback_params.py +++ b/src/telnyx/types/calls/action_start_playback_params.py @@ -4,8 +4,6 @@ from typing_extensions import Literal, TypedDict -from .loopcount_param import LoopcountParam - __all__ = ["ActionStartPlaybackParams"] @@ -39,7 +37,7 @@ class ActionStartPlaybackParams(TypedDict, total=False): `call_control_id`. """ - loop: LoopcountParam + loop: "LoopcountParam" """The number of times the audio file should be played. If supplied, the value must be an integer between 1 and 100, or the special @@ -81,3 +79,6 @@ class ActionStartPlaybackParams(TypedDict, total=False): If supplied, the value must be either `self`, `opposite` or `both`. """ + + +from .loopcount_param import LoopcountParam diff --git a/src/telnyx/types/calls/action_start_transcription_params.py b/src/telnyx/types/calls/action_start_transcription_params.py index 24d3468bb..1ee3246a3 100644 --- a/src/telnyx/types/calls/action_start_transcription_params.py +++ b/src/telnyx/types/calls/action_start_transcription_params.py @@ -5,22 +5,6 @@ from typing import Union from typing_extensions import Literal, TypeAlias, TypedDict -from .deepgram_nova2_config_param import DeepgramNova2ConfigParam -from .deepgram_nova3_config_param import DeepgramNova3ConfigParam -from .transcription_engine_a_config_param import TranscriptionEngineAConfigParam -from .transcription_engine_b_config_param import TranscriptionEngineBConfigParam -from .transcription_engine_xai_config_param import TranscriptionEngineXaiConfigParam -from .transcription_engine_azure_config_param import TranscriptionEngineAzureConfigParam -from .transcription_engine_cohere_config_param import TranscriptionEngineCohereConfigParam -from .transcription_engine_google_config_param import TranscriptionEngineGoogleConfigParam -from .transcription_engine_humain_config_param import TranscriptionEngineHumainConfigParam -from .transcription_engine_reson8_config_param import TranscriptionEngineReson8ConfigParam -from .transcription_engine_soniox_config_param import TranscriptionEngineSonioxConfigParam -from .transcription_engine_telnyx_config_param import TranscriptionEngineTelnyxConfigParam -from .transcription_engine_parakeet_config_param import TranscriptionEngineParakeetConfigParam -from .transcription_engine_assemblyai_config_param import TranscriptionEngineAssemblyaiConfigParam -from .transcription_engine_speechmatics_config_param import TranscriptionEngineSpeechmaticsConfigParam - __all__ = ["ActionStartTranscriptionParams", "TranscriptionEngineConfig"] @@ -71,19 +55,35 @@ class ActionStartTranscriptionParams(TypedDict, total=False): TranscriptionEngineConfig: TypeAlias = Union[ - TranscriptionEngineGoogleConfigParam, - TranscriptionEngineTelnyxConfigParam, - TranscriptionEngineAzureConfigParam, - TranscriptionEngineXaiConfigParam, - TranscriptionEngineAssemblyaiConfigParam, - TranscriptionEngineSpeechmaticsConfigParam, - TranscriptionEngineSonioxConfigParam, - TranscriptionEngineParakeetConfigParam, - TranscriptionEngineHumainConfigParam, - TranscriptionEngineReson8ConfigParam, - TranscriptionEngineCohereConfigParam, - TranscriptionEngineAConfigParam, - TranscriptionEngineBConfigParam, - DeepgramNova2ConfigParam, - DeepgramNova3ConfigParam, + "TranscriptionEngineGoogleConfigParam", + "TranscriptionEngineTelnyxConfigParam", + "TranscriptionEngineAzureConfigParam", + "TranscriptionEngineXaiConfigParam", + "TranscriptionEngineAssemblyaiConfigParam", + "TranscriptionEngineSpeechmaticsConfigParam", + "TranscriptionEngineSonioxConfigParam", + "TranscriptionEngineParakeetConfigParam", + "TranscriptionEngineHumainConfigParam", + "TranscriptionEngineReson8ConfigParam", + "TranscriptionEngineCohereConfigParam", + "TranscriptionEngineAConfigParam", + "TranscriptionEngineBConfigParam", + "DeepgramNova2ConfigParam", + "DeepgramNova3ConfigParam", ] + +from .deepgram_nova2_config_param import DeepgramNova2ConfigParam +from .deepgram_nova3_config_param import DeepgramNova3ConfigParam +from .transcription_engine_a_config_param import TranscriptionEngineAConfigParam +from .transcription_engine_b_config_param import TranscriptionEngineBConfigParam +from .transcription_engine_xai_config_param import TranscriptionEngineXaiConfigParam +from .transcription_engine_azure_config_param import TranscriptionEngineAzureConfigParam +from .transcription_engine_cohere_config_param import TranscriptionEngineCohereConfigParam +from .transcription_engine_google_config_param import TranscriptionEngineGoogleConfigParam +from .transcription_engine_humain_config_param import TranscriptionEngineHumainConfigParam +from .transcription_engine_reson8_config_param import TranscriptionEngineReson8ConfigParam +from .transcription_engine_soniox_config_param import TranscriptionEngineSonioxConfigParam +from .transcription_engine_telnyx_config_param import TranscriptionEngineTelnyxConfigParam +from .transcription_engine_parakeet_config_param import TranscriptionEngineParakeetConfigParam +from .transcription_engine_assemblyai_config_param import TranscriptionEngineAssemblyaiConfigParam +from .transcription_engine_speechmatics_config_param import TranscriptionEngineSpeechmaticsConfigParam diff --git a/src/telnyx/types/calls/action_transfer_params.py b/src/telnyx/types/calls/action_transfer_params.py index 33634f182..7b3d82b71 100644 --- a/src/telnyx/types/calls/action_transfer_params.py +++ b/src/telnyx/types/calls/action_transfer_params.py @@ -28,7 +28,15 @@ class ActionTransferParams(TypedDict, total=False): `send_digits_on_answer` parameter takes precedence. """ - answering_machine_detection: Literal["premium", "detect", "detect_beep", "detect_words", "greeting_end", "disabled"] + answering_machine_detection: Literal[ + "premium", + "premium_ios_call_screening_detection", + "detect", + "detect_beep", + "detect_words", + "greeting_end", + "disabled", + ] """Enables Answering Machine Detection. When a call is answered, Telnyx runs real-time detection to determine if it was @@ -37,7 +45,16 @@ class ActionTransferParams(TypedDict, total=False): and a 'machine' is detected, you will receive another 'call.machine.greeting.ended' webhook when the answering machine greeting ends with a beep or silence. If `detect_beep` is used, you will only receive - 'call.machine.greeting.ended' if a beep is detected. + 'call.machine.greeting.ended' if a beep is detected. If + `answering_machine_detection` is set to `premium_ios_call_screening_detection`, + Premium AMD runs with iOS Call Screening support: after an initial `machine` + result, Telnyx listens for the iOS call-screening prompt to end or for an Apple + Call Screening tone, sends `call.machine.premium.greeting.ended` with + `result=prompt_ended` or `call.machine.premium.call_screening.detected` with + `result=screening` respectively. When the Apple Call Screening tone is detected, + Premium AMD is restarted on the screened call and a + `call.machine.premium.detection.ended` webhook with the post-screening + classification follows. """ answering_machine_detection_config: AnsweringMachineDetectionConfig @@ -45,7 +62,8 @@ class ActionTransferParams(TypedDict, total=False): Optional configuration parameters to modify 'answering_machine_detection' performance. Only `total_analysis_time_millis` and `greeting_duration_millis` parameters are applicable when `premium` is selected as - answering_machine_detection. + answering_machine_detection. `prompt_end_timeout_millis` is additionally + applicable when `premium_ios_call_screening_detection` is selected. """ audio_url: str @@ -294,7 +312,7 @@ class ActionTransferParams(TypedDict, total=False): class AnsweringMachineDetectionConfig(TypedDict, total=False): """ - Optional configuration parameters to modify 'answering_machine_detection' performance. Only `total_analysis_time_millis` and `greeting_duration_millis` parameters are applicable when `premium` is selected as answering_machine_detection. + Optional configuration parameters to modify 'answering_machine_detection' performance. Only `total_analysis_time_millis` and `greeting_duration_millis` parameters are applicable when `premium` is selected as answering_machine_detection. `prompt_end_timeout_millis` is additionally applicable when `premium_ios_call_screening_detection` is selected. """ after_greeting_silence_millis: int @@ -387,6 +405,14 @@ class AnsweringMachineDetectionConfig(TypedDict, total=False): maximum_word_length_millis: int """If a single word lasts longer than this threshold, consider it a machine.""" + prompt_end_timeout_millis: int + """ + Maximum time Telnyx waits, in milliseconds, for the iOS call-screening prompt to + end after Premium AMD initially detects a `machine`. Used when + `answering_machine_detection` is `premium_ios_call_screening_detection`. + Defaults to 5000 milliseconds. + """ + silence_threshold: int """Minimum noise threshold for any analysis.""" diff --git a/src/telnyx/types/calls/telnyx_voice_settings_param.py b/src/telnyx/types/calls/telnyx_voice_settings_param.py index 1bf31f33e..eced83358 100644 --- a/src/telnyx/types/calls/telnyx_voice_settings_param.py +++ b/src/telnyx/types/calls/telnyx_voice_settings_param.py @@ -14,6 +14,8 @@ class TelnyxVoiceSettingsParam(TypedDict, total=False): voice_speed: float """The voice speed to be used for the voice. - The voice speed must be between 0.1 and 2.0. Default value is 1.0. Not supported - for `Telnyx.Bayan.*` or `Telnyx.Sukhan.*` voices. + Telnyx `Ultra` voices accept values from 0.6 to 1.5; values outside that range + are rejected by the synthesis engine. `Qwen3TTS` and `KokoroTTS` accept the + field but do not apply it. Default value is 1.0. Not supported for + `Telnyx.Bayan.*` or `Telnyx.Sukhan.*` voices. """ diff --git a/src/telnyx/types/calls/transcription_engine_a_config_param.py b/src/telnyx/types/calls/transcription_engine_a_config_param.py index 1ac6684d6..511add7c1 100644 --- a/src/telnyx/types/calls/transcription_engine_a_config_param.py +++ b/src/telnyx/types/calls/transcription_engine_a_config_param.py @@ -6,7 +6,6 @@ from typing_extensions import Literal, TypedDict from ..._types import SequenceNotStr -from .google_transcription_language import GoogleTranscriptionLanguage __all__ = ["TranscriptionEngineAConfigParam", "SpeechContext"] @@ -31,7 +30,7 @@ class TranscriptionEngineAConfigParam(TypedDict, total=False): If set to false, only final results will be sent. """ - language: GoogleTranscriptionLanguage + language: "GoogleTranscriptionLanguage" """Language to use for speech recognition""" max_speaker_count: int @@ -63,3 +62,6 @@ class TranscriptionEngineAConfigParam(TypedDict, total=False): use_enhanced: bool """Enables enhanced transcription, this works for models `phone_call` and `video`.""" + + +from .google_transcription_language import GoogleTranscriptionLanguage diff --git a/src/telnyx/types/calls/transcription_engine_b_config_param.py b/src/telnyx/types/calls/transcription_engine_b_config_param.py index 295be65e3..9b6211250 100644 --- a/src/telnyx/types/calls/transcription_engine_b_config_param.py +++ b/src/telnyx/types/calls/transcription_engine_b_config_param.py @@ -4,13 +4,11 @@ from typing_extensions import Literal, TypedDict -from .telnyx_transcription_language import TelnyxTranscriptionLanguage - __all__ = ["TranscriptionEngineBConfigParam"] class TranscriptionEngineBConfigParam(TypedDict, total=False): - language: TelnyxTranscriptionLanguage + language: "TelnyxTranscriptionLanguage" """Language to use for speech recognition""" transcription_engine: Literal["B"] @@ -18,3 +16,6 @@ class TranscriptionEngineBConfigParam(TypedDict, total=False): transcription_model: Literal["openai/whisper-tiny", "openai/whisper-large-v3-turbo"] """The model to use for transcription.""" + + +from .telnyx_transcription_language import TelnyxTranscriptionLanguage diff --git a/src/telnyx/types/calls/transcription_engine_google_config_param.py b/src/telnyx/types/calls/transcription_engine_google_config_param.py index 3d8dde539..f304291eb 100644 --- a/src/telnyx/types/calls/transcription_engine_google_config_param.py +++ b/src/telnyx/types/calls/transcription_engine_google_config_param.py @@ -6,7 +6,6 @@ from typing_extensions import Literal, TypedDict from ..._types import SequenceNotStr -from .google_transcription_language import GoogleTranscriptionLanguage __all__ = ["TranscriptionEngineGoogleConfigParam", "SpeechContext"] @@ -31,7 +30,7 @@ class TranscriptionEngineGoogleConfigParam(TypedDict, total=False): If set to false, only final results will be sent. """ - language: GoogleTranscriptionLanguage + language: "GoogleTranscriptionLanguage" """Language to use for speech recognition""" max_speaker_count: int @@ -63,3 +62,6 @@ class TranscriptionEngineGoogleConfigParam(TypedDict, total=False): use_enhanced: bool """Enables enhanced transcription, this works for models `phone_call` and `video`.""" + + +from .google_transcription_language import GoogleTranscriptionLanguage diff --git a/src/telnyx/types/calls/transcription_engine_telnyx_config_param.py b/src/telnyx/types/calls/transcription_engine_telnyx_config_param.py index ce4b37b41..f5027672d 100644 --- a/src/telnyx/types/calls/transcription_engine_telnyx_config_param.py +++ b/src/telnyx/types/calls/transcription_engine_telnyx_config_param.py @@ -4,13 +4,11 @@ from typing_extensions import Literal, TypedDict -from .telnyx_transcription_language import TelnyxTranscriptionLanguage - __all__ = ["TranscriptionEngineTelnyxConfigParam"] class TranscriptionEngineTelnyxConfigParam(TypedDict, total=False): - language: TelnyxTranscriptionLanguage + language: "TelnyxTranscriptionLanguage" """Language to use for speech recognition""" transcription_engine: Literal["Telnyx"] @@ -18,3 +16,6 @@ class TranscriptionEngineTelnyxConfigParam(TypedDict, total=False): transcription_model: Literal["openai/whisper-tiny", "openai/whisper-large-v3-turbo"] """The model to use for transcription.""" + + +from .telnyx_transcription_language import TelnyxTranscriptionLanguage diff --git a/src/telnyx/types/calls/transcription_start_request_param.py b/src/telnyx/types/calls/transcription_start_request_param.py index c6d846875..8334ee59c 100644 --- a/src/telnyx/types/calls/transcription_start_request_param.py +++ b/src/telnyx/types/calls/transcription_start_request_param.py @@ -5,40 +5,24 @@ from typing import Union from typing_extensions import Literal, TypeAlias, TypedDict -from .deepgram_nova2_config_param import DeepgramNova2ConfigParam -from .deepgram_nova3_config_param import DeepgramNova3ConfigParam -from .transcription_engine_a_config_param import TranscriptionEngineAConfigParam -from .transcription_engine_b_config_param import TranscriptionEngineBConfigParam -from .transcription_engine_xai_config_param import TranscriptionEngineXaiConfigParam -from .transcription_engine_azure_config_param import TranscriptionEngineAzureConfigParam -from .transcription_engine_cohere_config_param import TranscriptionEngineCohereConfigParam -from .transcription_engine_google_config_param import TranscriptionEngineGoogleConfigParam -from .transcription_engine_humain_config_param import TranscriptionEngineHumainConfigParam -from .transcription_engine_reson8_config_param import TranscriptionEngineReson8ConfigParam -from .transcription_engine_soniox_config_param import TranscriptionEngineSonioxConfigParam -from .transcription_engine_telnyx_config_param import TranscriptionEngineTelnyxConfigParam -from .transcription_engine_parakeet_config_param import TranscriptionEngineParakeetConfigParam -from .transcription_engine_assemblyai_config_param import TranscriptionEngineAssemblyaiConfigParam -from .transcription_engine_speechmatics_config_param import TranscriptionEngineSpeechmaticsConfigParam - __all__ = ["TranscriptionStartRequestParam", "TranscriptionEngineConfig"] TranscriptionEngineConfig: TypeAlias = Union[ - TranscriptionEngineGoogleConfigParam, - TranscriptionEngineTelnyxConfigParam, - TranscriptionEngineAzureConfigParam, - TranscriptionEngineXaiConfigParam, - TranscriptionEngineAssemblyaiConfigParam, - TranscriptionEngineSpeechmaticsConfigParam, - TranscriptionEngineSonioxConfigParam, - TranscriptionEngineParakeetConfigParam, - TranscriptionEngineHumainConfigParam, - TranscriptionEngineReson8ConfigParam, - TranscriptionEngineCohereConfigParam, - TranscriptionEngineAConfigParam, - TranscriptionEngineBConfigParam, - DeepgramNova2ConfigParam, - DeepgramNova3ConfigParam, + "TranscriptionEngineGoogleConfigParam", + "TranscriptionEngineTelnyxConfigParam", + "TranscriptionEngineAzureConfigParam", + "TranscriptionEngineXaiConfigParam", + "TranscriptionEngineAssemblyaiConfigParam", + "TranscriptionEngineSpeechmaticsConfigParam", + "TranscriptionEngineSonioxConfigParam", + "TranscriptionEngineParakeetConfigParam", + "TranscriptionEngineHumainConfigParam", + "TranscriptionEngineReson8ConfigParam", + "TranscriptionEngineCohereConfigParam", + "TranscriptionEngineAConfigParam", + "TranscriptionEngineBConfigParam", + "DeepgramNova2ConfigParam", + "DeepgramNova3ConfigParam", ] @@ -86,3 +70,20 @@ class TranscriptionStartRequestParam(TypedDict, total=False): Use `inbound` for the leg that requested the transcription, `outbound` for the other leg, and `both` for both legs of the call. Will default to `inbound`. """ + + +from .deepgram_nova2_config_param import DeepgramNova2ConfigParam +from .deepgram_nova3_config_param import DeepgramNova3ConfigParam +from .transcription_engine_a_config_param import TranscriptionEngineAConfigParam +from .transcription_engine_b_config_param import TranscriptionEngineBConfigParam +from .transcription_engine_xai_config_param import TranscriptionEngineXaiConfigParam +from .transcription_engine_azure_config_param import TranscriptionEngineAzureConfigParam +from .transcription_engine_cohere_config_param import TranscriptionEngineCohereConfigParam +from .transcription_engine_google_config_param import TranscriptionEngineGoogleConfigParam +from .transcription_engine_humain_config_param import TranscriptionEngineHumainConfigParam +from .transcription_engine_reson8_config_param import TranscriptionEngineReson8ConfigParam +from .transcription_engine_soniox_config_param import TranscriptionEngineSonioxConfigParam +from .transcription_engine_telnyx_config_param import TranscriptionEngineTelnyxConfigParam +from .transcription_engine_parakeet_config_param import TranscriptionEngineParakeetConfigParam +from .transcription_engine_assemblyai_config_param import TranscriptionEngineAssemblyaiConfigParam +from .transcription_engine_speechmatics_config_param import TranscriptionEngineSpeechmaticsConfigParam diff --git a/src/telnyx/types/conferences/action_hold_params.py b/src/telnyx/types/conferences/action_hold_params.py index 6d0609609..caadaf7b2 100644 --- a/src/telnyx/types/conferences/action_hold_params.py +++ b/src/telnyx/types/conferences/action_hold_params.py @@ -5,7 +5,6 @@ from typing_extensions import TypedDict from ..._types import SequenceNotStr -from .conference_region import ConferenceRegion __all__ = ["ActionHoldParams"] @@ -31,8 +30,11 @@ class ActionHoldParams(TypedDict, total=False): WAV or MP3 file. """ - region: ConferenceRegion + region: "ConferenceRegion" """Region where the conference data is located. Defaults to the region defined in user's data locality settings (Europe or US). """ + + +from .conference_region import ConferenceRegion diff --git a/src/telnyx/types/conferences/action_join_params.py b/src/telnyx/types/conferences/action_join_params.py index f3da43905..64b6d0294 100644 --- a/src/telnyx/types/conferences/action_join_params.py +++ b/src/telnyx/types/conferences/action_join_params.py @@ -5,7 +5,6 @@ from typing_extensions import Literal, Required, TypedDict from ..._types import SequenceNotStr -from .conference_region import ConferenceRegion __all__ = ["ActionJoinParams"] @@ -72,7 +71,7 @@ class ActionJoinParams(TypedDict, total=False): Defaults to "false". """ - region: ConferenceRegion + region: "ConferenceRegion" """Region where the conference data is located. Defaults to the region defined in user's data locality settings (Europe or US). @@ -106,3 +105,6 @@ class ActionJoinParams(TypedDict, total=False): If none provided, the supervisor will join the conference as a monitoring participant only. """ + + +from .conference_region import ConferenceRegion diff --git a/src/telnyx/types/conferences/action_leave_params.py b/src/telnyx/types/conferences/action_leave_params.py index 395c83be4..9c9ff7fdf 100644 --- a/src/telnyx/types/conferences/action_leave_params.py +++ b/src/telnyx/types/conferences/action_leave_params.py @@ -4,8 +4,6 @@ from typing_extensions import Literal, Required, TypedDict -from .conference_region import ConferenceRegion - __all__ = ["ActionLeaveParams"] @@ -27,8 +25,11 @@ class ActionLeaveParams(TypedDict, total=False): has already been executed. """ - region: ConferenceRegion + region: "ConferenceRegion" """Region where the conference data is located. Defaults to the region defined in user's data locality settings (Europe or US). """ + + +from .conference_region import ConferenceRegion diff --git a/src/telnyx/types/conferences/action_mute_params.py b/src/telnyx/types/conferences/action_mute_params.py index ba418e2e0..c1bc863ad 100644 --- a/src/telnyx/types/conferences/action_mute_params.py +++ b/src/telnyx/types/conferences/action_mute_params.py @@ -5,7 +5,6 @@ from typing_extensions import TypedDict from ..._types import SequenceNotStr -from .conference_region import ConferenceRegion __all__ = ["ActionMuteParams"] @@ -17,8 +16,11 @@ class ActionMuteParams(TypedDict, total=False): When empty all participants will be muted. """ - region: ConferenceRegion + region: "ConferenceRegion" """Region where the conference data is located. Defaults to the region defined in user's data locality settings (Europe or US). """ + + +from .conference_region import ConferenceRegion diff --git a/src/telnyx/types/conferences/action_play_params.py b/src/telnyx/types/conferences/action_play_params.py index 759000158..e34d47a13 100644 --- a/src/telnyx/types/conferences/action_play_params.py +++ b/src/telnyx/types/conferences/action_play_params.py @@ -5,7 +5,6 @@ from typing_extensions import TypedDict from ..._types import SequenceNotStr -from .conference_region import ConferenceRegion from ..calls.loopcount_param import LoopcountParam __all__ = ["ActionPlayParams"] @@ -39,8 +38,11 @@ class ActionPlayParams(TypedDict, total=False): WAV or MP3 file. """ - region: ConferenceRegion + region: "ConferenceRegion" """Region where the conference data is located. Defaults to the region defined in user's data locality settings (Europe or US). """ + + +from .conference_region import ConferenceRegion diff --git a/src/telnyx/types/conferences/action_record_pause_params.py b/src/telnyx/types/conferences/action_record_pause_params.py index d9750674d..7d4a8ce10 100644 --- a/src/telnyx/types/conferences/action_record_pause_params.py +++ b/src/telnyx/types/conferences/action_record_pause_params.py @@ -4,8 +4,6 @@ from typing_extensions import TypedDict -from .conference_region import ConferenceRegion - __all__ = ["ActionRecordPauseParams"] @@ -20,8 +18,11 @@ class ActionRecordPauseParams(TypedDict, total=False): recording_id: str """Use this field to pause specific recording.""" - region: ConferenceRegion + region: "ConferenceRegion" """Region where the conference data is located. Defaults to the region defined in user's data locality settings (Europe or US). """ + + +from .conference_region import ConferenceRegion diff --git a/src/telnyx/types/conferences/action_record_resume_params.py b/src/telnyx/types/conferences/action_record_resume_params.py index a8d3b5025..ab93c294f 100644 --- a/src/telnyx/types/conferences/action_record_resume_params.py +++ b/src/telnyx/types/conferences/action_record_resume_params.py @@ -4,8 +4,6 @@ from typing_extensions import TypedDict -from .conference_region import ConferenceRegion - __all__ = ["ActionRecordResumeParams"] @@ -20,8 +18,11 @@ class ActionRecordResumeParams(TypedDict, total=False): recording_id: str """Use this field to resume specific recording.""" - region: ConferenceRegion + region: "ConferenceRegion" """Region where the conference data is located. Defaults to the region defined in user's data locality settings (Europe or US). """ + + +from .conference_region import ConferenceRegion diff --git a/src/telnyx/types/conferences/action_record_start_params.py b/src/telnyx/types/conferences/action_record_start_params.py index 196066afd..17e6436ee 100644 --- a/src/telnyx/types/conferences/action_record_start_params.py +++ b/src/telnyx/types/conferences/action_record_start_params.py @@ -4,8 +4,6 @@ from typing_extensions import Literal, Required, TypedDict -from .conference_region import ConferenceRegion - __all__ = ["ActionRecordStartParams"] @@ -38,7 +36,7 @@ class ActionRecordStartParams(TypedDict, total=False): play_beep: bool """If enabled, a beep sound will be played at the start of a recording.""" - region: ConferenceRegion + region: "ConferenceRegion" """Region where the conference data is located. Defaults to the region defined in user's data locality settings (Europe or US). @@ -49,3 +47,6 @@ class ActionRecordStartParams(TypedDict, total=False): When set to `trim-silence`, silence will be removed from the beginning and end of the recording. """ + + +from .conference_region import ConferenceRegion diff --git a/src/telnyx/types/conferences/action_record_stop_params.py b/src/telnyx/types/conferences/action_record_stop_params.py index f684ed639..27879954d 100644 --- a/src/telnyx/types/conferences/action_record_stop_params.py +++ b/src/telnyx/types/conferences/action_record_stop_params.py @@ -4,8 +4,6 @@ from typing_extensions import TypedDict -from .conference_region import ConferenceRegion - __all__ = ["ActionRecordStopParams"] @@ -26,8 +24,11 @@ class ActionRecordStopParams(TypedDict, total=False): recording_id: str """Uniquely identifies the resource.""" - region: ConferenceRegion + region: "ConferenceRegion" """Region where the conference data is located. Defaults to the region defined in user's data locality settings (Europe or US). """ + + +from .conference_region import ConferenceRegion diff --git a/src/telnyx/types/conferences/action_speak_params.py b/src/telnyx/types/conferences/action_speak_params.py index cecd5dc25..e8d83f5d8 100644 --- a/src/telnyx/types/conferences/action_speak_params.py +++ b/src/telnyx/types/conferences/action_speak_params.py @@ -6,7 +6,6 @@ from typing_extensions import Literal, Required, TypeAlias, TypedDict from ..._types import SequenceNotStr -from .conference_region import ConferenceRegion from ..calls.aws_voice_settings_param import AwsVoiceSettingsParam from ..shared_params.xai_voice_settings import XaiVoiceSettings from ..calls.soniox_voice_settings_param import SonioxVoiceSettingsParam @@ -142,7 +141,7 @@ class ActionSpeakParams(TypedDict, total=False): (SSML). """ - region: ConferenceRegion + region: "ConferenceRegion" """Region where the conference data is located. Defaults to the region defined in user's data locality settings (Europe or US). @@ -163,3 +162,5 @@ class ActionSpeakParams(TypedDict, total=False): XaiVoiceSettings, SonioxVoiceSettingsParam, ] + +from .conference_region import ConferenceRegion diff --git a/src/telnyx/types/conferences/action_stop_params.py b/src/telnyx/types/conferences/action_stop_params.py index 27d19392b..4ce7e34b4 100644 --- a/src/telnyx/types/conferences/action_stop_params.py +++ b/src/telnyx/types/conferences/action_stop_params.py @@ -5,7 +5,6 @@ from typing_extensions import TypedDict from ..._types import SequenceNotStr -from .conference_region import ConferenceRegion __all__ = ["ActionStopParams"] @@ -17,8 +16,11 @@ class ActionStopParams(TypedDict, total=False): played to. If not given, the audio will be stoped to the entire conference. """ - region: ConferenceRegion + region: "ConferenceRegion" """Region where the conference data is located. Defaults to the region defined in user's data locality settings (Europe or US). """ + + +from .conference_region import ConferenceRegion diff --git a/src/telnyx/types/conferences/action_unhold_params.py b/src/telnyx/types/conferences/action_unhold_params.py index 1465c9935..7d0c40de2 100644 --- a/src/telnyx/types/conferences/action_unhold_params.py +++ b/src/telnyx/types/conferences/action_unhold_params.py @@ -5,7 +5,6 @@ from typing_extensions import Required, TypedDict from ..._types import SequenceNotStr -from .conference_region import ConferenceRegion __all__ = ["ActionUnholdParams"] @@ -17,8 +16,11 @@ class ActionUnholdParams(TypedDict, total=False): Enter each call control ID to be unheld. """ - region: ConferenceRegion + region: "ConferenceRegion" """Region where the conference data is located. Defaults to the region defined in user's data locality settings (Europe or US). """ + + +from .conference_region import ConferenceRegion diff --git a/src/telnyx/types/conferences/action_unmute_params.py b/src/telnyx/types/conferences/action_unmute_params.py index 19dab1d67..9054528ce 100644 --- a/src/telnyx/types/conferences/action_unmute_params.py +++ b/src/telnyx/types/conferences/action_unmute_params.py @@ -5,7 +5,6 @@ from typing_extensions import TypedDict from ..._types import SequenceNotStr -from .conference_region import ConferenceRegion __all__ = ["ActionUnmuteParams"] @@ -18,8 +17,11 @@ class ActionUnmuteParams(TypedDict, total=False): unmuted. """ - region: ConferenceRegion + region: "ConferenceRegion" """Region where the conference data is located. Defaults to the region defined in user's data locality settings (Europe or US). """ + + +from .conference_region import ConferenceRegion diff --git a/src/telnyx/types/conferences/action_update_params.py b/src/telnyx/types/conferences/action_update_params.py index c6476c36e..c01d1d730 100644 --- a/src/telnyx/types/conferences/action_update_params.py +++ b/src/telnyx/types/conferences/action_update_params.py @@ -5,7 +5,6 @@ from typing_extensions import Literal, Required, TypedDict from ..._types import SequenceNotStr -from .conference_region import ConferenceRegion __all__ = ["ActionUpdateParams"] @@ -31,7 +30,7 @@ class ActionUpdateParams(TypedDict, total=False): has already been executed. """ - region: ConferenceRegion + region: "ConferenceRegion" """Region where the conference data is located. Defaults to the region defined in user's data locality settings (Europe or US). @@ -43,3 +42,6 @@ class ActionUpdateParams(TypedDict, total=False): If none provided, the supervisor will join the conference as a monitoring participant only. """ + + +from .conference_region import ConferenceRegion diff --git a/src/telnyx/types/conversation_relay_embedded_config_param.py b/src/telnyx/types/conversation_relay_embedded_config_param.py index d2e169064..4151f296a 100644 --- a/src/telnyx/types/conversation_relay_embedded_config_param.py +++ b/src/telnyx/types/conversation_relay_embedded_config_param.py @@ -5,31 +5,18 @@ from typing import Dict, Union, Iterable from typing_extensions import Literal, Required, TypeAlias, TypedDict -from .calls.aws_voice_settings_param import AwsVoiceSettingsParam -from .shared_params.xai_voice_settings import XaiVoiceSettings -from .calls.soniox_voice_settings_param import SonioxVoiceSettingsParam -from .calls.telnyx_voice_settings_param import TelnyxVoiceSettingsParam -from .conversation_relay_language_param import ConversationRelayLanguageParam -from .shared_params.azure_voice_settings import AzureVoiceSettings -from .shared_params.inworld_voice_settings import InworldVoiceSettings -from .shared_params.minimax_voice_settings import MinimaxVoiceSettings -from .shared_params.resemble_voice_settings import ResembleVoiceSettings -from .calls.conversation_relay_interruptible import ConversationRelayInterruptible -from .calls.eleven_labs_voice_settings_param import ElevenLabsVoiceSettingsParam -from .conversation_relay_interruption_settings_param import ConversationRelayInterruptionSettingsParam - __all__ = ["ConversationRelayEmbeddedConfigParam", "VoiceSettings"] VoiceSettings: TypeAlias = Union[ - ElevenLabsVoiceSettingsParam, - TelnyxVoiceSettingsParam, - AwsVoiceSettingsParam, - MinimaxVoiceSettings, - AzureVoiceSettings, - ResembleVoiceSettings, - InworldVoiceSettings, - XaiVoiceSettings, - SonioxVoiceSettingsParam, + "ElevenLabsVoiceSettingsParam", + "TelnyxVoiceSettingsParam", + "AwsVoiceSettingsParam", + "MinimaxVoiceSettings", + "AzureVoiceSettings", + "ResembleVoiceSettings", + "InworldVoiceSettings", + "XaiVoiceSettings", + "SonioxVoiceSettingsParam", ] @@ -56,27 +43,27 @@ class ConversationRelayEmbeddedConfigParam(TypedDict, total=False): greeting: str """Text played when the relay session starts.""" - interruptible: ConversationRelayInterruptible + interruptible: "ConversationRelayInterruptible" """Controls when caller input can interrupt assistant speech. `any` allows speech or DTMF interruptions; `none` disables interruptions; `speech` allows speech only; `dtmf` allows DTMF only. """ - interruptible_greeting: ConversationRelayInterruptible + interruptible_greeting: "ConversationRelayInterruptible" """Controls when caller input can interrupt assistant speech. `any` allows speech or DTMF interruptions; `none` disables interruptions; `speech` allows speech only; `dtmf` allows DTMF only. """ - interruption_settings: ConversationRelayInterruptionSettingsParam + interruption_settings: "ConversationRelayInterruptionSettingsParam" """Settings for handling caller interruptions during Conversation Relay speech.""" language: str """Default language for both text-to-speech and speech recognition.""" - languages: Iterable[ConversationRelayLanguageParam] + languages: Iterable["ConversationRelayLanguageParam"] """Per-language TTS and transcription settings.""" provider: str @@ -162,3 +149,17 @@ class ConversationRelayEmbeddedConfigParam(TypedDict, total=False): voice_settings: VoiceSettings """The settings associated with the voice selected""" + + +from .calls.aws_voice_settings_param import AwsVoiceSettingsParam +from .shared_params.xai_voice_settings import XaiVoiceSettings +from .calls.soniox_voice_settings_param import SonioxVoiceSettingsParam +from .calls.telnyx_voice_settings_param import TelnyxVoiceSettingsParam +from .conversation_relay_language_param import ConversationRelayLanguageParam +from .shared_params.azure_voice_settings import AzureVoiceSettings +from .shared_params.inworld_voice_settings import InworldVoiceSettings +from .shared_params.minimax_voice_settings import MinimaxVoiceSettings +from .shared_params.resemble_voice_settings import ResembleVoiceSettings +from .calls.conversation_relay_interruptible import ConversationRelayInterruptible +from .calls.eleven_labs_voice_settings_param import ElevenLabsVoiceSettingsParam +from .conversation_relay_interruption_settings_param import ConversationRelayInterruptionSettingsParam diff --git a/src/telnyx/types/conversation_relay_interruption_settings_param.py b/src/telnyx/types/conversation_relay_interruption_settings_param.py index 0b86cef82..cbca27098 100644 --- a/src/telnyx/types/conversation_relay_interruption_settings_param.py +++ b/src/telnyx/types/conversation_relay_interruption_settings_param.py @@ -4,8 +4,6 @@ from typing_extensions import TypedDict -from .calls.conversation_relay_interruptible import ConversationRelayInterruptible - __all__ = ["ConversationRelayInterruptionSettingsParam"] @@ -19,23 +17,26 @@ class ConversationRelayInterruptionSettingsParam(TypedDict, total=False): `interruptible=none`. """ - interruptible: ConversationRelayInterruptible + interruptible: "ConversationRelayInterruptible" """Controls when caller input can interrupt assistant speech. `any` allows speech or DTMF interruptions; `none` disables interruptions; `speech` allows speech only; `dtmf` allows DTMF only. """ - interruptible_greeting: ConversationRelayInterruptible + interruptible_greeting: "ConversationRelayInterruptible" """Controls when caller input can interrupt assistant speech. `any` allows speech or DTMF interruptions; `none` disables interruptions; `speech` allows speech only; `dtmf` allows DTMF only. """ - welcome_greeting_interruptible: ConversationRelayInterruptible + welcome_greeting_interruptible: "ConversationRelayInterruptible" """Controls when caller input can interrupt assistant speech. `any` allows speech or DTMF interruptions; `none` disables interruptions; `speech` allows speech only; `dtmf` allows DTMF only. """ + + +from .calls.conversation_relay_interruptible import ConversationRelayInterruptible diff --git a/src/telnyx/types/conversation_relay_language_param.py b/src/telnyx/types/conversation_relay_language_param.py index 3e9b28d3d..ad65a7a2d 100644 --- a/src/telnyx/types/conversation_relay_language_param.py +++ b/src/telnyx/types/conversation_relay_language_param.py @@ -5,28 +5,18 @@ from typing import Dict, Union from typing_extensions import Literal, Required, TypeAlias, TypedDict -from .calls.aws_voice_settings_param import AwsVoiceSettingsParam -from .shared_params.xai_voice_settings import XaiVoiceSettings -from .calls.soniox_voice_settings_param import SonioxVoiceSettingsParam -from .calls.telnyx_voice_settings_param import TelnyxVoiceSettingsParam -from .shared_params.azure_voice_settings import AzureVoiceSettings -from .shared_params.inworld_voice_settings import InworldVoiceSettings -from .shared_params.minimax_voice_settings import MinimaxVoiceSettings -from .shared_params.resemble_voice_settings import ResembleVoiceSettings -from .calls.eleven_labs_voice_settings_param import ElevenLabsVoiceSettingsParam - __all__ = ["ConversationRelayLanguageParam", "VoiceSettings"] VoiceSettings: TypeAlias = Union[ - ElevenLabsVoiceSettingsParam, - TelnyxVoiceSettingsParam, - AwsVoiceSettingsParam, - MinimaxVoiceSettings, - AzureVoiceSettings, - ResembleVoiceSettings, - InworldVoiceSettings, - XaiVoiceSettings, - SonioxVoiceSettingsParam, + "ElevenLabsVoiceSettingsParam", + "TelnyxVoiceSettingsParam", + "AwsVoiceSettingsParam", + "MinimaxVoiceSettings", + "AzureVoiceSettings", + "ResembleVoiceSettings", + "InworldVoiceSettings", + "XaiVoiceSettings", + "SonioxVoiceSettingsParam", ] @@ -79,3 +69,14 @@ class ConversationRelayLanguageParam(TypedDict, total=False): voice_settings: VoiceSettings """The settings associated with the voice selected""" + + +from .calls.aws_voice_settings_param import AwsVoiceSettingsParam +from .shared_params.xai_voice_settings import XaiVoiceSettings +from .calls.soniox_voice_settings_param import SonioxVoiceSettingsParam +from .calls.telnyx_voice_settings_param import TelnyxVoiceSettingsParam +from .shared_params.azure_voice_settings import AzureVoiceSettings +from .shared_params.inworld_voice_settings import InworldVoiceSettings +from .shared_params.minimax_voice_settings import MinimaxVoiceSettings +from .shared_params.resemble_voice_settings import ResembleVoiceSettings +from .calls.eleven_labs_voice_settings_param import ElevenLabsVoiceSettingsParam diff --git a/src/telnyx/types/credential_connection_create_params.py b/src/telnyx/types/credential_connection_create_params.py index 78485bddf..f791c183d 100644 --- a/src/telnyx/types/credential_connection_create_params.py +++ b/src/telnyx/types/credential_connection_create_params.py @@ -6,15 +6,6 @@ from typing_extensions import Literal, Required, TypedDict from .._types import SequenceNotStr -from .dtmf_type import DtmfType -from .encrypted_media import EncryptedMedia -from .anchorsite_override import AnchorsiteOverride -from .credential_inbound_param import CredentialInboundParam -from .credential_outbound_param import CredentialOutboundParam -from .connection_noise_suppression import ConnectionNoiseSuppression -from .connection_rtcp_settings_param import ConnectionRtcpSettingsParam -from .shared_params.connection_jitter_buffer import ConnectionJitterBuffer -from .shared_params.connection_noise_suppression_details import ConnectionNoiseSuppressionDetails __all__ = ["CredentialConnectionCreateParams"] @@ -39,7 +30,7 @@ class CredentialConnectionCreateParams(TypedDict, total=False): active: bool """Defaults to true""" - anchorsite_override: AnchorsiteOverride + anchorsite_override: "AnchorsiteOverride" """ `Latency` directs Telnyx to route media through the site with the lowest round-trip time to the user's connection. Telnyx calculates this time using ICMP @@ -60,7 +51,7 @@ class CredentialConnectionCreateParams(TypedDict, total=False): RTP timeout. """ - dtmf_type: DtmfType + dtmf_type: "DtmfType" """Sets the type of DTMF digits sent from Telnyx to this Connection. Note that DTMF digits sent to Telnyx will be accepted in all formats. @@ -72,18 +63,18 @@ class CredentialConnectionCreateParams(TypedDict, total=False): scenarios. """ - encrypted_media: Optional[EncryptedMedia] + encrypted_media: Optional["EncryptedMedia"] """Enable use of SRTP for encryption. Cannot be set if the transport_portocol is TLS. """ - inbound: CredentialInboundParam + inbound: "CredentialInboundParam" ios_push_credential_id: Optional[str] """The uuid of the push credential for Ios""" - jitter_buffer: ConnectionJitterBuffer + jitter_buffer: "ConnectionJitterBuffer" """Configuration options for Jitter Buffer. Enables Jitter Buffer for RTP streams of SIP Trunking calls. The feature is off @@ -92,7 +83,7 @@ class CredentialConnectionCreateParams(TypedDict, total=False): smaller values reduce latency but are more sensitive to jitter and reordering. """ - noise_suppression: ConnectionNoiseSuppression + noise_suppression: "ConnectionNoiseSuppression" """Controls when noise suppression is applied to calls. When set to 'inbound', noise suppression is applied to incoming audio. When set @@ -100,7 +91,7 @@ class CredentialConnectionCreateParams(TypedDict, total=False): in both directions. When set to 'disabled', noise suppression is turned off. """ - noise_suppression_details: ConnectionNoiseSuppressionDetails + noise_suppression_details: "ConnectionNoiseSuppressionDetails" """Configuration options for noise suppression. These settings are stored regardless of the noise_suppression value, but only @@ -116,9 +107,9 @@ class CredentialConnectionCreateParams(TypedDict, total=False): use T38 on just one leg of the call depending on each leg's settings. """ - outbound: CredentialOutboundParam + outbound: "CredentialOutboundParam" - rtcp_settings: ConnectionRtcpSettingsParam + rtcp_settings: "ConnectionRtcpSettingsParam" sip_uri_calling_preference: Literal["disabled", "unrestricted", "internal"] """This feature enables inbound SIP URI calls to your Credential Auth Connection. @@ -153,3 +144,14 @@ class CredentialConnectionCreateParams(TypedDict, total=False): webhook_timeout_secs: Optional[int] """Specifies how many seconds to wait before timing out a webhook.""" + + +from .dtmf_type import DtmfType +from .encrypted_media import EncryptedMedia +from .anchorsite_override import AnchorsiteOverride +from .credential_inbound_param import CredentialInboundParam +from .credential_outbound_param import CredentialOutboundParam +from .connection_noise_suppression import ConnectionNoiseSuppression +from .connection_rtcp_settings_param import ConnectionRtcpSettingsParam +from .shared_params.connection_jitter_buffer import ConnectionJitterBuffer +from .shared_params.connection_noise_suppression_details import ConnectionNoiseSuppressionDetails diff --git a/src/telnyx/types/credential_connection_update_params.py b/src/telnyx/types/credential_connection_update_params.py index a4427c094..31c7dcbd3 100644 --- a/src/telnyx/types/credential_connection_update_params.py +++ b/src/telnyx/types/credential_connection_update_params.py @@ -6,15 +6,6 @@ from typing_extensions import Literal, TypedDict from .._types import SequenceNotStr -from .dtmf_type import DtmfType -from .encrypted_media import EncryptedMedia -from .anchorsite_override import AnchorsiteOverride -from .credential_inbound_param import CredentialInboundParam -from .credential_outbound_param import CredentialOutboundParam -from .connection_noise_suppression import ConnectionNoiseSuppression -from .connection_rtcp_settings_param import ConnectionRtcpSettingsParam -from .shared_params.connection_jitter_buffer import ConnectionJitterBuffer -from .shared_params.connection_noise_suppression_details import ConnectionNoiseSuppressionDetails __all__ = ["CredentialConnectionUpdateParams"] @@ -23,7 +14,7 @@ class CredentialConnectionUpdateParams(TypedDict, total=False): active: bool """Defaults to true""" - anchorsite_override: AnchorsiteOverride + anchorsite_override: "AnchorsiteOverride" """ `Latency` directs Telnyx to route media through the site with the lowest round-trip time to the user's connection. Telnyx calculates this time using ICMP @@ -54,7 +45,7 @@ class CredentialConnectionUpdateParams(TypedDict, total=False): RTP timeout. """ - dtmf_type: DtmfType + dtmf_type: "DtmfType" """Sets the type of DTMF digits sent from Telnyx to this Connection. Note that DTMF digits sent to Telnyx will be accepted in all formats. @@ -66,18 +57,18 @@ class CredentialConnectionUpdateParams(TypedDict, total=False): scenarios. """ - encrypted_media: Optional[EncryptedMedia] + encrypted_media: Optional["EncryptedMedia"] """Enable use of SRTP for encryption. Cannot be set if the transport_portocol is TLS. """ - inbound: CredentialInboundParam + inbound: "CredentialInboundParam" ios_push_credential_id: Optional[str] """The uuid of the push credential for Ios""" - jitter_buffer: ConnectionJitterBuffer + jitter_buffer: "ConnectionJitterBuffer" """Configuration options for Jitter Buffer. Enables Jitter Buffer for RTP streams of SIP Trunking calls. The feature is off @@ -86,7 +77,7 @@ class CredentialConnectionUpdateParams(TypedDict, total=False): smaller values reduce latency but are more sensitive to jitter and reordering. """ - noise_suppression: ConnectionNoiseSuppression + noise_suppression: "ConnectionNoiseSuppression" """Controls when noise suppression is applied to calls. When set to 'inbound', noise suppression is applied to incoming audio. When set @@ -94,7 +85,7 @@ class CredentialConnectionUpdateParams(TypedDict, total=False): in both directions. When set to 'disabled', noise suppression is turned off. """ - noise_suppression_details: ConnectionNoiseSuppressionDetails + noise_suppression_details: "ConnectionNoiseSuppressionDetails" """Configuration options for noise suppression. These settings are stored regardless of the noise_suppression value, but only @@ -110,7 +101,7 @@ class CredentialConnectionUpdateParams(TypedDict, total=False): use T38 on just one leg of the call depending on each leg's settings. """ - outbound: CredentialOutboundParam + outbound: "CredentialOutboundParam" password: str """The password to be used as part of the credentials. @@ -118,7 +109,7 @@ class CredentialConnectionUpdateParams(TypedDict, total=False): Must be 8 to 128 characters long. """ - rtcp_settings: ConnectionRtcpSettingsParam + rtcp_settings: "ConnectionRtcpSettingsParam" sip_uri_calling_preference: Literal["disabled", "unrestricted", "internal"] """This feature enables inbound SIP URI calls to your Credential Auth Connection. @@ -156,3 +147,14 @@ class CredentialConnectionUpdateParams(TypedDict, total=False): webhook_timeout_secs: Optional[int] """Specifies how many seconds to wait before timing out a webhook.""" + + +from .dtmf_type import DtmfType +from .encrypted_media import EncryptedMedia +from .anchorsite_override import AnchorsiteOverride +from .credential_inbound_param import CredentialInboundParam +from .credential_outbound_param import CredentialOutboundParam +from .connection_noise_suppression import ConnectionNoiseSuppression +from .connection_rtcp_settings_param import ConnectionRtcpSettingsParam +from .shared_params.connection_jitter_buffer import ConnectionJitterBuffer +from .shared_params.connection_noise_suppression_details import ConnectionNoiseSuppressionDetails diff --git a/src/telnyx/types/custom_storage_credential_create_params.py b/src/telnyx/types/custom_storage_credential_create_params.py index 1e8aa3f36..9290fd8c3 100644 --- a/src/telnyx/types/custom_storage_credential_create_params.py +++ b/src/telnyx/types/custom_storage_credential_create_params.py @@ -5,11 +5,6 @@ from typing import Union from typing_extensions import Literal, Required, TypeAlias, TypedDict -from .s3_configuration_data_param import S3ConfigurationDataParam -from .gcs_configuration_data_param import GcsConfigurationDataParam -from .azure_configuration_data_param import AzureConfigurationDataParam -from .s3_generic_configuration_data_param import S3GenericConfigurationDataParam - __all__ = ["CustomStorageCredentialCreateParams", "Configuration"] @@ -20,5 +15,13 @@ class CustomStorageCredentialCreateParams(TypedDict, total=False): Configuration: TypeAlias = Union[ - GcsConfigurationDataParam, S3ConfigurationDataParam, S3GenericConfigurationDataParam, AzureConfigurationDataParam + "GcsConfigurationDataParam", + "S3ConfigurationDataParam", + "S3GenericConfigurationDataParam", + "AzureConfigurationDataParam", ] + +from .s3_configuration_data_param import S3ConfigurationDataParam +from .gcs_configuration_data_param import GcsConfigurationDataParam +from .azure_configuration_data_param import AzureConfigurationDataParam +from .s3_generic_configuration_data_param import S3GenericConfigurationDataParam diff --git a/src/telnyx/types/custom_storage_credential_update_params.py b/src/telnyx/types/custom_storage_credential_update_params.py index 024ecad8d..36111c2f0 100644 --- a/src/telnyx/types/custom_storage_credential_update_params.py +++ b/src/telnyx/types/custom_storage_credential_update_params.py @@ -5,11 +5,6 @@ from typing import Union from typing_extensions import Literal, Required, TypeAlias, TypedDict -from .s3_configuration_data_param import S3ConfigurationDataParam -from .gcs_configuration_data_param import GcsConfigurationDataParam -from .azure_configuration_data_param import AzureConfigurationDataParam -from .s3_generic_configuration_data_param import S3GenericConfigurationDataParam - __all__ = ["CustomStorageCredentialUpdateParams", "Configuration"] @@ -20,5 +15,13 @@ class CustomStorageCredentialUpdateParams(TypedDict, total=False): Configuration: TypeAlias = Union[ - GcsConfigurationDataParam, S3ConfigurationDataParam, S3GenericConfigurationDataParam, AzureConfigurationDataParam + "GcsConfigurationDataParam", + "S3ConfigurationDataParam", + "S3GenericConfigurationDataParam", + "AzureConfigurationDataParam", ] + +from .s3_configuration_data_param import S3ConfigurationDataParam +from .gcs_configuration_data_param import GcsConfigurationDataParam +from .azure_configuration_data_param import AzureConfigurationDataParam +from .s3_generic_configuration_data_param import S3GenericConfigurationDataParam diff --git a/src/telnyx/types/dir/comment_list_params.py b/src/telnyx/types/dir/comment_list_params.py index 42c1c7ec4..e4e735739 100644 --- a/src/telnyx/types/dir/comment_list_params.py +++ b/src/telnyx/types/dir/comment_list_params.py @@ -5,13 +5,12 @@ from typing_extensions import Annotated, TypedDict from ..._utils import PropertyInfo -from .comment_type import CommentType __all__ = ["CommentListParams"] class CommentListParams(TypedDict, total=False): - comment_type: CommentType + comment_type: "CommentType" """Restrict to comments of this category. Customer-visible categories only: internal-only comments are filtered out @@ -26,3 +25,6 @@ class CommentListParams(TypedDict, total=False): page_size: Annotated[int, PropertyInfo(alias="page[size]")] """Items per page. Maximum 250; values above are clamped to 250.""" + + +from .comment_type import CommentType diff --git a/src/telnyx/types/dir/dir.py b/src/telnyx/types/dir/dir.py index 68670e198..39b2288d6 100644 --- a/src/telnyx/types/dir/dir.py +++ b/src/telnyx/types/dir/dir.py @@ -36,6 +36,12 @@ class Dir(BaseModel): created_at: Optional[datetime] = None + delete_requested_at: Optional[datetime] = None + """When deletion was requested. + + Set once the DIR enters `delete_requested`; `null` otherwise. + """ + display_name: Optional[str] = None documents: Optional[List[Document]] = None @@ -71,6 +77,10 @@ class Dir(BaseModel): - `infringement_claimed` - a trademark/impersonation claim is open against this DIR. - `permanently_rejected` - terminal; cannot be resubmitted. + - `delete_requested` - you have requested deletion; the DIR still exists and + Telnyx is completing the removal (de-registration and cleanup). A verified DIR + keeps serving its branded identity, and keeps billing, until the removal + finishes. """ submitted_at: Optional[datetime] = None @@ -78,3 +88,9 @@ class Dir(BaseModel): updated_at: Optional[datetime] = None verified_at: Optional[datetime] = None + + webhook_url: Optional[str] = None + """ + `https://` URL that receives webhook notifications for this DIR's + compliance-review outcomes. `null` when not subscribed. + """ diff --git a/src/telnyx/types/dir/phone_number_batch_list_params.py b/src/telnyx/types/dir/phone_number_batch_list_params.py index e46c68070..b7c567175 100644 --- a/src/telnyx/types/dir/phone_number_batch_list_params.py +++ b/src/telnyx/types/dir/phone_number_batch_list_params.py @@ -5,13 +5,12 @@ from typing_extensions import Annotated, TypedDict from ..._utils import PropertyInfo -from .dir_phone_number_status import DirPhoneNumberStatus __all__ = ["PhoneNumberBatchListParams"] class PhoneNumberBatchListParams(TypedDict, total=False): - filter_status: Annotated[DirPhoneNumberStatus, PropertyInfo(alias="filter[status]")] + filter_status: Annotated["DirPhoneNumberStatus", PropertyInfo(alias="filter[status]")] """Restrict to batches whose aggregate status equals this value.""" page_number: Annotated[int, PropertyInfo(alias="page[number]")] @@ -22,3 +21,6 @@ class PhoneNumberBatchListParams(TypedDict, total=False): page_size: Annotated[int, PropertyInfo(alias="page[size]")] """Items per page. Maximum 250; values above are clamped to 250.""" + + +from .dir_phone_number_status import DirPhoneNumberStatus diff --git a/src/telnyx/types/dir/phone_number_list_params.py b/src/telnyx/types/dir/phone_number_list_params.py index bf466ca94..c26abf302 100644 --- a/src/telnyx/types/dir/phone_number_list_params.py +++ b/src/telnyx/types/dir/phone_number_list_params.py @@ -5,7 +5,6 @@ from typing_extensions import Annotated, TypedDict from ..._utils import PropertyInfo -from .dir_phone_number_status import DirPhoneNumberStatus __all__ = ["PhoneNumberListParams"] @@ -20,5 +19,8 @@ class PhoneNumberListParams(TypedDict, total=False): page_size: Annotated[int, PropertyInfo(alias="page[size]")] """Items per page. Maximum 250; values above are clamped to 250.""" - status: DirPhoneNumberStatus + status: "DirPhoneNumberStatus" """Filter by phone-number status.""" + + +from .dir_phone_number_status import DirPhoneNumberStatus diff --git a/src/telnyx/types/dir/phone_number_remove_params.py b/src/telnyx/types/dir/phone_number_remove_params.py index 1e695d958..9d67d3520 100644 --- a/src/telnyx/types/dir/phone_number_remove_params.py +++ b/src/telnyx/types/dir/phone_number_remove_params.py @@ -11,3 +11,7 @@ class PhoneNumberRemoveParams(TypedDict, total=False): phone_numbers: Required[SequenceNotStr[str]] + """ + The phone numbers to remove from this brand, in E.164 format, up to 100 per + request. They must currently be attached to this brand. + """ diff --git a/src/telnyx/types/dir/reference_create_params.py b/src/telnyx/types/dir/reference_create_params.py index e74f3c59d..7a5b40464 100644 --- a/src/telnyx/types/dir/reference_create_params.py +++ b/src/telnyx/types/dir/reference_create_params.py @@ -5,13 +5,11 @@ from typing import Iterable from typing_extensions import Required, TypedDict -from .reference_input_param import ReferenceInputParam - __all__ = ["ReferenceCreateParams"] class ReferenceCreateParams(TypedDict, total=False): - business_references: Required[Iterable[ReferenceInputParam]] + business_references: Required[Iterable["ReferenceInputParam"]] """Exactly two business references. Array order determines each one's slot: the first entry becomes slot 1 and the @@ -23,9 +21,12 @@ class ReferenceCreateParams(TypedDict, total=False): client. """ - financial_reference: Required[ReferenceInputParam] + financial_reference: Required["ReferenceInputParam"] """One reference supplied at submit. The reference type is implied by the field that carries it (business_references vs financial_reference). """ + + +from .reference_input_param import ReferenceInputParam diff --git a/src/telnyx/types/dir/reference_update_params.py b/src/telnyx/types/dir/reference_update_params.py index a24a9a51c..ac877f1bc 100644 --- a/src/telnyx/types/dir/reference_update_params.py +++ b/src/telnyx/types/dir/reference_update_params.py @@ -14,22 +14,32 @@ class ReferenceUpdateParams(TypedDict, total=False): ref_type: Required[Literal["business", "financial"]] email: str - """Reference contact email address.""" + """The reference's email address. + + We email them scheduling and dial-in instructions before we call, so use an + address they check. + """ full_name: str - """Full name of the reference contact.""" + """The full name of the person we should contact as your reference.""" job_title: Optional[str] - """Job title of the reference contact.""" + """The reference contact's job title, for example CFO or Owner.""" organization: Optional[str] - """Organization the reference contact belongs to.""" + """The name of the organization the reference contact works for.""" phone_e164: str - """Reference phone number in E.164 format.""" + """The reference's phone number in E.164 format, for example +14155550123. + + We call this number during their local business hours. + """ relationship_to_registrant: Optional[str] """How the reference contact is related to the registering business.""" timezone: str - """IANA timezone id for the reference.""" + """The reference's IANA time zone, for example America/New_York. + + We only call during their local 8am to 9pm hours, which is why we need it. + """ diff --git a/src/telnyx/types/dir_bpo_loa_params.py b/src/telnyx/types/dir_bpo_loa_params.py new file mode 100644 index 000000000..7a3ecf759 --- /dev/null +++ b/src/telnyx/types/dir_bpo_loa_params.py @@ -0,0 +1,27 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, TypedDict + +__all__ = ["DirBpoLoaParams"] + + +class DirBpoLoaParams(TypedDict, total=False): + bpo_enterprise_id: Required[str] + """The approved BPO enterprise the Brand Owner is authorizing. + + Must be a BPO account on the caller's organization that has already been + approved. + """ + + signature: "SignaturePayloadParam" + """Optional. + + When provided the rendered PDF embeds the signature image, printed name, and + signed-at date. When absent the PDF is returned unsigned so the Brand Owner can + sign externally and the BPO can upload it via the Documents API. + """ + + +from .signature_payload_param import SignaturePayloadParam diff --git a/src/telnyx/types/dir_delete_response.py b/src/telnyx/types/dir_delete_response.py new file mode 100644 index 000000000..79cc25f3c --- /dev/null +++ b/src/telnyx/types/dir_delete_response.py @@ -0,0 +1,23 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal + +from .._models import BaseModel + +__all__ = ["DirDeleteResponse", "Data"] + + +class Data(BaseModel): + id: str + """Id of the DIR whose deletion was requested.""" + + status: Literal["delete_requested"] + """ + Always `delete_requested`: the DIR has been queued for removal, not yet removed. + """ + + +class DirDeleteResponse(BaseModel): + data: Data diff --git a/src/telnyx/types/dir_list_params.py b/src/telnyx/types/dir_list_params.py index 84a6f037e..422792e35 100644 --- a/src/telnyx/types/dir_list_params.py +++ b/src/telnyx/types/dir_list_params.py @@ -7,7 +7,6 @@ from typing_extensions import Literal, Annotated, TypedDict from .._utils import PropertyInfo -from .dir_status import DirStatus __all__ = ["DirListParams"] @@ -35,7 +34,7 @@ class DirListParams(TypedDict, total=False): ] """Return only DIRs whose `expiring_at` is at or before this ISO-8601 timestamp.""" - filter_status: Annotated[DirStatus, PropertyInfo(alias="filter[status]")] + filter_status: Annotated["DirStatus", PropertyInfo(alias="filter[status]")] """Filter by DIR status.""" page_number: Annotated[int, PropertyInfo(alias="page[number]")] @@ -55,3 +54,6 @@ class DirListParams(TypedDict, total=False): Allowed values: `created_at`, `updated_at`, `display_name`, `status`. Prefix with `-` for descending. Default `-created_at`. """ + + +from .dir_status import DirStatus diff --git a/src/telnyx/types/dir_new_loa_params.py b/src/telnyx/types/dir_new_loa_params.py index eb968bef9..994166573 100644 --- a/src/telnyx/types/dir_new_loa_params.py +++ b/src/telnyx/types/dir_new_loa_params.py @@ -2,13 +2,11 @@ from __future__ import annotations -from typing import Optional from typing_extensions import Required, TypedDict from .._types import SequenceNotStr -from .enterprises.reputation.agent_input_param import AgentInputParam -__all__ = ["DirNewLoaParams", "Signature"] +__all__ = ["DirNewLoaParams"] class DirNewLoaParams(TypedDict, total=False): @@ -18,13 +16,13 @@ class DirNewLoaParams(TypedDict, total=False): 10-15 digits). Max 15 per request. """ - agent: AgentInputParam + agent: "AgentInputParam" """Third-party reseller / partner managing the enterprise's phone numbers. Omit when the enterprise works directly with Telnyx. """ - signature: Signature + signature: "SignaturePayloadParam" """Optional. When provided the rendered PDF embeds the signature image, printed name, and @@ -33,17 +31,5 @@ class DirNewLoaParams(TypedDict, total=False): """ -class Signature(TypedDict, total=False): - """Optional. - - When provided the rendered PDF embeds the signature image, printed name, and signed-at date. When absent the PDF is returned unsigned so the customer can sign externally and upload it via the Documents API. - """ - - image_base64: Required[str] - """PNG image, base64-encoded.""" - - signer_name: Optional[str] - """Optional. - - When absent the rendered PDF falls back to the enterprise contact's legal name. - """ +from .signature_payload_param import SignaturePayloadParam +from .enterprises.reputation.agent_input_param import AgentInputParam diff --git a/src/telnyx/types/dir_retrieve_bpo_authorizations_params.py b/src/telnyx/types/dir_retrieve_bpo_authorizations_params.py new file mode 100644 index 000000000..677023fcf --- /dev/null +++ b/src/telnyx/types/dir_retrieve_bpo_authorizations_params.py @@ -0,0 +1,20 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Annotated, TypedDict + +from .._utils import PropertyInfo + +__all__ = ["DirRetrieveBpoAuthorizationsParams"] + + +class DirRetrieveBpoAuthorizationsParams(TypedDict, total=False): + page_number: Annotated[int, PropertyInfo(alias="page[number]")] + """1-based page number. + + Out-of-range values return an empty page with correct meta. + """ + + page_size: Annotated[int, PropertyInfo(alias="page[size]")] + """Items per page. Maximum 250; values above are clamped to 250.""" diff --git a/src/telnyx/types/dir_retrieve_bpo_authorizations_response.py b/src/telnyx/types/dir_retrieve_bpo_authorizations_response.py new file mode 100644 index 000000000..3fa3b04ac --- /dev/null +++ b/src/telnyx/types/dir_retrieve_bpo_authorizations_response.py @@ -0,0 +1,53 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import List, Optional +from typing_extensions import Literal + +from .._models import BaseModel +from .branded_calling_pagination_meta import BrandedCallingPaginationMeta + +__all__ = ["DirRetrieveBpoAuthorizationsResponse", "Data"] + + +class Data(BaseModel): + """A single authorization of a BPO (Business Process Outsourcer) account on a DIR.""" + + bpo_enterprise_id: str + """The authorized BPO account's enterprise id.""" + + loa_document_id: str + """Id of the signed Letter of Authorization document submitted for this BPO. + + Send it back unchanged in `bpo_authorizations` when updating the DIR to keep + this authorization and its review state. + """ + + record_type: Literal["bpo_authorization"] + """Always `bpo_authorization`.""" + + status: Literal["pending", "approved", "rejected"] + """Review state of this authorization. + + `pending` on create or when the Letter of Authorization is re-uploaded; an admin + moves it to `approved` or `rejected`. Only an `approved` authorization adds the + BPO to this DIR's authorized callers in the branded calling registry. + """ + + rejection_reason: Optional[str] = None + """Why the authorization was rejected. `null` unless `status` is `rejected`.""" + + +class DirRetrieveBpoAuthorizationsResponse(BaseModel): + """Paginated list of a DIR's BPO authorizations.""" + + data: List[Data] + + meta: BrandedCallingPaginationMeta + """JSON:API pagination metadata returned with every paginated list response. + + Page numbering is 1-based. `page_size` reports the number of items actually + returned in `data` for this page; the requested size is taken from the + `page[size]` query parameter. + """ diff --git a/src/telnyx/types/dir_status.py b/src/telnyx/types/dir_status.py index 207a1bff6..81ade0467 100644 --- a/src/telnyx/types/dir_status.py +++ b/src/telnyx/types/dir_status.py @@ -17,4 +17,5 @@ "expired", "infringement_claimed", "permanently_rejected", + "delete_requested", ] diff --git a/src/telnyx/types/dir_update_infringement_params.py b/src/telnyx/types/dir_update_infringement_params.py index 6c1a3df15..d2722ba1c 100644 --- a/src/telnyx/types/dir_update_infringement_params.py +++ b/src/telnyx/types/dir_update_infringement_params.py @@ -6,7 +6,6 @@ from typing_extensions import Literal, Required, TypedDict from .._types import SequenceNotStr -from .document_param import DocumentParam __all__ = ["DirUpdateInfringementParams"] @@ -19,7 +18,10 @@ class DirUpdateInfringementParams(TypedDict, total=False): """Must be `true`.""" certify_no_infringement: Required[Literal[True]] - """Must be `true`.""" + """ + Check to certify that the brand no longer infringes anyone else's trademark or + intellectual property. + """ certify_no_shaft_content: Required[Literal[True]] """Must be `true`.""" @@ -30,8 +32,12 @@ class DirUpdateInfringementParams(TypedDict, total=False): call_reasons: Optional[SequenceNotStr[str]] display_name: Optional[str] + """ + The business name shown to call recipients, 1 to 35 characters, no emoji, not + blank. + """ - documents: Optional[Iterable[DocumentParam]] + documents: Optional[Iterable["DocumentParam"]] """Append-only supporting documents to attach while resolving the claim (e.g. authorization or licensing proof). @@ -39,3 +45,6 @@ class DirUpdateInfringementParams(TypedDict, total=False): logo_url: Optional[str] """Publicly accessible HTTPS URL (max 128 chars) to a 256x256 BMP logo (max 1 MB).""" + + +from .document_param import DocumentParam diff --git a/src/telnyx/types/dir_update_params.py b/src/telnyx/types/dir_update_params.py index ba7fae78e..f0109fc99 100644 --- a/src/telnyx/types/dir_update_params.py +++ b/src/telnyx/types/dir_update_params.py @@ -2,11 +2,10 @@ from __future__ import annotations -from typing import Iterable +from typing import Iterable, Optional from typing_extensions import TypedDict from .._types import SequenceNotStr -from .document_param import DocumentParam __all__ = ["DirUpdateParams"] @@ -24,6 +23,17 @@ class DirUpdateParams(TypedDict, total=False): Must be a real individual. """ + bpo_authorizations: Iterable["BpoAuthorizationInputParam"] + """Optional. + + Replace this DIR's authorized BPO (Business Process Outsourcer) accounts with + these, each with its signed Letter of Authorization. The supplied list replaces + the current one: a BPO left out has its authorization removed, and a new BPO (or + a changed Letter of Authorization) is created `pending` admin review. Send an + empty list to clear all authorizations; omit the field to leave them unchanged. + Editing this list does not re-vet the DIR. Maximum 10. + """ + call_reasons: SequenceNotStr[str] """1–10 reasons your business calls customers. @@ -52,7 +62,7 @@ class DirUpdateParams(TypedDict, total=False): display_name: str """Name shown to call recipients. 1–35 characters, no emoji, not whitespace-only.""" - documents: Iterable[DocumentParam] + documents: Iterable["DocumentParam"] """Additional supporting documents to attach. Append-only: existing documents are never removed or replaced, and an empty or @@ -67,3 +77,14 @@ class DirUpdateParams(TypedDict, total=False): Set to true if your organization places calls on behalf of other enterprises (BPO/reseller). Updating this triggers re-vetting on next submit. """ + + webhook_url: Optional[str] + """ + Optional `https://` URL that receives webhook notifications when this DIR's + compliance review completes. Send `null` to clear. Changing only this field on a + `verified` DIR does not re-vet it. Maximum 2048 characters. + """ + + +from .document_param import DocumentParam +from .bpo_authorization_input_param import BpoAuthorizationInputParam diff --git a/src/telnyx/types/doc_reqs_requirement.py b/src/telnyx/types/doc_reqs_requirement.py index 41e95f6ee..f07ec4161 100644 --- a/src/telnyx/types/doc_reqs_requirement.py +++ b/src/telnyx/types/doc_reqs_requirement.py @@ -42,7 +42,9 @@ class DocReqsRequirement(BaseModel): locality: Optional[str] = None """The locality where this requirement applies""" - phone_number_type: Optional[Literal["local", "national", "toll_free"]] = None + phone_number_type: Optional[Literal["local", "mobile", "multipurpose", "national", "shared_cost", "toll_free"]] = ( + None + ) """Indicates the phone_number_type this requirement applies to. Leave blank if this requirement applies to all number_types. diff --git a/src/telnyx/types/document.py b/src/telnyx/types/document.py index 2076b3696..de2b4128e 100644 --- a/src/telnyx/types/document.py +++ b/src/telnyx/types/document.py @@ -40,3 +40,4 @@ class Document(BaseModel): """ description: Optional[str] = None + """An optional note describing this document, for example what it proves.""" diff --git a/src/telnyx/types/document_param.py b/src/telnyx/types/document_param.py index 8d38fcf26..5ca48ce60 100644 --- a/src/telnyx/types/document_param.py +++ b/src/telnyx/types/document_param.py @@ -39,3 +39,4 @@ class DocumentParam(TypedDict, total=False): """ description: str + """An optional note describing this document, for example what it proves.""" diff --git a/src/telnyx/types/email_address_input_param.py b/src/telnyx/types/email_address_input_param.py index d6c61136a..35d14ea56 100644 --- a/src/telnyx/types/email_address_input_param.py +++ b/src/telnyx/types/email_address_input_param.py @@ -5,8 +5,8 @@ from typing import Union from typing_extensions import TypeAlias -from .email_inboxes.email_address_param import EmailAddressParam - __all__ = ["EmailAddressInputParam"] -EmailAddressInputParam: TypeAlias = Union[str, EmailAddressParam] +EmailAddressInputParam: TypeAlias = Union[str, "EmailAddressParam"] + +from .email_inboxes.email_address_param import EmailAddressParam diff --git a/src/telnyx/types/email_domain_create_params.py b/src/telnyx/types/email_domain_create_params.py index 7d1254d9f..f9cdce9f7 100644 --- a/src/telnyx/types/email_domain_create_params.py +++ b/src/telnyx/types/email_domain_create_params.py @@ -5,16 +5,13 @@ from typing import Optional from typing_extensions import Required, TypedDict -from .email_dmarc_policy_param import EmailDmarcPolicyParam -from .domains_tracking_settings_param import DomainsTrackingSettingsParam - __all__ = ["EmailDomainCreateParams"] class EmailDomainCreateParams(TypedDict, total=False): domain: Required[str] - dmarc_policy: Optional[EmailDmarcPolicyParam] + dmarc_policy: Optional["EmailDmarcPolicyParam"] """DMARC policy for a sending domain. Drives the recommended \\__dmarc. TXT record. DMARC is advisory and never @@ -25,4 +22,8 @@ class EmailDomainCreateParams(TypedDict, total=False): inbound_enabled: bool """Enable inbound routing for this domain""" - tracking: DomainsTrackingSettingsParam + tracking: "DomainsTrackingSettingsParam" + + +from .email_dmarc_policy_param import EmailDmarcPolicyParam +from .domains_tracking_settings_param import DomainsTrackingSettingsParam diff --git a/src/telnyx/types/email_domain_list_params.py b/src/telnyx/types/email_domain_list_params.py index 1601bda24..68a6a9d31 100644 --- a/src/telnyx/types/email_domain_list_params.py +++ b/src/telnyx/types/email_domain_list_params.py @@ -5,8 +5,6 @@ from typing_extensions import Literal, Annotated, TypedDict from .._utils import PropertyInfo -from .email_domain_type import EmailDomainType -from .email_domain_status import EmailDomainStatus __all__ = ["EmailDomainListParams"] @@ -18,13 +16,13 @@ class EmailDomainListParams(TypedDict, total=False): filter_profile_id: Annotated[str, PropertyInfo(alias="filter[profile_id]")] """Filter by profile UUID""" - filter_status: Annotated[EmailDomainStatus, PropertyInfo(alias="filter[status]")] + filter_status: Annotated["EmailDomainStatus", PropertyInfo(alias="filter[status]")] """ Filter domains by verification status: pending, verifying, verified, failed, degraded, or suspended. """ - filter_type: Annotated[EmailDomainType, PropertyInfo(alias="filter[type]")] + filter_type: Annotated["EmailDomainType", PropertyInfo(alias="filter[type]")] """Filter domains by type: custom, shared, or shared_inbound.""" filter_usable_for_inbound: Annotated[bool, PropertyInfo(alias="filter[usable_for_inbound]")] @@ -47,3 +45,7 @@ class EmailDomainListParams(TypedDict, total=False): sort: Literal["created_at", "-created_at", "domain", "-domain"] """Field to sort by. Prefix with `-` for descending order.""" + + +from .email_domain_type import EmailDomainType +from .email_domain_status import EmailDomainStatus diff --git a/src/telnyx/types/email_domain_update_params.py b/src/telnyx/types/email_domain_update_params.py index 3d53abf4c..18c86aa84 100644 --- a/src/telnyx/types/email_domain_update_params.py +++ b/src/telnyx/types/email_domain_update_params.py @@ -5,14 +5,11 @@ from typing import Optional from typing_extensions import TypedDict -from .email_dmarc_policy_param import EmailDmarcPolicyParam -from .domains_tracking_settings_param import DomainsTrackingSettingsParam - __all__ = ["EmailDomainUpdateParams"] class EmailDomainUpdateParams(TypedDict, total=False): - dmarc_policy: Optional[EmailDmarcPolicyParam] + dmarc_policy: Optional["EmailDmarcPolicyParam"] """DMARC policy for a sending domain. Drives the recommended \\__dmarc. TXT record. DMARC is advisory and never @@ -23,4 +20,8 @@ class EmailDomainUpdateParams(TypedDict, total=False): inbound_enabled: bool """Enable or disable inbound routing for this domain""" - tracking: DomainsTrackingSettingsParam + tracking: "DomainsTrackingSettingsParam" + + +from .email_dmarc_policy_param import EmailDmarcPolicyParam +from .domains_tracking_settings_param import DomainsTrackingSettingsParam diff --git a/src/telnyx/types/email_domains/webhook_create_params.py b/src/telnyx/types/email_domains/webhook_create_params.py index 97af15920..2d9e57cc5 100644 --- a/src/telnyx/types/email_domains/webhook_create_params.py +++ b/src/telnyx/types/email_domains/webhook_create_params.py @@ -5,14 +5,15 @@ from typing import List from typing_extensions import Required, TypedDict -from .email_webhook_event import EmailWebhookEvent - __all__ = ["WebhookCreateParams"] class WebhookCreateParams(TypedDict, total=False): - events: Required[List[EmailWebhookEvent]] + events: Required[List["EmailWebhookEvent"]] """At least one event type is required.""" url: Required[str] """HTTPS endpoint to deliver subscribed events to.""" + + +from .email_webhook_event import EmailWebhookEvent diff --git a/src/telnyx/types/email_domains/webhook_update_params.py b/src/telnyx/types/email_domains/webhook_update_params.py index c13ca0fd5..81d5cee7f 100644 --- a/src/telnyx/types/email_domains/webhook_update_params.py +++ b/src/telnyx/types/email_domains/webhook_update_params.py @@ -5,14 +5,15 @@ from typing import List from typing_extensions import Required, TypedDict -from .email_webhook_event import EmailWebhookEvent - __all__ = ["WebhookUpdateParams"] class WebhookUpdateParams(TypedDict, total=False): domain_id: Required[str] - events: List[EmailWebhookEvent] + events: List["EmailWebhookEvent"] url: str + + +from .email_webhook_event import EmailWebhookEvent diff --git a/src/telnyx/types/email_inboxes/messages/action_forward_params.py b/src/telnyx/types/email_inboxes/messages/action_forward_params.py index b7ca35425..85f6c7719 100644 --- a/src/telnyx/types/email_inboxes/messages/action_forward_params.py +++ b/src/telnyx/types/email_inboxes/messages/action_forward_params.py @@ -6,8 +6,6 @@ from typing_extensions import Required, TypeAlias, TypedDict from ...._types import SequenceNotStr -from .inbox_action_recipient_input_param import InboxActionRecipientInputParam -from .inbox_action_email_address_input_param import InboxActionEmailAddressInputParam __all__ = ["ActionForwardParams", "To", "ToInboxRecipientAddress"] @@ -22,14 +20,14 @@ class ActionForwardParams(TypedDict, total=False): `name`. """ - bcc: InboxActionRecipientInputParam + bcc: "InboxActionRecipientInputParam" """One recipient or a recipient array. Each recipient may be an email string or an object with `email` and optional `name`. """ - cc: InboxActionRecipientInputParam + cc: "InboxActionRecipientInputParam" """One recipient or a recipient array. Each recipient may be an email string or an object with `email` and optional @@ -55,4 +53,7 @@ class ToInboxRecipientAddress(TypedDict, total=False): name: str -To: TypeAlias = Union[str, ToInboxRecipientAddress, SequenceNotStr[InboxActionEmailAddressInputParam]] +To: TypeAlias = Union[str, ToInboxRecipientAddress, SequenceNotStr["InboxActionEmailAddressInputParam"]] + +from .inbox_action_recipient_input_param import InboxActionRecipientInputParam +from .inbox_action_email_address_input_param import InboxActionEmailAddressInputParam diff --git a/src/telnyx/types/email_inboxes/messages/inbox_action_recipient_input_param.py b/src/telnyx/types/email_inboxes/messages/inbox_action_recipient_input_param.py index a633a7a4d..c15e7f2c7 100644 --- a/src/telnyx/types/email_inboxes/messages/inbox_action_recipient_input_param.py +++ b/src/telnyx/types/email_inboxes/messages/inbox_action_recipient_input_param.py @@ -6,7 +6,6 @@ from typing_extensions import Required, TypeAlias, TypedDict from ...._types import SequenceNotStr -from .inbox_action_email_address_input_param import InboxActionEmailAddressInputParam __all__ = ["InboxActionRecipientInputParam", "InboxRecipientAddress"] @@ -18,5 +17,7 @@ class InboxRecipientAddress(TypedDict, total=False): InboxActionRecipientInputParam: TypeAlias = Union[ - str, InboxRecipientAddress, SequenceNotStr[InboxActionEmailAddressInputParam] + str, InboxRecipientAddress, SequenceNotStr["InboxActionEmailAddressInputParam"] ] + +from .inbox_action_email_address_input_param import InboxActionEmailAddressInputParam diff --git a/src/telnyx/types/email_message_batch_params.py b/src/telnyx/types/email_message_batch_params.py index eab88ef69..53950fd37 100644 --- a/src/telnyx/types/email_message_batch_params.py +++ b/src/telnyx/types/email_message_batch_params.py @@ -8,9 +8,6 @@ from .._types import SequenceNotStr from .._utils import PropertyInfo -from .tracking_settings_param import TrackingSettingsParam -from .attachment_request_param import AttachmentRequestParam -from .email_address_input_param import EmailAddressInputParam __all__ = ["EmailMessageBatchParams", "Message"] @@ -40,7 +37,7 @@ class EmailMessageBatchParams(TypedDict, total=False): _MessageReservedKeywords = TypedDict( "_MessageReservedKeywords", { - "from": EmailAddressInputParam, + "from": "EmailAddressInputParam", }, total=False, ) @@ -58,13 +55,13 @@ class Message(_MessageReservedKeywords, total=False): case-insensitive normalization. Duplicate recipients return `400`. """ - to: Required[SequenceNotStr[EmailAddressInputParam]] + to: Required[SequenceNotStr["EmailAddressInputParam"]] - attachments: Iterable[AttachmentRequestParam] + attachments: Iterable["AttachmentRequestParam"] - bcc: SequenceNotStr[EmailAddressInputParam] + bcc: SequenceNotStr["EmailAddressInputParam"] - cc: SequenceNotStr[EmailAddressInputParam] + cc: SequenceNotStr["EmailAddressInputParam"] from_name: str """Optional display name for string `from`; overrides `from.name` when provided.""" @@ -101,7 +98,7 @@ class Message(_MessageReservedKeywords, total=False): Detail Records. Usable in `filter[metadata]` when listing messages. """ - reply_to: EmailAddressInputParam + reply_to: "EmailAddressInputParam" """Reply-to address. If provided as an object with a name, only the email is stored; the name is @@ -164,8 +161,13 @@ class Message(_MessageReservedKeywords, total=False): responses. """ - tracking_settings: TrackingSettingsParam + tracking_settings: "TrackingSettingsParam" """Per-send open and click tracking overrides. Omitted properties inherit the sender domain's tracking settings. """ + + +from .tracking_settings_param import TrackingSettingsParam +from .attachment_request_param import AttachmentRequestParam +from .email_address_input_param import EmailAddressInputParam diff --git a/src/telnyx/types/email_message_create_params.py b/src/telnyx/types/email_message_create_params.py index 1b3db1ef3..05cb4ff35 100644 --- a/src/telnyx/types/email_message_create_params.py +++ b/src/telnyx/types/email_message_create_params.py @@ -8,23 +8,20 @@ from .._types import SequenceNotStr from .._utils import PropertyInfo -from .tracking_settings_param import TrackingSettingsParam -from .attachment_request_param import AttachmentRequestParam -from .email_address_input_param import EmailAddressInputParam __all__ = ["EmailMessageCreateParams"] class EmailMessageCreateParams(TypedDict, total=False): - from_: Required[Annotated[EmailAddressInputParam, PropertyInfo(alias="from")]] + from_: Required[Annotated["EmailAddressInputParam", PropertyInfo(alias="from")]] - to: Required[SequenceNotStr[EmailAddressInputParam]] + to: Required[SequenceNotStr["EmailAddressInputParam"]] - attachments: Iterable[AttachmentRequestParam] + attachments: Iterable["AttachmentRequestParam"] - bcc: SequenceNotStr[EmailAddressInputParam] + bcc: SequenceNotStr["EmailAddressInputParam"] - cc: SequenceNotStr[EmailAddressInputParam] + cc: SequenceNotStr["EmailAddressInputParam"] forward_of_message_id: Optional[str] """Telnyx message UUID of the message this send forwards. @@ -88,7 +85,7 @@ class EmailMessageCreateParams(TypedDict, total=False): Detail Records. Usable in `filter[metadata]` when listing messages. """ - reply_to: EmailAddressInputParam + reply_to: "EmailAddressInputParam" """Reply-to address. If provided as an object with a name, only the email is stored; the name is @@ -183,10 +180,15 @@ class EmailMessageCreateParams(TypedDict, total=False): responses. """ - tracking_settings: TrackingSettingsParam + tracking_settings: "TrackingSettingsParam" """Per-send open and click tracking overrides. Omitted properties inherit the sender domain's tracking settings. """ idempotency_key: Annotated[str, PropertyInfo(alias="Idempotency-Key")] + + +from .tracking_settings_param import TrackingSettingsParam +from .attachment_request_param import AttachmentRequestParam +from .email_address_input_param import EmailAddressInputParam diff --git a/src/telnyx/types/enterprise_create_params.py b/src/telnyx/types/enterprise_create_params.py index 652619535..0e01272c9 100644 --- a/src/telnyx/types/enterprise_create_params.py +++ b/src/telnyx/types/enterprise_create_params.py @@ -5,22 +5,23 @@ from typing import Optional from typing_extensions import Literal, Required, TypedDict -from .billing_contact_param import BillingContactParam -from .physical_address_param import PhysicalAddressParam -from .organization_contact_param import OrganizationContactParam - __all__ = ["EnterpriseCreateParams"] class EnterpriseCreateParams(TypedDict, total=False): - billing_address: Required[PhysicalAddressParam] + billing_address: Required["PhysicalAddressParam"] - billing_contact: Required[BillingContactParam] + billing_contact: Required["BillingContactParam"] country_code: Required[str] """ISO 3166-1 alpha-2 country code. Currently `US` and `CA` are supported.""" doing_business_as: Required[str] + """ + The trade name your business operates under if it is different from your legal + name, also called a Doing Business As (DBA) name. Leave blank if you only use + your legal name. + """ fein: Required[str] """ @@ -74,12 +75,23 @@ class EnterpriseCreateParams(TypedDict, total=False): "hotel", ] ] - """Industry classification.""" + """The industry your business operates in. + + Choose the closest match from the list; if your value is not accepted, pick the + nearest category. + """ jurisdiction_of_incorporation: Required[str] + """ + The state, province, or country where your business was legally incorporated, + for example Delaware. + """ legal_name: Required[str] - """Legal name of the enterprise.""" + """ + Your business's full registered legal name, exactly as it appears on your + incorporation or tax documents, 3 to 64 characters. + """ number_of_employees: Required[Literal["1-10", "11-50", "51-200", "201-500", "501-2000", "2001-10000", "10001+"]] """Approximate headcount range. @@ -88,7 +100,7 @@ class EnterpriseCreateParams(TypedDict, total=False): count. """ - organization_contact: Required[OrganizationContactParam] + organization_contact: Required["OrganizationContactParam"] organization_legal_type: Required[Literal["corporation", "llc", "partnership", "nonprofit", "other"]] """Legal-entity form. Pick the form that matches your incorporation documents: @@ -102,7 +114,7 @@ class EnterpriseCreateParams(TypedDict, total=False): You may be asked for additional documents during vetting. """ - organization_physical_address: Required[PhysicalAddressParam] + organization_physical_address: Required["PhysicalAddressParam"] organization_type: Required[Literal["commercial", "government", "non_profit"]] """Organization category for vetting purposes: @@ -115,27 +127,58 @@ class EnterpriseCreateParams(TypedDict, total=False): """ website: Required[str] + """Your business's public website address, including https://. + + Leave blank if your business has no website. + """ corporate_registration_number: Optional[str] - """Optional corporate-registration / company-number identifier.""" + """ + The official number your company received when it was legally registered or + incorporated (for example from your state or national business registry). It is + on your certificate of incorporation. + """ customer_reference: str - """Optional free-form string the caller can attach for their own bookkeeping. + """Your own label for this account. - Telnyx does not interpret it. + Enter any reference that helps you find it in your records. Telnyx does not use + it during vetting. """ dun_bradstreet_number: Optional[str] - """Optional D-U-N-S Number.""" + """ + Your optional 9-digit D-U-N-S Number issued by Dun & Bradstreet, a unique + identifier for your business. Leave blank if you do not have one. + """ primary_business_domain_sic_code: Optional[str] - """Optional SIC code for the primary line of business.""" + """ + The 4-digit Standard Industrial Classification code for your main line of + business, which tells us what industry you operate in. Look it up in the SIC + code directory if you are unsure. + """ professional_license_number: Optional[str] - """Optional professional-license number for regulated industries.""" + """ + If your business operates under a professional license (for example legal, + medical, or financial services), enter the license number issued by the + licensing authority. Leave blank if it does not apply. + """ role_type: Literal["enterprise", "bpo"] """ - `enterprise` for an organization registering its own DIRs; `bpo` for a Business - Process Outsourcer placing calls on behalf of one or more enterprises. + `enterprise` for an organization registering its own DIRs (the default, and the + right choice when the calls display your own brand). `bpo` for a Business + Process Outsourcer: a call center that places calls on behalf of other + enterprises and displays their brand. A `bpo` enterprise describes the call + center itself and cannot own a DIR. Each client the call center calls for gets + its own `enterprise` in the same account, with the client's DIR under it; that + DIR is then linked to the `bpo` enterprise through `bpo_authorizations`. Fixed + at creation. """ + + +from .billing_contact_param import BillingContactParam +from .physical_address_param import PhysicalAddressParam +from .organization_contact_param import OrganizationContactParam diff --git a/src/telnyx/types/enterprise_list_params.py b/src/telnyx/types/enterprise_list_params.py index c3783bcef..47f7352df 100644 --- a/src/telnyx/types/enterprise_list_params.py +++ b/src/telnyx/types/enterprise_list_params.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing_extensions import Annotated, TypedDict +from typing_extensions import Literal, Annotated, TypedDict from .._utils import PropertyInfo @@ -13,6 +13,12 @@ class EnterpriseListParams(TypedDict, total=False): filter_legal_name_contains: Annotated[str, PropertyInfo(alias="filter[legal_name][contains]")] """Case-insensitive partial match on legal name.""" + filter_role_type: Annotated[Literal["enterprise", "bpo"], PropertyInfo(alias="filter[role_type]")] + """ + Only return enterprises of this type: `bpo` for call-center (BPO) enterprises, + `enterprise` for normal enterprises. Omit to return both. + """ + legal_name: str """Filter by legal name (partial match).""" diff --git a/src/telnyx/types/enterprise_public.py b/src/telnyx/types/enterprise_public.py index 78a483d79..25d8842b6 100644 --- a/src/telnyx/types/enterprise_public.py +++ b/src/telnyx/types/enterprise_public.py @@ -4,6 +4,7 @@ from typing import Optional from datetime import datetime +from typing_extensions import Literal from .._models import BaseModel from .billing_contact import BillingContact @@ -20,6 +21,20 @@ class EnterprisePublic(BaseModel): billing_contact: Optional[BillingContact] = None + bpo_verification_rejection_reason: Optional[str] = None + """ + Reason Telnyx rejected the BPO (Business Process Outsourcer) verification, when + `bpo_verification_status` is `rejected`; `null` otherwise. + """ + + bpo_verification_status: Optional[Literal["pending", "approved", "rejected"]] = None + """Whether Telnyx has approved this BPO (Business Process Outsourcer) account. + + Only set for accounts created with `role_type` `bpo`; `null` for normal + enterprises. A BPO enterprise must be `approved` before a DIR can be linked to + it through `bpo_authorizations`. + """ + branded_calling_enabled: Optional[bool] = None """ True once Branded Calling has been activated on this enterprise (see @@ -27,28 +42,66 @@ class EnterprisePublic(BaseModel): """ corporate_registration_number: Optional[str] = None - """Optional corporate-registration / company-number identifier.""" + """ + The official number your company received when it was legally registered or + incorporated (for example from your state or national business registry). It is + on your certificate of incorporation. + """ country_code: Optional[str] = None created_at: Optional[datetime] = None customer_reference: Optional[str] = None + """Your own label for this account. + + Enter any reference that helps you find it in your records. Telnyx does not use + it during vetting. + """ doing_business_as: Optional[str] = None + """ + The trade name your business operates under if it is different from your legal + name, also called a Doing Business As (DBA) name. Leave blank if you only use + your legal name. + """ dun_bradstreet_number: Optional[str] = None - """Optional D-U-N-S Number issued by Dun & Bradstreet.""" + """ + Your optional 9-digit D-U-N-S Number issued by Dun & Bradstreet, a unique + identifier for your business. Leave blank if you do not have one. + """ fein: Optional[str] = None + """ + US Federal Employer Identification Number (`NN-NNNNNNN`) or Canadian equivalent. + """ industry: Optional[str] = None + """The industry your business operates in. + + Choose the closest match from the list; if your value is not accepted, pick the + nearest category. + """ jurisdiction_of_incorporation: Optional[str] = None + """ + The state, province, or country where your business was legally incorporated, + for example Delaware. + """ legal_name: Optional[str] = None + """ + Your business's full registered legal name, exactly as it appears on your + incorporation or tax documents, 3 to 64 characters. + """ number_of_employees: Optional[str] = None + """Approximate headcount range. + + Used for vetting heuristics; pick the bucket that contains your current employee + count. + """ number_reputation_enabled: Optional[bool] = None """ @@ -59,19 +112,41 @@ class EnterprisePublic(BaseModel): organization_contact: Optional[OrganizationContact] = None organization_legal_type: Optional[str] = None + """Legal-entity form. Pick the form that matches your incorporation documents: + + - `corporation` - C-corp or S-corp. + - `llc` - limited liability company. + - `partnership` - general/limited partnership. + - `nonprofit` - non-profit corporation, charitable trust, or + 501(c)(3)/equivalent. + - `other` - anything else (sole proprietorships, government bodies, DBAs, etc.). + You may be asked for additional documents during vetting. + """ organization_physical_address: Optional[PhysicalAddress] = None organization_type: Optional[str] = None primary_business_domain_sic_code: Optional[str] = None - """Optional SIC code for the primary line of business.""" + """ + The 4-digit Standard Industrial Classification code for your main line of + business, which tells us what industry you operate in. Look it up in the SIC + code directory if you are unsure. + """ professional_license_number: Optional[str] = None - """Optional professional-license number for regulated industries.""" + """ + If your business operates under a professional license (for example legal, + medical, or financial services), enter the license number issued by the + licensing authority. Leave blank if it does not apply. + """ - role_type: Optional[str] = None + role_type: Optional[Literal["enterprise", "bpo"]] = None updated_at: Optional[datetime] = None website: Optional[str] = None + """Your business's public website address, including https://. + + Leave blank if your business has no website. + """ diff --git a/src/telnyx/types/enterprise_update_params.py b/src/telnyx/types/enterprise_update_params.py index 26f5d95f5..820b3e260 100644 --- a/src/telnyx/types/enterprise_update_params.py +++ b/src/telnyx/types/enterprise_update_params.py @@ -5,27 +5,45 @@ from typing import Optional from typing_extensions import Literal, TypedDict -from .billing_contact_param import BillingContactParam -from .physical_address_param import PhysicalAddressParam -from .organization_contact_param import OrganizationContactParam - __all__ = ["EnterpriseUpdateParams"] class EnterpriseUpdateParams(TypedDict, total=False): - billing_address: PhysicalAddressParam + billing_address: "PhysicalAddressParam" - billing_contact: BillingContactParam + billing_contact: "BillingContactParam" corporate_registration_number: Optional[str] + """ + The official number your company received when it was legally registered or + incorporated (for example from your state or national business registry). It is + on your certificate of incorporation. + """ customer_reference: str + """Your own label for this account. + + Enter any reference that helps you find it in your records. Telnyx does not use + it during vetting. + """ doing_business_as: str + """ + The trade name your business operates under if it is different from your legal + name, also called a Doing Business As (DBA) name. Leave blank if you only use + your legal name. + """ dun_bradstreet_number: Optional[str] + """ + Your optional 9-digit D-U-N-S Number issued by Dun & Bradstreet, a unique + identifier for your business. Leave blank if you do not have one. + """ fein: str + """ + US Federal Employer Identification Number (`NN-NNNNNNN`) or Canadian equivalent. + """ industry: Literal[ "accounting", @@ -72,23 +90,68 @@ class EnterpriseUpdateParams(TypedDict, total=False): "hospitality", "hotel", ] + """The industry your business operates in. + + Choose the closest match from the list; if your value is not accepted, pick the + nearest category. + """ jurisdiction_of_incorporation: str - """Updated state/province/country of incorporation. Optional on update.""" + """ + The state, province, or country where your business was legally incorporated, + for example Delaware. + """ legal_name: str - """Legal name of the enterprise.""" + """ + Your business's full registered legal name, exactly as it appears on your + incorporation or tax documents, 3 to 64 characters. + """ number_of_employees: str + """Approximate headcount range. + + Used for vetting heuristics; pick the bucket that contains your current employee + count. + """ - organization_contact: OrganizationContactParam + organization_contact: "OrganizationContactParam" organization_legal_type: str + """Legal-entity form. Pick the form that matches your incorporation documents: - organization_physical_address: PhysicalAddressParam + - `corporation` - C-corp or S-corp. + - `llc` - limited liability company. + - `partnership` - general/limited partnership. + - `nonprofit` - non-profit corporation, charitable trust, or + 501(c)(3)/equivalent. + - `other` - anything else (sole proprietorships, government bodies, DBAs, etc.). + You may be asked for additional documents during vetting. + """ + + organization_physical_address: "PhysicalAddressParam" primary_business_domain_sic_code: Optional[str] + """ + The 4-digit Standard Industrial Classification code for your main line of + business, which tells us what industry you operate in. Look it up in the SIC + code directory if you are unsure. + """ professional_license_number: Optional[str] + """ + If your business operates under a professional license (for example legal, + medical, or financial services), enter the license number issued by the + licensing authority. Leave blank if it does not apply. + """ website: str + """Your business's public website address, including https://. + + Leave blank if your business has no website. + """ + + +from .billing_contact_param import BillingContactParam +from .physical_address_param import PhysicalAddressParam +from .organization_contact_param import OrganizationContactParam diff --git a/src/telnyx/types/enterprises/__init__.py b/src/telnyx/types/enterprises/__init__.py index 3bf133157..56e82c16c 100644 --- a/src/telnyx/types/enterprises/__init__.py +++ b/src/telnyx/types/enterprises/__init__.py @@ -8,6 +8,7 @@ from .dir_create_params import DirCreateParams as DirCreateParams from .reputation_enable_params import ReputationEnableParams as ReputationEnableParams from .reputation_check_frequency import ReputationCheckFrequency as ReputationCheckFrequency +from .verify_email_confirm_params import VerifyEmailConfirmParams as VerifyEmailConfirmParams from .reputation_update_frequency_params import ReputationUpdateFrequencyParams as ReputationUpdateFrequencyParams if TYPE_CHECKING: @@ -15,6 +16,9 @@ from .enterprise_reputation_public_wrapped import ( EnterpriseReputationPublicWrapped as EnterpriseReputationPublicWrapped, ) + from .enterprise_email_verification_status_wrapped import ( + EnterpriseEmailVerificationStatusWrapped as EnterpriseEmailVerificationStatusWrapped, + ) def __getattr__(name: str) -> Any: @@ -26,4 +30,8 @@ def __getattr__(name: str) -> Any: from .enterprise_reputation_public_wrapped import EnterpriseReputationPublicWrapped return EnterpriseReputationPublicWrapped + if name == "EnterpriseEmailVerificationStatusWrapped": + from .enterprise_email_verification_status_wrapped import EnterpriseEmailVerificationStatusWrapped + + return EnterpriseEmailVerificationStatusWrapped raise AttributeError(f"module {__name__!r} has no attribute {name!r}") diff --git a/src/telnyx/types/enterprises/dir_create_params.py b/src/telnyx/types/enterprises/dir_create_params.py index b14e3f73f..c63e6da32 100644 --- a/src/telnyx/types/enterprises/dir_create_params.py +++ b/src/telnyx/types/enterprises/dir_create_params.py @@ -2,11 +2,12 @@ from __future__ import annotations -from typing import Iterable +from typing import Iterable, Optional from typing_extensions import Literal, Required, TypedDict from ..._types import SequenceNotStr from ..document_param import DocumentParam +from ..bpo_authorization_input_param import BpoAuthorizationInputParam __all__ = ["DirCreateParams"] @@ -32,7 +33,10 @@ class DirCreateParams(TypedDict, total=False): """ certify_brand_is_accurate: Required[Literal[True]] - """Must be `true`.""" + """Certification that the DIR information is accurate. + + Must be `true` for the DIR to be submitted for vetting. + """ certify_ip_ownership: Required[Literal[True]] """Must be `true`. Confirms ownership of any logos/trademarks shown.""" @@ -47,6 +51,16 @@ class DirCreateParams(TypedDict, total=False): display_name: Required[str] """Name shown to call recipients. No emoji; not whitespace-only.""" + bpo_authorizations: Iterable[BpoAuthorizationInputParam] + """Optional. + + Approved BPO (Business Process Outsourcer) accounts on your organization + authorized to place branded calls for this DIR, each with the signed Letter of + Authorization the Brand Owner granted it. Each authorization starts `pending` + and takes effect only after an admin reviews its Letter of Authorization. Omit + or send an empty list to authorize no BPO on this DIR. Maximum 10. + """ + documents: Iterable[DocumentParam] """Supporting documents. Each `document_id` may appear at most once on a DIR.""" @@ -58,3 +72,10 @@ class DirCreateParams(TypedDict, total=False): Set to true if your organization places calls on behalf of other enterprises (BPO/reseller). """ + + webhook_url: Optional[str] + """ + Optional `https://` URL that receives webhook notifications when this DIR's + compliance review completes (rejection outcomes include structured rejection + reasons). Maximum 2048 characters. + """ diff --git a/src/telnyx/types/enterprises/enterprise_email_verification_status_wrapped.py b/src/telnyx/types/enterprises/enterprise_email_verification_status_wrapped.py new file mode 100644 index 000000000..75c57ea2d --- /dev/null +++ b/src/telnyx/types/enterprises/enterprise_email_verification_status_wrapped.py @@ -0,0 +1,41 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Optional +from datetime import datetime +from typing_extensions import Literal + +from ..._models import BaseModel + +__all__ = ["EnterpriseEmailVerificationStatusWrapped", "Data"] + + +class Data(BaseModel): + """Verification state for an enterprise account's contact email.""" + + email_verified: bool + """Whether the enterprise account's contact email has been confirmed.""" + + record_type: Literal["email_verification"] + """Always `email_verification`.""" + + status: Literal["sent", "verified"] + """`sent` after a code is emailed; `verified` after a successful confirm.""" + + expires_at: Optional[datetime] = None + """When the code just sent stops being accepted. + + Present on a send response; null on a confirm response. + """ + + sends_remaining_today: Optional[int] = None + """How many more codes may be requested for this enterprise account today. + + Present on a send response; null on a confirm response. + """ + + +class EnterpriseEmailVerificationStatusWrapped(BaseModel): + data: Data + """Verification state for an enterprise account's contact email.""" diff --git a/src/telnyx/types/enterprises/reputation/agent_input_param.py b/src/telnyx/types/enterprises/reputation/agent_input_param.py index 1ec225aa4..fef34456a 100644 --- a/src/telnyx/types/enterprises/reputation/agent_input_param.py +++ b/src/telnyx/types/enterprises/reputation/agent_input_param.py @@ -15,25 +15,56 @@ class AgentInputParam(TypedDict, total=False): """ administrative_area: Required[str] + """ + The state or province of the partner's address, as its code, for example IL or + ON. + """ city: Required[str] + """The city of the partner's address.""" contact_email: Required[str] + """The email address of the contact person at the partner.""" contact_name: Required[str] + """The name of a contact person at the partner.""" contact_phone: Required[str] + """ + The phone number of the contact person at the partner, in E.164 format, for + example +13125550000. + """ contact_title: Required[str] + """The job title of the contact person at the partner.""" country: Required[str] + """The two-letter country code of the partner's address, for example US.""" legal_name: Required[str] + """ + The legal name of the third-party partner or reseller managing these numbers on + your behalf. + """ postal_code: Required[str] + """The postal or ZIP code of the partner's address.""" street_address: Required[str] + """ + The street address of the partner, including the building number and street + name. + """ dba: Optional[str] + """ + The trade name (Doing Business As) the partner operates under, if different from + its legal name. Leave blank if it does not apply. + """ extended_address: Optional[str] + """An optional second address line for the partner, such as a suite, unit, or + floor. + + Leave blank if it does not apply. + """ diff --git a/src/telnyx/types/enterprises/reputation/loa_render_params.py b/src/telnyx/types/enterprises/reputation/loa_render_params.py index 54da3a572..f30109d7e 100644 --- a/src/telnyx/types/enterprises/reputation/loa_render_params.py +++ b/src/telnyx/types/enterprises/reputation/loa_render_params.py @@ -5,13 +5,11 @@ from typing import Optional from typing_extensions import Required, TypedDict -from .agent_input_param import AgentInputParam - -__all__ = ["LoaRenderParams", "Signature"] +__all__ = ["LoaRenderParams", "Agent", "Signature"] class LoaRenderParams(TypedDict, total=False): - agent: AgentInputParam + agent: Agent """Third-party reseller / partner managing the enterprise's phone numbers. Omit when the enterprise works directly with Telnyx. @@ -24,6 +22,37 @@ class LoaRenderParams(TypedDict, total=False): """ +class Agent(TypedDict, total=False): + """Third-party reseller / partner managing the enterprise's phone numbers. + + Omit when the enterprise works directly with Telnyx. + """ + + administrative_area: Required[str] + + city: Required[str] + + contact_email: Required[str] + + contact_name: Required[str] + + contact_phone: Required[str] + + contact_title: Required[str] + + country: Required[str] + + legal_name: Required[str] + + postal_code: Required[str] + + street_address: Required[str] + + dba: Optional[str] + + extended_address: Optional[str] + + class Signature(TypedDict, total=False): """Optional signature embedded in the rendered PDF. diff --git a/src/telnyx/types/enterprises/reputation/remediation_list_params.py b/src/telnyx/types/enterprises/reputation/remediation_list_params.py index 35e0b58d2..088f46c9d 100644 --- a/src/telnyx/types/enterprises/reputation/remediation_list_params.py +++ b/src/telnyx/types/enterprises/reputation/remediation_list_params.py @@ -7,7 +7,6 @@ from typing_extensions import Annotated, TypedDict from ...._utils import PropertyInfo -from .remediation_status import RemediationStatus __all__ = ["RemediationListParams"] @@ -23,7 +22,7 @@ class RemediationListParams(TypedDict, total=False): ] """Only requests created on or before this timestamp (ISO 8601).""" - filter_status: Annotated[RemediationStatus, PropertyInfo(alias="filter[status]")] + filter_status: Annotated["RemediationStatus", PropertyInfo(alias="filter[status]")] """Filter by customer-facing status.""" page_number: Annotated[int, PropertyInfo(alias="page[number]")] @@ -34,3 +33,6 @@ class RemediationListParams(TypedDict, total=False): page_size: Annotated[int, PropertyInfo(alias="page[size]")] """Items per page. Maximum 250; values above are clamped to 250.""" + + +from .remediation_status import RemediationStatus diff --git a/src/telnyx/types/enterprises/reputation_enable_params.py b/src/telnyx/types/enterprises/reputation_enable_params.py index d65d6eaa8..0e312d7ef 100644 --- a/src/telnyx/types/enterprises/reputation_enable_params.py +++ b/src/telnyx/types/enterprises/reputation_enable_params.py @@ -4,8 +4,6 @@ from typing_extensions import Required, TypedDict -from .reputation_check_frequency import ReputationCheckFrequency - __all__ = ["ReputationEnableParams"] @@ -17,8 +15,11 @@ class ReputationEnableParams(TypedDict, total=False): https://developers.telnyx.com/api/documents). """ - check_frequency: ReputationCheckFrequency + check_frequency: "ReputationCheckFrequency" """ How often Telnyx refreshes the stored reputation data for this enterprise's registered numbers. """ + + +from .reputation_check_frequency import ReputationCheckFrequency diff --git a/src/telnyx/types/enterprises/reputation_update_frequency_params.py b/src/telnyx/types/enterprises/reputation_update_frequency_params.py index 4bdc38722..087948d19 100644 --- a/src/telnyx/types/enterprises/reputation_update_frequency_params.py +++ b/src/telnyx/types/enterprises/reputation_update_frequency_params.py @@ -4,14 +4,15 @@ from typing_extensions import Required, TypedDict -from .reputation_check_frequency import ReputationCheckFrequency - __all__ = ["ReputationUpdateFrequencyParams"] class ReputationUpdateFrequencyParams(TypedDict, total=False): - check_frequency: Required[ReputationCheckFrequency] + check_frequency: Required["ReputationCheckFrequency"] """ How often Telnyx refreshes the stored reputation data for this enterprise's registered numbers. """ + + +from .reputation_check_frequency import ReputationCheckFrequency diff --git a/src/telnyx/types/enterprises/verify_email_confirm_params.py b/src/telnyx/types/enterprises/verify_email_confirm_params.py new file mode 100644 index 000000000..fb11ed796 --- /dev/null +++ b/src/telnyx/types/enterprises/verify_email_confirm_params.py @@ -0,0 +1,12 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, TypedDict + +__all__ = ["VerifyEmailConfirmParams"] + + +class VerifyEmailConfirmParams(TypedDict, total=False): + code: Required[str] + """The 6-digit code sent to the enterprise account's contact email.""" diff --git a/src/telnyx/types/fax_application_create_params.py b/src/telnyx/types/fax_application_create_params.py index 928f10e14..557f7150f 100644 --- a/src/telnyx/types/fax_application_create_params.py +++ b/src/telnyx/types/fax_application_create_params.py @@ -6,7 +6,6 @@ from typing_extensions import Literal, Required, TypedDict from .._types import SequenceNotStr -from .anchorsite_override import AnchorsiteOverride __all__ = ["FaxApplicationCreateParams", "Inbound", "Outbound"] @@ -24,7 +23,7 @@ class FaxApplicationCreateParams(TypedDict, total=False): active: bool """Specifies whether the connection can be used.""" - anchorsite_override: AnchorsiteOverride + anchorsite_override: "AnchorsiteOverride" """ `Latency` directs Telnyx to route media through the site with the lowest round-trip time to the user's connection. Telnyx calculates this time using ICMP @@ -82,3 +81,6 @@ class Outbound(TypedDict, total=False): outbound_voice_profile_id: str """Identifies the associated outbound voice profile.""" + + +from .anchorsite_override import AnchorsiteOverride diff --git a/src/telnyx/types/fax_application_update_params.py b/src/telnyx/types/fax_application_update_params.py index 5e8adee77..02bb717bc 100644 --- a/src/telnyx/types/fax_application_update_params.py +++ b/src/telnyx/types/fax_application_update_params.py @@ -6,7 +6,6 @@ from typing_extensions import Literal, Required, TypedDict from .._types import SequenceNotStr -from .anchorsite_override import AnchorsiteOverride __all__ = ["FaxApplicationUpdateParams", "Inbound", "Outbound"] @@ -24,7 +23,7 @@ class FaxApplicationUpdateParams(TypedDict, total=False): active: bool """Specifies whether the connection can be used.""" - anchorsite_override: AnchorsiteOverride + anchorsite_override: "AnchorsiteOverride" """ `Latency` directs Telnyx to route media through the site with the lowest round-trip time to the user's connection. Telnyx calculates this time using ICMP @@ -88,3 +87,6 @@ class Outbound(TypedDict, total=False): outbound_voice_profile_id: str """Identifies the associated outbound voice profile.""" + + +from .anchorsite_override import AnchorsiteOverride diff --git a/src/telnyx/types/fax_create_params.py b/src/telnyx/types/fax_create_params.py index 5b3a05b3e..dec8410b2 100644 --- a/src/telnyx/types/fax_create_params.py +++ b/src/telnyx/types/fax_create_params.py @@ -5,7 +5,6 @@ from typing_extensions import Literal, Required, Annotated, TypedDict from .._utils import PropertyInfo -from .quality import Quality __all__ = ["FaxCreateParams"] @@ -62,7 +61,7 @@ class FaxCreateParams(TypedDict, total=False): preview_format: Literal["pdf", "tiff"] """The format for the preview file in case the `store_preview` is `true`.""" - quality: Quality + quality: "Quality" """The quality of the fax. The `ultra` settings provides the highest quality available, but also present @@ -87,3 +86,6 @@ class FaxCreateParams(TypedDict, total=False): Use this field to override the URL to which Telnyx will send subsequent webhooks for this fax. """ + + +from .quality import Quality diff --git a/src/telnyx/types/fqdn_connection_create_params.py b/src/telnyx/types/fqdn_connection_create_params.py index 763b41781..80e6e4aee 100644 --- a/src/telnyx/types/fqdn_connection_create_params.py +++ b/src/telnyx/types/fqdn_connection_create_params.py @@ -6,17 +6,6 @@ from typing_extensions import Required, TypedDict from .._types import SequenceNotStr -from .dtmf_type import DtmfType -from .encrypted_media import EncryptedMedia -from .inbound_fqdn_param import InboundFqdnParam -from .transport_protocol import TransportProtocol -from .anchorsite_override import AnchorsiteOverride -from .outbound_fqdn_param import OutboundFqdnParam -from .webhook_api_version import WebhookAPIVersion -from .connection_noise_suppression import ConnectionNoiseSuppression -from .connection_rtcp_settings_param import ConnectionRtcpSettingsParam -from .shared_params.connection_jitter_buffer import ConnectionJitterBuffer -from .shared_params.connection_noise_suppression_details import ConnectionNoiseSuppressionDetails __all__ = ["FqdnConnectionCreateParams"] @@ -28,7 +17,7 @@ class FqdnConnectionCreateParams(TypedDict, total=False): active: bool """Defaults to true""" - anchorsite_override: AnchorsiteOverride + anchorsite_override: "AnchorsiteOverride" """ `Latency` directs Telnyx to route media through the site with the lowest round-trip time to the user's connection. Telnyx calculates this time using ICMP @@ -49,7 +38,7 @@ class FqdnConnectionCreateParams(TypedDict, total=False): RTP timeout. """ - dtmf_type: DtmfType + dtmf_type: "DtmfType" """Sets the type of DTMF digits sent from Telnyx to this Connection. Note that DTMF digits sent to Telnyx will be accepted in all formats. @@ -61,18 +50,18 @@ class FqdnConnectionCreateParams(TypedDict, total=False): scenarios. """ - encrypted_media: Optional[EncryptedMedia] + encrypted_media: Optional["EncryptedMedia"] """Enable use of SRTP for encryption. Cannot be set if the transport_portocol is TLS. """ - inbound: InboundFqdnParam + inbound: "InboundFqdnParam" ios_push_credential_id: Optional[str] """The uuid of the push credential for Ios""" - jitter_buffer: ConnectionJitterBuffer + jitter_buffer: "ConnectionJitterBuffer" """Configuration options for Jitter Buffer. Enables Jitter Buffer for RTP streams of SIP Trunking calls. The feature is off @@ -87,7 +76,7 @@ class FqdnConnectionCreateParams(TypedDict, total=False): A \\**.mstsbc.telnyx.tech FQDN will be created for the connection automatically. """ - noise_suppression: ConnectionNoiseSuppression + noise_suppression: "ConnectionNoiseSuppression" """Controls when noise suppression is applied to calls. When set to 'inbound', noise suppression is applied to incoming audio. When set @@ -95,7 +84,7 @@ class FqdnConnectionCreateParams(TypedDict, total=False): in both directions. When set to 'disabled', noise suppression is turned off. """ - noise_suppression_details: ConnectionNoiseSuppressionDetails + noise_suppression_details: "ConnectionNoiseSuppressionDetails" """Configuration options for noise suppression. These settings are stored regardless of the noise_suppression value, but only @@ -111,20 +100,20 @@ class FqdnConnectionCreateParams(TypedDict, total=False): use T38 on just one leg of the call depending on each leg's settings. """ - outbound: OutboundFqdnParam + outbound: "OutboundFqdnParam" - rtcp_settings: ConnectionRtcpSettingsParam + rtcp_settings: "ConnectionRtcpSettingsParam" tags: SequenceNotStr[str] """Tags associated with the connection.""" - transport_protocol: TransportProtocol + transport_protocol: "TransportProtocol" """One of UDP, TLS, or TCP. Applies only to connections with IP authentication or FQDN authentication. """ - webhook_api_version: WebhookAPIVersion + webhook_api_version: "WebhookAPIVersion" """Determines which webhook format will be used, Telnyx API v1 or v2.""" webhook_event_failover_url: Optional[str] @@ -141,3 +130,16 @@ class FqdnConnectionCreateParams(TypedDict, total=False): webhook_timeout_secs: Optional[int] """Specifies how many seconds to wait before timing out a webhook.""" + + +from .dtmf_type import DtmfType +from .encrypted_media import EncryptedMedia +from .inbound_fqdn_param import InboundFqdnParam +from .transport_protocol import TransportProtocol +from .anchorsite_override import AnchorsiteOverride +from .outbound_fqdn_param import OutboundFqdnParam +from .webhook_api_version import WebhookAPIVersion +from .connection_noise_suppression import ConnectionNoiseSuppression +from .connection_rtcp_settings_param import ConnectionRtcpSettingsParam +from .shared_params.connection_jitter_buffer import ConnectionJitterBuffer +from .shared_params.connection_noise_suppression_details import ConnectionNoiseSuppressionDetails diff --git a/src/telnyx/types/fqdn_connection_update_params.py b/src/telnyx/types/fqdn_connection_update_params.py index 416c9df39..4e3a0d30e 100644 --- a/src/telnyx/types/fqdn_connection_update_params.py +++ b/src/telnyx/types/fqdn_connection_update_params.py @@ -6,17 +6,6 @@ from typing_extensions import TypedDict from .._types import SequenceNotStr -from .dtmf_type import DtmfType -from .encrypted_media import EncryptedMedia -from .inbound_fqdn_param import InboundFqdnParam -from .transport_protocol import TransportProtocol -from .anchorsite_override import AnchorsiteOverride -from .outbound_fqdn_param import OutboundFqdnParam -from .webhook_api_version import WebhookAPIVersion -from .connection_noise_suppression import ConnectionNoiseSuppression -from .connection_rtcp_settings_param import ConnectionRtcpSettingsParam -from .shared_params.connection_jitter_buffer import ConnectionJitterBuffer -from .shared_params.connection_noise_suppression_details import ConnectionNoiseSuppressionDetails __all__ = ["FqdnConnectionUpdateParams"] @@ -25,7 +14,7 @@ class FqdnConnectionUpdateParams(TypedDict, total=False): active: bool """Defaults to true""" - anchorsite_override: AnchorsiteOverride + anchorsite_override: "AnchorsiteOverride" """ `Latency` directs Telnyx to route media through the site with the lowest round-trip time to the user's connection. Telnyx calculates this time using ICMP @@ -56,7 +45,7 @@ class FqdnConnectionUpdateParams(TypedDict, total=False): RTP timeout. """ - dtmf_type: DtmfType + dtmf_type: "DtmfType" """Sets the type of DTMF digits sent from Telnyx to this Connection. Note that DTMF digits sent to Telnyx will be accepted in all formats. @@ -68,18 +57,18 @@ class FqdnConnectionUpdateParams(TypedDict, total=False): scenarios. """ - encrypted_media: Optional[EncryptedMedia] + encrypted_media: Optional["EncryptedMedia"] """Enable use of SRTP for encryption. Cannot be set if the transport_portocol is TLS. """ - inbound: InboundFqdnParam + inbound: "InboundFqdnParam" ios_push_credential_id: Optional[str] """The uuid of the push credential for Ios""" - jitter_buffer: ConnectionJitterBuffer + jitter_buffer: "ConnectionJitterBuffer" """Configuration options for Jitter Buffer. Enables Jitter Buffer for RTP streams of SIP Trunking calls. The feature is off @@ -88,7 +77,7 @@ class FqdnConnectionUpdateParams(TypedDict, total=False): smaller values reduce latency but are more sensitive to jitter and reordering. """ - noise_suppression: ConnectionNoiseSuppression + noise_suppression: "ConnectionNoiseSuppression" """Controls when noise suppression is applied to calls. When set to 'inbound', noise suppression is applied to incoming audio. When set @@ -96,7 +85,7 @@ class FqdnConnectionUpdateParams(TypedDict, total=False): in both directions. When set to 'disabled', noise suppression is turned off. """ - noise_suppression_details: ConnectionNoiseSuppressionDetails + noise_suppression_details: "ConnectionNoiseSuppressionDetails" """Configuration options for noise suppression. These settings are stored regardless of the noise_suppression value, but only @@ -112,20 +101,20 @@ class FqdnConnectionUpdateParams(TypedDict, total=False): be able to use T38 on just one leg of the call according to each leg's settings. """ - outbound: OutboundFqdnParam + outbound: "OutboundFqdnParam" - rtcp_settings: ConnectionRtcpSettingsParam + rtcp_settings: "ConnectionRtcpSettingsParam" tags: SequenceNotStr[str] """Tags associated with the connection.""" - transport_protocol: TransportProtocol + transport_protocol: "TransportProtocol" """One of UDP, TLS, or TCP. Applies only to connections with IP authentication or FQDN authentication. """ - webhook_api_version: WebhookAPIVersion + webhook_api_version: "WebhookAPIVersion" """Determines which webhook format will be used, Telnyx API v1 or v2.""" webhook_event_failover_url: Optional[str] @@ -142,3 +131,16 @@ class FqdnConnectionUpdateParams(TypedDict, total=False): webhook_timeout_secs: Optional[int] """Specifies how many seconds to wait before timing out a webhook.""" + + +from .dtmf_type import DtmfType +from .encrypted_media import EncryptedMedia +from .inbound_fqdn_param import InboundFqdnParam +from .transport_protocol import TransportProtocol +from .anchorsite_override import AnchorsiteOverride +from .outbound_fqdn_param import OutboundFqdnParam +from .webhook_api_version import WebhookAPIVersion +from .connection_noise_suppression import ConnectionNoiseSuppression +from .connection_rtcp_settings_param import ConnectionRtcpSettingsParam +from .shared_params.connection_jitter_buffer import ConnectionJitterBuffer +from .shared_params.connection_noise_suppression_details import ConnectionNoiseSuppressionDetails diff --git a/src/telnyx/types/infringement_claim.py b/src/telnyx/types/infringement_claim.py index 3e73a1433..a1203fee3 100644 --- a/src/telnyx/types/infringement_claim.py +++ b/src/telnyx/types/infringement_claim.py @@ -50,6 +50,10 @@ class Dir(BaseModel): - `infringement_claimed` - a trademark/impersonation claim is open against this DIR. - `permanently_rejected` - terminal; cannot be resubmitted. + - `delete_requested` - you have requested deletion; the DIR still exists and + Telnyx is completing the removal (de-registration and cleanup). A verified DIR + keeps serving its branded identity, and keeps billing, until the removal + finishes. """ diff --git a/src/telnyx/types/infringement_claim_contest_params.py b/src/telnyx/types/infringement_claim_contest_params.py index 60951c7e0..23bd66414 100644 --- a/src/telnyx/types/infringement_claim_contest_params.py +++ b/src/telnyx/types/infringement_claim_contest_params.py @@ -5,8 +5,6 @@ from typing import Iterable from typing_extensions import Required, TypedDict -from .document_param import DocumentParam - __all__ = ["InfringementClaimContestParams"] @@ -14,9 +12,12 @@ class InfringementClaimContestParams(TypedDict, total=False): contest_notes: Required[str] """Customer's response to the claim. 10–2000 characters.""" - documents: Iterable[DocumentParam] + documents: Iterable["DocumentParam"] """Up to 20 supporting documents per submission. `document_id` must be unique within this submission. Documents are aggregated into the claim's `contest_documents` across all submissions. """ + + +from .document_param import DocumentParam diff --git a/src/telnyx/types/ip_connection_create_params.py b/src/telnyx/types/ip_connection_create_params.py index b26be6fac..cb04cbb53 100644 --- a/src/telnyx/types/ip_connection_create_params.py +++ b/src/telnyx/types/ip_connection_create_params.py @@ -6,14 +6,6 @@ from typing_extensions import Literal, TypedDict from .._types import SequenceNotStr -from .dtmf_type import DtmfType -from .encrypted_media import EncryptedMedia -from .outbound_ip_param import OutboundIPParam -from .anchorsite_override import AnchorsiteOverride -from .connection_noise_suppression import ConnectionNoiseSuppression -from .connection_rtcp_settings_param import ConnectionRtcpSettingsParam -from .shared_params.connection_jitter_buffer import ConnectionJitterBuffer -from .shared_params.connection_noise_suppression_details import ConnectionNoiseSuppressionDetails __all__ = ["IPConnectionCreateParams", "Inbound"] @@ -22,7 +14,7 @@ class IPConnectionCreateParams(TypedDict, total=False): active: bool """Defaults to true""" - anchorsite_override: AnchorsiteOverride + anchorsite_override: "AnchorsiteOverride" """ `Latency` directs Telnyx to route media through the site with the lowest round-trip time to the user's connection. Telnyx calculates this time using ICMP @@ -45,7 +37,7 @@ class IPConnectionCreateParams(TypedDict, total=False): RTP timeout. """ - dtmf_type: DtmfType + dtmf_type: "DtmfType" """Sets the type of DTMF digits sent from Telnyx to this Connection. Note that DTMF digits sent to Telnyx will be accepted in all formats. @@ -57,7 +49,7 @@ class IPConnectionCreateParams(TypedDict, total=False): scenarios. """ - encrypted_media: Optional[EncryptedMedia] + encrypted_media: Optional["EncryptedMedia"] """Enable use of SRTP for encryption. Cannot be set if the transport_portocol is TLS. @@ -68,7 +60,7 @@ class IPConnectionCreateParams(TypedDict, total=False): ios_push_credential_id: Optional[str] """The uuid of the push credential for Ios""" - jitter_buffer: ConnectionJitterBuffer + jitter_buffer: "ConnectionJitterBuffer" """Configuration options for Jitter Buffer. Enables Jitter Buffer for RTP streams of SIP Trunking calls. The feature is off @@ -77,7 +69,7 @@ class IPConnectionCreateParams(TypedDict, total=False): smaller values reduce latency but are more sensitive to jitter and reordering. """ - noise_suppression: ConnectionNoiseSuppression + noise_suppression: "ConnectionNoiseSuppression" """Controls when noise suppression is applied to calls. When set to 'inbound', noise suppression is applied to incoming audio. When set @@ -85,7 +77,7 @@ class IPConnectionCreateParams(TypedDict, total=False): in both directions. When set to 'disabled', noise suppression is turned off. """ - noise_suppression_details: ConnectionNoiseSuppressionDetails + noise_suppression_details: "ConnectionNoiseSuppressionDetails" """Configuration options for noise suppression. These settings are stored regardless of the noise_suppression value, but only @@ -101,9 +93,9 @@ class IPConnectionCreateParams(TypedDict, total=False): use T38 on just one leg of the call depending on each leg's settings. """ - outbound: OutboundIPParam + outbound: "OutboundIPParam" - rtcp_settings: ConnectionRtcpSettingsParam + rtcp_settings: "ConnectionRtcpSettingsParam" tags: SequenceNotStr[str] """Tags associated with the connection.""" @@ -213,3 +205,13 @@ class Inbound(TypedDict, total=False): timeout_2xx_secs: int """Time(sec) before aborting if call is unanswered (min: 1, max: 600).""" + + +from .dtmf_type import DtmfType +from .encrypted_media import EncryptedMedia +from .outbound_ip_param import OutboundIPParam +from .anchorsite_override import AnchorsiteOverride +from .connection_noise_suppression import ConnectionNoiseSuppression +from .connection_rtcp_settings_param import ConnectionRtcpSettingsParam +from .shared_params.connection_jitter_buffer import ConnectionJitterBuffer +from .shared_params.connection_noise_suppression_details import ConnectionNoiseSuppressionDetails diff --git a/src/telnyx/types/ip_connection_update_params.py b/src/telnyx/types/ip_connection_update_params.py index dc5fb00a8..baff1eb34 100644 --- a/src/telnyx/types/ip_connection_update_params.py +++ b/src/telnyx/types/ip_connection_update_params.py @@ -6,15 +6,6 @@ from typing_extensions import Literal, TypedDict from .._types import SequenceNotStr -from .dtmf_type import DtmfType -from .encrypted_media import EncryptedMedia -from .inbound_ip_param import InboundIPParam -from .outbound_ip_param import OutboundIPParam -from .anchorsite_override import AnchorsiteOverride -from .connection_noise_suppression import ConnectionNoiseSuppression -from .connection_rtcp_settings_param import ConnectionRtcpSettingsParam -from .shared_params.connection_jitter_buffer import ConnectionJitterBuffer -from .shared_params.connection_noise_suppression_details import ConnectionNoiseSuppressionDetails __all__ = ["IPConnectionUpdateParams"] @@ -23,7 +14,7 @@ class IPConnectionUpdateParams(TypedDict, total=False): active: bool """Defaults to true""" - anchorsite_override: AnchorsiteOverride + anchorsite_override: "AnchorsiteOverride" """ `Latency` directs Telnyx to route media through the site with the lowest round-trip time to the user's connection. Telnyx calculates this time using ICMP @@ -53,7 +44,7 @@ class IPConnectionUpdateParams(TypedDict, total=False): RTP timeout. """ - dtmf_type: DtmfType + dtmf_type: "DtmfType" """Sets the type of DTMF digits sent from Telnyx to this Connection. Note that DTMF digits sent to Telnyx will be accepted in all formats. @@ -65,18 +56,18 @@ class IPConnectionUpdateParams(TypedDict, total=False): scenarios. """ - encrypted_media: Optional[EncryptedMedia] + encrypted_media: Optional["EncryptedMedia"] """Enable use of SRTP for encryption. Cannot be set if the transport_portocol is TLS. """ - inbound: InboundIPParam + inbound: "InboundIPParam" ios_push_credential_id: Optional[str] """The uuid of the push credential for Ios""" - jitter_buffer: ConnectionJitterBuffer + jitter_buffer: "ConnectionJitterBuffer" """Configuration options for Jitter Buffer. Enables Jitter Buffer for RTP streams of SIP Trunking calls. The feature is off @@ -85,7 +76,7 @@ class IPConnectionUpdateParams(TypedDict, total=False): smaller values reduce latency but are more sensitive to jitter and reordering. """ - noise_suppression: ConnectionNoiseSuppression + noise_suppression: "ConnectionNoiseSuppression" """Controls when noise suppression is applied to calls. When set to 'inbound', noise suppression is applied to incoming audio. When set @@ -93,7 +84,7 @@ class IPConnectionUpdateParams(TypedDict, total=False): in both directions. When set to 'disabled', noise suppression is turned off. """ - noise_suppression_details: ConnectionNoiseSuppressionDetails + noise_suppression_details: "ConnectionNoiseSuppressionDetails" """Configuration options for noise suppression. These settings are stored regardless of the noise_suppression value, but only @@ -109,9 +100,9 @@ class IPConnectionUpdateParams(TypedDict, total=False): use T38 on just one leg of the call depending on each leg's settings. """ - outbound: OutboundIPParam + outbound: "OutboundIPParam" - rtcp_settings: ConnectionRtcpSettingsParam + rtcp_settings: "ConnectionRtcpSettingsParam" tags: SequenceNotStr[str] """Tags associated with the connection.""" @@ -139,3 +130,14 @@ class IPConnectionUpdateParams(TypedDict, total=False): webhook_timeout_secs: Optional[int] """Specifies how many seconds to wait before timing out a webhook.""" + + +from .dtmf_type import DtmfType +from .encrypted_media import EncryptedMedia +from .inbound_ip_param import InboundIPParam +from .outbound_ip_param import OutboundIPParam +from .anchorsite_override import AnchorsiteOverride +from .connection_noise_suppression import ConnectionNoiseSuppression +from .connection_rtcp_settings_param import ConnectionRtcpSettingsParam +from .shared_params.connection_jitter_buffer import ConnectionJitterBuffer +from .shared_params.connection_noise_suppression_details import ConnectionNoiseSuppressionDetails diff --git a/src/telnyx/types/llm_token_gateway/__init__.py b/src/telnyx/types/llm_token_gateway/__init__.py new file mode 100644 index 000000000..e3e426eb6 --- /dev/null +++ b/src/telnyx/types/llm_token_gateway/__init__.py @@ -0,0 +1,18 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import TYPE_CHECKING, Any + +from .usage_retrieve_summary_params import UsageRetrieveSummaryParams as UsageRetrieveSummaryParams + +if TYPE_CHECKING: + from .usage_retrieve_summary_response import UsageRetrieveSummaryResponse as UsageRetrieveSummaryResponse + + +def __getattr__(name: str) -> Any: + if name == "UsageRetrieveSummaryResponse": + from .usage_retrieve_summary_response import UsageRetrieveSummaryResponse + + return UsageRetrieveSummaryResponse + raise AttributeError(f"module {__name__!r} has no attribute {name!r}") diff --git a/src/telnyx/types/llm_token_gateway/usage_retrieve_summary_params.py b/src/telnyx/types/llm_token_gateway/usage_retrieve_summary_params.py new file mode 100644 index 000000000..db23f8d23 --- /dev/null +++ b/src/telnyx/types/llm_token_gateway/usage_retrieve_summary_params.py @@ -0,0 +1,25 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Union +from datetime import date +from typing_extensions import Required, Annotated, TypedDict + +from ..._utils import PropertyInfo + +__all__ = ["UsageRetrieveSummaryParams"] + + +class UsageRetrieveSummaryParams(TypedDict, total=False): + end_date: Required[Annotated[Union[str, date], PropertyInfo(format="iso8601")]] + """Exclusive UTC date in YYYY-MM-DD format. + + Must follow start_date by 1 to 31 days. + """ + + start_date: Required[Annotated[Union[str, date], PropertyInfo(format="iso8601")]] + """Inclusive UTC date in YYYY-MM-DD format. Must precede end_date by 1 to 31 days.""" + + token_group_id: Required[str] + """ID of a token group owned by the authenticated account.""" diff --git a/src/telnyx/types/llm_token_gateway/usage_retrieve_summary_response.py b/src/telnyx/types/llm_token_gateway/usage_retrieve_summary_response.py new file mode 100644 index 000000000..ff82133c7 --- /dev/null +++ b/src/telnyx/types/llm_token_gateway/usage_retrieve_summary_response.py @@ -0,0 +1,215 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import datetime +from typing import List, Optional +from typing_extensions import Literal + +from ..._models import BaseModel + +__all__ = [ + "UsageRetrieveSummaryResponse", + "Data", + "DataByDay", + "DataByModel", + "DataGuardrails", + "DataGuardrailsRecentEvent", + "DataGuardrailsRecentEventFinding", + "DataTotals", + "Meta", +] + + +class DataByDay(BaseModel): + cache_hits: int + """Requests served from the gateway cache.""" + + date: datetime.date + """UTC day.""" + + failed_requests: int + """Requests classified as failed.""" + + input_tokens: int + """Independently known input tokens across attempts, including corrected usage.""" + + output_tokens: int + """Independently known output tokens across attempts, including corrected usage.""" + + partial_requests: int + """Requests classified as partial after streaming began.""" + + requests: int + """Number of matching requests.""" + + reserved_spend: float + """Unresolved budget reservations in USD.""" + + spend: float + """Sum of known reference/enforcement cost in USD.""" + + succeeded_requests: int + """Requests classified as succeeded.""" + + unknown_requests: int + """Requests whose cost remains unresolved; unknown cost is excluded from spend.""" + + +class DataByModel(BaseModel): + cache_hits: int + """Requests served from the gateway cache.""" + + failed_requests: int + """Requests classified as failed.""" + + input_tokens: int + """Independently known input tokens across attempts, including corrected usage.""" + + model: str + """Model identifier.""" + + output_tokens: int + """Independently known output tokens across attempts, including corrected usage.""" + + partial_requests: int + """Requests classified as partial after streaming began.""" + + requests: int + """Number of matching requests.""" + + reserved_spend: float + """Unresolved budget reservations in USD.""" + + spend: float + """Sum of known reference/enforcement cost in USD.""" + + succeeded_requests: int + """Requests classified as succeeded.""" + + unknown_requests: int + """Requests whose cost remains unresolved; unknown cost is excluded from spend.""" + + +class DataGuardrailsRecentEventFinding(BaseModel): + action: Literal["flag", "block"] + + code: str + + count: int + + detector: Literal["secrets", "dlp", "safety"] + + +class DataGuardrailsRecentEvent(BaseModel): + id: str + + created_at: datetime.datetime + + end_user_id: Optional[str] = None + + evaluation_input_tokens: Optional[int] = None + + evaluation_output_tokens: Optional[int] = None + + findings: List[DataGuardrailsRecentEventFinding] + + model: str + """Model identifier.""" + + outcome: Literal["evaluated", "flagged", "blocked", "unevaluated"] + + record_type: Literal["guardrail_event"] + + request_id: str + + stage: Literal["prompt", "response"] + + token_group_id: str + + token_key_id: str + + token_user_id: Optional[str] = None + + +class DataGuardrails(BaseModel): + """ + Complete guardrail event counts and bounded recent findings for the same group and range. + """ + + blocked_events: int + """Total blocked guardrail events, not distinct requests.""" + + flagged_events: int + """Total flagged guardrail events, not distinct requests.""" + + recent_events: List[DataGuardrailsRecentEvent] + """ + Up to 20 newest privacy-safe guardrail events, ordered by creation time + descending and event ID. + """ + + +class DataTotals(BaseModel): + """Metrics for all matching requests.""" + + cache_hits: int + """Requests served from the gateway cache.""" + + failed_requests: int + """Requests classified as failed.""" + + input_tokens: int + """Independently known input tokens across attempts, including corrected usage.""" + + output_tokens: int + """Independently known output tokens across attempts, including corrected usage.""" + + partial_requests: int + """Requests classified as partial after streaming began.""" + + requests: int + """Number of matching requests.""" + + reserved_spend: float + """Unresolved budget reservations in USD.""" + + spend: float + """Sum of known reference/enforcement cost in USD.""" + + succeeded_requests: int + """Requests classified as succeeded.""" + + unknown_requests: int + """Requests whose cost remains unresolved; unknown cost is excluded from spend.""" + + +class Data(BaseModel): + by_day: List[DataByDay] + """One row per UTC day, including zero-activity days.""" + + by_model: List[DataByModel] + """One row per model, ordered by request count descending then model name.""" + + guardrails: DataGuardrails + """ + Complete guardrail event counts and bounded recent findings for the same group + and range. + """ + + totals: DataTotals + """Metrics for all matching requests.""" + + +class Meta(BaseModel): + end_date: datetime.date + + start_date: datetime.date + + token_group_id: str + + +class UsageRetrieveSummaryResponse(BaseModel): + data: Data + + meta: Meta diff --git a/src/telnyx/types/meeting_session_delete_recording_media_response.py b/src/telnyx/types/meeting_session_delete_recording_media_response.py index 225bf8057..fc16bee28 100644 --- a/src/telnyx/types/meeting_session_delete_recording_media_response.py +++ b/src/telnyx/types/meeting_session_delete_recording_media_response.py @@ -15,7 +15,7 @@ class Data(BaseModel): meeting_session_id: str """The account-scoped Meeting Session identifier.""" - provider: Literal["recall"] + provider: Literal["telnyx"] scope: Literal["provider_recording_media"] diff --git a/src/telnyx/types/meeting_session_retrieve_recordings_response.py b/src/telnyx/types/meeting_session_retrieve_recordings_response.py index e8e18120d..042066968 100644 --- a/src/telnyx/types/meeting_session_retrieve_recordings_response.py +++ b/src/telnyx/types/meeting_session_retrieve_recordings_response.py @@ -11,10 +11,7 @@ class Data(BaseModel): expires_at: Optional[str] = None - """Expiry timestamp when supplied by the provider, or null. - - The current adapter returns null. - """ + """Expiry timestamp when available, or null. Currently returns null.""" type: str diff --git a/src/telnyx/types/message_whatsapp_params.py b/src/telnyx/types/message_whatsapp_params.py index 5d85ffb35..22d7a379c 100644 --- a/src/telnyx/types/message_whatsapp_params.py +++ b/src/telnyx/types/message_whatsapp_params.py @@ -5,7 +5,6 @@ from typing_extensions import Literal, Required, Annotated, TypedDict from .._utils import PropertyInfo -from .whatsapp_message_content_param import WhatsappMessageContentParam __all__ = ["MessageWhatsappParams"] @@ -17,7 +16,7 @@ class MessageWhatsappParams(TypedDict, total=False): to: Required[str] """Phone number in +E.164 format""" - whatsapp_message: Required[WhatsappMessageContentParam] + whatsapp_message: Required["WhatsappMessageContentParam"] messaging_profile_id: str """Messaging profile ID - required if the 'from' number is not SMS-enabled""" @@ -27,3 +26,6 @@ class MessageWhatsappParams(TypedDict, total=False): webhook_url: str """The URL where webhooks related to this message will be sent.""" + + +from .whatsapp_message_content_param import WhatsappMessageContentParam diff --git a/src/telnyx/types/messaging_10dlc/brand_create_params.py b/src/telnyx/types/messaging_10dlc/brand_create_params.py index a8e97b72e..f06ccce9e 100644 --- a/src/telnyx/types/messaging_10dlc/brand_create_params.py +++ b/src/telnyx/types/messaging_10dlc/brand_create_params.py @@ -5,9 +5,6 @@ from typing_extensions import Required, Annotated, TypedDict from ..._utils import PropertyInfo -from .vertical import Vertical -from .entity_type import EntityType -from .stock_exchange import StockExchange __all__ = ["BrandCreateParams"] @@ -22,10 +19,10 @@ class BrandCreateParams(TypedDict, total=False): email: Required[str] """Valid email address of brand support contact.""" - entity_type: Required[Annotated[EntityType, PropertyInfo(alias="entityType")]] + entity_type: Required[Annotated["EntityType", PropertyInfo(alias="entityType")]] """Entity type behind the brand. This is the form of business establishment.""" - vertical: Required[Vertical] + vertical: Required["Vertical"] """Vertical or industry segment of the brand or campaign.""" business_contact_email: Annotated[str, PropertyInfo(alias="businessContactEmail")] @@ -73,7 +70,7 @@ class BrandCreateParams(TypedDict, total=False): state: str """State. Must be 2 letters code for United States.""" - stock_exchange: Annotated[StockExchange, PropertyInfo(alias="stockExchange")] + stock_exchange: Annotated["StockExchange", PropertyInfo(alias="stockExchange")] """(Required for public company) stock exchange.""" stock_symbol: Annotated[str, PropertyInfo(alias="stockSymbol")] @@ -90,3 +87,8 @@ class BrandCreateParams(TypedDict, total=False): website: str """Brand website URL.""" + + +from .vertical import Vertical +from .entity_type import EntityType +from .stock_exchange import StockExchange diff --git a/src/telnyx/types/messaging_10dlc/brand_update_params.py b/src/telnyx/types/messaging_10dlc/brand_update_params.py index a5405b297..2f2d51353 100644 --- a/src/telnyx/types/messaging_10dlc/brand_update_params.py +++ b/src/telnyx/types/messaging_10dlc/brand_update_params.py @@ -5,11 +5,6 @@ from typing_extensions import Required, Annotated, TypedDict from ..._utils import PropertyInfo -from .vertical import Vertical -from .entity_type import EntityType -from .stock_exchange import StockExchange -from .alt_business_id_type import AltBusinessIDType -from .brand_identity_status import BrandIdentityStatus __all__ = ["BrandUpdateParams"] @@ -24,16 +19,16 @@ class BrandUpdateParams(TypedDict, total=False): email: Required[str] """Valid email address of brand support contact.""" - entity_type: Required[Annotated[EntityType, PropertyInfo(alias="entityType")]] + entity_type: Required[Annotated["EntityType", PropertyInfo(alias="entityType")]] """Entity type behind the brand. This is the form of business establishment.""" - vertical: Required[Vertical] + vertical: Required["Vertical"] """Vertical or industry segment of the brand or campaign.""" alt_business_id: Annotated[str, PropertyInfo(alias="altBusinessId")] """Alternate business identifier such as DUNS, LEI, or GIIN""" - alt_business_id_type: Annotated[AltBusinessIDType, PropertyInfo(alias="altBusinessIdType")] + alt_business_id_type: Annotated["AltBusinessIDType", PropertyInfo(alias="altBusinessIdType")] """An enumeration.""" business_contact_email: Annotated[str, PropertyInfo(alias="businessContactEmail")] @@ -58,7 +53,7 @@ class BrandUpdateParams(TypedDict, total=False): first_name: Annotated[str, PropertyInfo(alias="firstName")] """First name of business contact.""" - identity_status: Annotated[BrandIdentityStatus, PropertyInfo(alias="identityStatus")] + identity_status: Annotated["BrandIdentityStatus", PropertyInfo(alias="identityStatus")] """The verification status of an active brand""" ip_address: Annotated[str, PropertyInfo(alias="ipAddress")] @@ -78,7 +73,7 @@ class BrandUpdateParams(TypedDict, total=False): state: str """State. Must be 2 letters code for United States.""" - stock_exchange: Annotated[StockExchange, PropertyInfo(alias="stockExchange")] + stock_exchange: Annotated["StockExchange", PropertyInfo(alias="stockExchange")] """(Required for public company) stock exchange.""" stock_symbol: Annotated[str, PropertyInfo(alias="stockSymbol")] @@ -95,3 +90,10 @@ class BrandUpdateParams(TypedDict, total=False): website: str """Brand website URL.""" + + +from .vertical import Vertical +from .entity_type import EntityType +from .stock_exchange import StockExchange +from .alt_business_id_type import AltBusinessIDType +from .brand_identity_status import BrandIdentityStatus diff --git a/src/telnyx/types/messaging_profile_create_params.py b/src/telnyx/types/messaging_profile_create_params.py index badd3edc5..9b464e085 100644 --- a/src/telnyx/types/messaging_profile_create_params.py +++ b/src/telnyx/types/messaging_profile_create_params.py @@ -6,9 +6,6 @@ from typing_extensions import Literal, Required, TypedDict from .._types import SequenceNotStr -from .number_pool_settings_param import NumberPoolSettingsParam -from .url_shortener_settings_param import URLShortenerSettingsParam -from .messaging_profile_features_param import MessagingProfileFeaturesParam __all__ = ["MessagingProfileCreateParams"] @@ -45,7 +42,7 @@ class MessagingProfileCreateParams(TypedDict, total=False): enabled: bool """Specifies whether the messaging profile is enabled or not.""" - features: Optional[MessagingProfileFeaturesParam] + features: Optional["MessagingProfileFeaturesParam"] """ Telnyx product features the messaging customer can enable on the messaging profile. Keys map to individual feature flags; unknown keys are accepted and @@ -64,7 +61,7 @@ class MessagingProfileCreateParams(TypedDict, total=False): mobile_only: bool """Send messages only to mobile phone numbers.""" - number_pool_settings: Optional[NumberPoolSettingsParam] + number_pool_settings: Optional["NumberPoolSettingsParam"] """ Number Pool allows you to send messages from a pool of numbers of different types, assigning weights to each type. The pool consists of all the long code @@ -84,7 +81,7 @@ class MessagingProfileCreateParams(TypedDict, total=False): minimize costs. """ - url_shortener_settings: Optional[URLShortenerSettingsParam] + url_shortener_settings: Optional["URLShortenerSettingsParam"] """ The URL shortener feature allows automatic replacement of URLs that were generated using a public URL shortener service. Some examples include bit.do, @@ -109,3 +106,8 @@ class MessagingProfileCreateParams(TypedDict, total=False): webhook_url: Optional[str] """The URL where webhooks related to this messaging profile will be sent.""" + + +from .number_pool_settings_param import NumberPoolSettingsParam +from .url_shortener_settings_param import URLShortenerSettingsParam +from .messaging_profile_features_param import MessagingProfileFeaturesParam diff --git a/src/telnyx/types/messaging_profile_metric_list_params.py b/src/telnyx/types/messaging_profile_metric_list_params.py index 40e729251..3c438e604 100644 --- a/src/telnyx/types/messaging_profile_metric_list_params.py +++ b/src/telnyx/types/messaging_profile_metric_list_params.py @@ -4,11 +4,12 @@ from typing_extensions import TypedDict -from .messaging_metrics_time_frame import MessagingMetricsTimeFrame - __all__ = ["MessagingProfileMetricListParams"] class MessagingProfileMetricListParams(TypedDict, total=False): - time_frame: MessagingMetricsTimeFrame + time_frame: "MessagingMetricsTimeFrame" """The time frame for metrics.""" + + +from .messaging_metrics_time_frame import MessagingMetricsTimeFrame diff --git a/src/telnyx/types/messaging_profile_retrieve_metrics_params.py b/src/telnyx/types/messaging_profile_retrieve_metrics_params.py index d5926f764..974cac2b8 100644 --- a/src/telnyx/types/messaging_profile_retrieve_metrics_params.py +++ b/src/telnyx/types/messaging_profile_retrieve_metrics_params.py @@ -4,11 +4,12 @@ from typing_extensions import TypedDict -from .messaging_metrics_time_frame import MessagingMetricsTimeFrame - __all__ = ["MessagingProfileRetrieveMetricsParams"] class MessagingProfileRetrieveMetricsParams(TypedDict, total=False): - time_frame: MessagingMetricsTimeFrame + time_frame: "MessagingMetricsTimeFrame" """The time frame for metrics.""" + + +from .messaging_metrics_time_frame import MessagingMetricsTimeFrame diff --git a/src/telnyx/types/messaging_profile_update_params.py b/src/telnyx/types/messaging_profile_update_params.py index dcfdbb2e4..7e47456ba 100644 --- a/src/telnyx/types/messaging_profile_update_params.py +++ b/src/telnyx/types/messaging_profile_update_params.py @@ -6,9 +6,6 @@ from typing_extensions import Literal, TypedDict from .._types import SequenceNotStr -from .number_pool_settings_param import NumberPoolSettingsParam -from .url_shortener_settings_param import URLShortenerSettingsParam -from .messaging_profile_features_param import MessagingProfileFeaturesParam __all__ = ["MessagingProfileUpdateParams"] @@ -35,7 +32,7 @@ class MessagingProfileUpdateParams(TypedDict, total=False): enabled: bool """Specifies whether the messaging profile is enabled or not.""" - features: Optional[MessagingProfileFeaturesParam] + features: Optional["MessagingProfileFeaturesParam"] """ Telnyx product features the messaging customer can enable on the messaging profile. Keys map to individual feature flags; unknown keys are accepted and @@ -54,7 +51,7 @@ class MessagingProfileUpdateParams(TypedDict, total=False): name: str """A user friendly name for the messaging profile.""" - number_pool_settings: Optional[NumberPoolSettingsParam] + number_pool_settings: Optional["NumberPoolSettingsParam"] """ Number Pool allows you to send messages from a pool of numbers of different types, assigning weights to each type. The pool consists of all the long code @@ -87,7 +84,7 @@ class MessagingProfileUpdateParams(TypedDict, total=False): minimize costs. """ - url_shortener_settings: Optional[URLShortenerSettingsParam] + url_shortener_settings: Optional["URLShortenerSettingsParam"] """ The URL shortener feature allows automatic replacement of URLs that were generated using a public URL shortener service. Some examples include bit.do, @@ -124,3 +121,8 @@ class MessagingProfileUpdateParams(TypedDict, total=False): This field is required if the messaging profile doesn't have it defined yet. """ + + +from .number_pool_settings_param import NumberPoolSettingsParam +from .url_shortener_settings_param import URLShortenerSettingsParam +from .messaging_profile_features_param import MessagingProfileFeaturesParam diff --git a/src/telnyx/types/messaging_tollfree/verification/request_create_params.py b/src/telnyx/types/messaging_tollfree/verification/request_create_params.py index 9e84bd6d1..c87b6c187 100644 --- a/src/telnyx/types/messaging_tollfree/verification/request_create_params.py +++ b/src/telnyx/types/messaging_tollfree/verification/request_create_params.py @@ -5,12 +5,7 @@ from typing import Iterable, Optional from typing_extensions import Required, Annotated, TypedDict -from .volume import Volume from ...._utils import PropertyInfo -from .url_param import URLParam -from .use_case_categories import UseCaseCategories -from .tf_phone_number_param import TfPhoneNumberParam -from .messaging_toll_free_verification_entity_type import MessagingTollFreeVerificationEntityType __all__ = ["RequestCreateParams"] @@ -58,7 +53,7 @@ class RequestCreateParams(TypedDict, total=False): corporate_website: Required[Annotated[str, PropertyInfo(alias="corporateWebsite")]] """A URL, including the scheme, pointing to the corporate website""" - message_volume: Required[Annotated[Volume, PropertyInfo(alias="messageVolume")]] + message_volume: Required[Annotated["Volume", PropertyInfo(alias="messageVolume")]] """Message Volume Enums""" opt_in_workflow: Required[Annotated[str, PropertyInfo(alias="optInWorkflow")]] @@ -67,16 +62,16 @@ class RequestCreateParams(TypedDict, total=False): from the given phone numbers """ - opt_in_workflow_image_urls: Required[Annotated[Iterable[URLParam], PropertyInfo(alias="optInWorkflowImageURLs")]] + opt_in_workflow_image_urls: Required[Annotated[Iterable["URLParam"], PropertyInfo(alias="optInWorkflowImageURLs")]] """Images showing the opt-in workflow""" - phone_numbers: Required[Annotated[Iterable[TfPhoneNumberParam], PropertyInfo(alias="phoneNumbers")]] + phone_numbers: Required[Annotated[Iterable["TfPhoneNumberParam"], PropertyInfo(alias="phoneNumbers")]] """The phone numbers to request the verification of""" production_message_content: Required[Annotated[str, PropertyInfo(alias="productionMessageContent")]] """An example of a message that will be sent from the given phone numbers""" - use_case: Required[Annotated[UseCaseCategories, PropertyInfo(alias="useCase")]] + use_case: Required[Annotated["UseCaseCategories", PropertyInfo(alias="useCase")]] """Tollfree usecase categories""" use_case_summary: Required[Annotated[str, PropertyInfo(alias="useCaseSummary")]] @@ -119,7 +114,7 @@ class RequestCreateParams(TypedDict, total=False): doing_business_as: Annotated[Optional[str], PropertyInfo(alias="doingBusinessAs")] """Doing Business As (DBA) name if different from legal name""" - entity_type: Annotated[Optional[MessagingTollFreeVerificationEntityType], PropertyInfo(alias="entityType")] + entity_type: Annotated[Optional["MessagingTollFreeVerificationEntityType"], PropertyInfo(alias="entityType")] """Business entity classification""" help_message_response: Annotated[Optional[str], PropertyInfo(alias="helpMessageResponse")] @@ -148,3 +143,10 @@ class RequestCreateParams(TypedDict, total=False): webhook_url: Annotated[str, PropertyInfo(alias="webhookUrl")] """URL that should receive webhooks relating to this verification request""" + + +from .volume import Volume +from .url_param import URLParam +from .use_case_categories import UseCaseCategories +from .tf_phone_number_param import TfPhoneNumberParam +from .messaging_toll_free_verification_entity_type import MessagingTollFreeVerificationEntityType diff --git a/src/telnyx/types/messaging_tollfree/verification/request_list_params.py b/src/telnyx/types/messaging_tollfree/verification/request_list_params.py index a35697307..0e03d2e8b 100644 --- a/src/telnyx/types/messaging_tollfree/verification/request_list_params.py +++ b/src/telnyx/types/messaging_tollfree/verification/request_list_params.py @@ -7,7 +7,6 @@ from typing_extensions import Required, Annotated, TypedDict from ...._utils import PropertyInfo -from .tf_verification_status import TfVerificationStatus __all__ = ["RequestListParams"] @@ -34,5 +33,8 @@ class RequestListParams(TypedDict, total=False): phone_number: str """Filter results by phone number.""" - status: TfVerificationStatus + status: "TfVerificationStatus" """Filter results by status.""" + + +from .tf_verification_status import TfVerificationStatus diff --git a/src/telnyx/types/messaging_tollfree/verification/request_update_params.py b/src/telnyx/types/messaging_tollfree/verification/request_update_params.py index 067ba0ec4..c37da2e6d 100644 --- a/src/telnyx/types/messaging_tollfree/verification/request_update_params.py +++ b/src/telnyx/types/messaging_tollfree/verification/request_update_params.py @@ -5,12 +5,7 @@ from typing import Iterable, Optional from typing_extensions import Required, Annotated, TypedDict -from .volume import Volume from ...._utils import PropertyInfo -from .url_param import URLParam -from .use_case_categories import UseCaseCategories -from .tf_phone_number_param import TfPhoneNumberParam -from .messaging_toll_free_verification_entity_type import MessagingTollFreeVerificationEntityType __all__ = ["RequestUpdateParams"] @@ -58,7 +53,7 @@ class RequestUpdateParams(TypedDict, total=False): corporate_website: Required[Annotated[str, PropertyInfo(alias="corporateWebsite")]] """A URL, including the scheme, pointing to the corporate website""" - message_volume: Required[Annotated[Volume, PropertyInfo(alias="messageVolume")]] + message_volume: Required[Annotated["Volume", PropertyInfo(alias="messageVolume")]] """Message Volume Enums""" opt_in_workflow: Required[Annotated[str, PropertyInfo(alias="optInWorkflow")]] @@ -67,16 +62,16 @@ class RequestUpdateParams(TypedDict, total=False): from the given phone numbers """ - opt_in_workflow_image_urls: Required[Annotated[Iterable[URLParam], PropertyInfo(alias="optInWorkflowImageURLs")]] + opt_in_workflow_image_urls: Required[Annotated[Iterable["URLParam"], PropertyInfo(alias="optInWorkflowImageURLs")]] """Images showing the opt-in workflow""" - phone_numbers: Required[Annotated[Iterable[TfPhoneNumberParam], PropertyInfo(alias="phoneNumbers")]] + phone_numbers: Required[Annotated[Iterable["TfPhoneNumberParam"], PropertyInfo(alias="phoneNumbers")]] """The phone numbers to request the verification of""" production_message_content: Required[Annotated[str, PropertyInfo(alias="productionMessageContent")]] """An example of a message that will be sent from the given phone numbers""" - use_case: Required[Annotated[UseCaseCategories, PropertyInfo(alias="useCase")]] + use_case: Required[Annotated["UseCaseCategories", PropertyInfo(alias="useCase")]] """Tollfree usecase categories""" use_case_summary: Required[Annotated[str, PropertyInfo(alias="useCaseSummary")]] @@ -119,7 +114,7 @@ class RequestUpdateParams(TypedDict, total=False): doing_business_as: Annotated[Optional[str], PropertyInfo(alias="doingBusinessAs")] """Doing Business As (DBA) name if different from legal name""" - entity_type: Annotated[Optional[MessagingTollFreeVerificationEntityType], PropertyInfo(alias="entityType")] + entity_type: Annotated[Optional["MessagingTollFreeVerificationEntityType"], PropertyInfo(alias="entityType")] """Business entity classification""" help_message_response: Annotated[Optional[str], PropertyInfo(alias="helpMessageResponse")] @@ -148,3 +143,10 @@ class RequestUpdateParams(TypedDict, total=False): webhook_url: Annotated[str, PropertyInfo(alias="webhookUrl")] """URL that should receive webhooks relating to this verification request""" + + +from .volume import Volume +from .url_param import URLParam +from .use_case_categories import UseCaseCategories +from .tf_phone_number_param import TfPhoneNumberParam +from .messaging_toll_free_verification_entity_type import MessagingTollFreeVerificationEntityType diff --git a/src/telnyx/types/model_metadata.py b/src/telnyx/types/model_metadata.py index c4708004b..7246be2cf 100644 --- a/src/telnyx/types/model_metadata.py +++ b/src/telnyx/types/model_metadata.py @@ -86,10 +86,10 @@ class ModelMetadata(BaseModel): """ max_completion_tokens: Optional[int] = None - """Maximum number of completion (output) tokens the model will generate per - request. + """Maximum completion (output) tokens the model may generate per request. - `null` if unconstrained beyond `context_length`. + This value caps the Chat Completions `max_tokens` default and any larger + explicit value on that model. `null` if unconstrained beyond `context_length`. """ object: Optional[str] = None diff --git a/src/telnyx/types/network_coverage_list_params.py b/src/telnyx/types/network_coverage_list_params.py index a9f1764ff..4ca4f0a03 100644 --- a/src/telnyx/types/network_coverage_list_params.py +++ b/src/telnyx/types/network_coverage_list_params.py @@ -6,7 +6,6 @@ from typing_extensions import Annotated, TypeAlias, TypedDict from .._utils import PropertyInfo -from .available_service import AvailableService __all__ = [ "NetworkCoverageListParams", @@ -58,11 +57,11 @@ class Filter(TypedDict, total=False): class FiltersAvailableServicesContains(TypedDict, total=False): """Available service filtering operations""" - contains: AvailableService + contains: "AvailableService" """Filter by available services containing the specified service""" -FiltersAvailableServices: TypeAlias = Union[AvailableService, FiltersAvailableServicesContains] +FiltersAvailableServices: TypeAlias = Union["AvailableService", FiltersAvailableServicesContains] class Filters(TypedDict, total=False): @@ -73,3 +72,6 @@ class Filters(TypedDict, total=False): available_services: FiltersAvailableServices """Filter by exact available service match""" + + +from .available_service import AvailableService diff --git a/src/telnyx/types/network_create_params.py b/src/telnyx/types/network_create_params.py index 8961b1962..d54ac89df 100644 --- a/src/telnyx/types/network_create_params.py +++ b/src/telnyx/types/network_create_params.py @@ -4,10 +4,11 @@ from typing_extensions import Required, TypedDict -from .network_create_param import NetworkCreateParam - __all__ = ["NetworkCreateParams"] class NetworkCreateParams(TypedDict, total=False): - network_create: Required[NetworkCreateParam] + network_create: Required["NetworkCreateParam"] + + +from .network_create_param import NetworkCreateParam diff --git a/src/telnyx/types/network_update_params.py b/src/telnyx/types/network_update_params.py index 317080130..248e84afe 100644 --- a/src/telnyx/types/network_update_params.py +++ b/src/telnyx/types/network_update_params.py @@ -4,10 +4,11 @@ from typing_extensions import Required, TypedDict -from .network_create_param import NetworkCreateParam - __all__ = ["NetworkUpdateParams"] class NetworkUpdateParams(TypedDict, total=False): - network_create: Required[NetworkCreateParam] + network_create: Required["NetworkCreateParam"] + + +from .network_create_param import NetworkCreateParam diff --git a/src/telnyx/types/number_order_phone_number_update_requirements_params.py b/src/telnyx/types/number_order_phone_number_update_requirements_params.py index e07e3c243..cb3d69bd0 100644 --- a/src/telnyx/types/number_order_phone_number_update_requirements_params.py +++ b/src/telnyx/types/number_order_phone_number_update_requirements_params.py @@ -5,10 +5,11 @@ from typing import Iterable from typing_extensions import TypedDict -from .update_regulatory_requirement_param import UpdateRegulatoryRequirementParam - __all__ = ["NumberOrderPhoneNumberUpdateRequirementsParams"] class NumberOrderPhoneNumberUpdateRequirementsParams(TypedDict, total=False): - regulatory_requirements: Iterable[UpdateRegulatoryRequirementParam] + regulatory_requirements: Iterable["UpdateRegulatoryRequirementParam"] + + +from .update_regulatory_requirement_param import UpdateRegulatoryRequirementParam diff --git a/src/telnyx/types/number_order_update_params.py b/src/telnyx/types/number_order_update_params.py index 2c3590587..249938f52 100644 --- a/src/telnyx/types/number_order_update_params.py +++ b/src/telnyx/types/number_order_update_params.py @@ -5,8 +5,6 @@ from typing import Iterable from typing_extensions import TypedDict -from .update_regulatory_requirement_param import UpdateRegulatoryRequirementParam - __all__ = ["NumberOrderUpdateParams"] @@ -14,4 +12,7 @@ class NumberOrderUpdateParams(TypedDict, total=False): customer_reference: str """A customer reference string for customer look ups.""" - regulatory_requirements: Iterable[UpdateRegulatoryRequirementParam] + regulatory_requirements: Iterable["UpdateRegulatoryRequirementParam"] + + +from .update_regulatory_requirement_param import UpdateRegulatoryRequirementParam diff --git a/src/telnyx/types/number_reservation_create_params.py b/src/telnyx/types/number_reservation_create_params.py index 327859a11..c9d51ba67 100644 --- a/src/telnyx/types/number_reservation_create_params.py +++ b/src/telnyx/types/number_reservation_create_params.py @@ -5,8 +5,6 @@ from typing import Iterable from typing_extensions import TypedDict -from .reserved_phone_number_param import ReservedPhoneNumberParam - __all__ = ["NumberReservationCreateParams"] @@ -14,4 +12,7 @@ class NumberReservationCreateParams(TypedDict, total=False): customer_reference: str """A customer reference string for customer look ups.""" - phone_numbers: Iterable[ReservedPhoneNumberParam] + phone_numbers: Iterable["ReservedPhoneNumberParam"] + + +from .reserved_phone_number_param import ReservedPhoneNumberParam diff --git a/src/telnyx/types/organization_contact.py b/src/telnyx/types/organization_contact.py index 4fe381026..4fd06aa10 100644 --- a/src/telnyx/types/organization_contact.py +++ b/src/telnyx/types/organization_contact.py @@ -9,12 +9,22 @@ class OrganizationContact(BaseModel): email: str + """The email address of the main person Telnyx should contact about this account. + + For a call center (BPO) account this is the email you will verify later, so use + a mailbox you can access. + """ first_name: str + """The first name of the main person Telnyx should contact about this account.""" job_title: str + """The job title of the main person Telnyx should contact about this account.""" last_name: str + """The last name of the main person Telnyx should contact about this account.""" phone_number: str - """E.164 format with leading `+`.""" + """ + The phone number of the main contact, in E.164 format, for example +12125551234. + """ diff --git a/src/telnyx/types/organization_contact_param.py b/src/telnyx/types/organization_contact_param.py index 7948928a4..05cc1dc1d 100644 --- a/src/telnyx/types/organization_contact_param.py +++ b/src/telnyx/types/organization_contact_param.py @@ -9,12 +9,22 @@ class OrganizationContactParam(TypedDict, total=False): email: Required[str] + """The email address of the main person Telnyx should contact about this account. + + For a call center (BPO) account this is the email you will verify later, so use + a mailbox you can access. + """ first_name: Required[str] + """The first name of the main person Telnyx should contact about this account.""" job_title: Required[str] + """The job title of the main person Telnyx should contact about this account.""" last_name: Required[str] + """The last name of the main person Telnyx should contact about this account.""" phone_number: Required[str] - """E.164 format with leading `+`.""" + """ + The phone number of the main contact, in E.164 format, for example +12125551234. + """ diff --git a/src/telnyx/types/outbound_fqdn_param.py b/src/telnyx/types/outbound_fqdn_param.py index 3d6182db8..4aea2c957 100644 --- a/src/telnyx/types/outbound_fqdn_param.py +++ b/src/telnyx/types/outbound_fqdn_param.py @@ -5,8 +5,6 @@ from typing import Optional from typing_extensions import Literal, TypedDict -from .encrypted_media import EncryptedMedia - __all__ = ["OutboundFqdnParam"] @@ -37,7 +35,7 @@ class OutboundFqdnParam(TypedDict, total=False): associated with this connection. """ - encrypted_media: Optional[EncryptedMedia] + encrypted_media: Optional["EncryptedMedia"] """Enable use of SRTP for encryption. Cannot be set if the transport_portocol is TLS. @@ -83,3 +81,6 @@ class OutboundFqdnParam(TypedDict, total=False): timeout_2xx_secs: int """Time(sec) before aborting if call is unanswered (min: 1, max: 600).""" + + +from .encrypted_media import EncryptedMedia diff --git a/src/telnyx/types/outbound_voice_profile_create_params.py b/src/telnyx/types/outbound_voice_profile_create_params.py index 3f6cb2703..4b846f10e 100644 --- a/src/telnyx/types/outbound_voice_profile_create_params.py +++ b/src/telnyx/types/outbound_voice_profile_create_params.py @@ -6,10 +6,6 @@ from typing_extensions import Required, TypedDict from .._types import SequenceNotStr -from .service_plan import ServicePlan -from .traffic_type import TrafficType -from .usage_payment_method import UsagePaymentMethod -from .outbound_call_recording_param import OutboundCallRecordingParam __all__ = ["OutboundVoiceProfileCreateParams", "CallingWindow"] @@ -24,7 +20,7 @@ class OutboundVoiceProfileCreateParams(TypedDict, total=False): Defaults to null (for no group assigned). """ - call_recording: OutboundCallRecordingParam + call_recording: "OutboundCallRecordingParam" calling_window: CallingWindow """ @@ -60,15 +56,15 @@ class OutboundVoiceProfileCreateParams(TypedDict, total=False): outbound calls. """ - service_plan: ServicePlan + service_plan: "ServicePlan" """Indicates the coverage of the termination regions.""" tags: SequenceNotStr[str] - traffic_type: TrafficType + traffic_type: "TrafficType" """Specifies the type of traffic allowed in this profile.""" - usage_payment_method: UsagePaymentMethod + usage_payment_method: "UsagePaymentMethod" """Setting for how costs for outbound profile are calculated.""" whitelisted_destinations: SequenceNotStr[str] @@ -100,3 +96,9 @@ class CallingWindow(TypedDict, total=False): The UTC time of day (in HH:MM format, 24-hour clock) when calls are allowed to start. """ + + +from .service_plan import ServicePlan +from .traffic_type import TrafficType +from .usage_payment_method import UsagePaymentMethod +from .outbound_call_recording_param import OutboundCallRecordingParam diff --git a/src/telnyx/types/outbound_voice_profile_update_params.py b/src/telnyx/types/outbound_voice_profile_update_params.py index 4d9954133..dff3d1cb4 100644 --- a/src/telnyx/types/outbound_voice_profile_update_params.py +++ b/src/telnyx/types/outbound_voice_profile_update_params.py @@ -6,10 +6,6 @@ from typing_extensions import Required, TypedDict from .._types import SequenceNotStr -from .service_plan import ServicePlan -from .traffic_type import TrafficType -from .usage_payment_method import UsagePaymentMethod -from .outbound_call_recording_param import OutboundCallRecordingParam __all__ = ["OutboundVoiceProfileUpdateParams", "CallingWindow"] @@ -24,7 +20,7 @@ class OutboundVoiceProfileUpdateParams(TypedDict, total=False): Defaults to null (for no group assigned). """ - call_recording: OutboundCallRecordingParam + call_recording: "OutboundCallRecordingParam" calling_window: CallingWindow """ @@ -60,15 +56,15 @@ class OutboundVoiceProfileUpdateParams(TypedDict, total=False): outbound calls. """ - service_plan: ServicePlan + service_plan: "ServicePlan" """Indicates the coverage of the termination regions.""" tags: SequenceNotStr[str] - traffic_type: TrafficType + traffic_type: "TrafficType" """Specifies the type of traffic allowed in this profile.""" - usage_payment_method: UsagePaymentMethod + usage_payment_method: "UsagePaymentMethod" """Setting for how costs for outbound profile are calculated.""" whitelisted_destinations: SequenceNotStr[str] @@ -100,3 +96,9 @@ class CallingWindow(TypedDict, total=False): The UTC time of day (in HH:MM format, 24-hour clock) when calls are allowed to start. """ + + +from .service_plan import ServicePlan +from .traffic_type import TrafficType +from .usage_payment_method import UsagePaymentMethod +from .outbound_call_recording_param import OutboundCallRecordingParam diff --git a/src/telnyx/types/phone_numbers/job_update_batch_params.py b/src/telnyx/types/phone_numbers/job_update_batch_params.py index 03bf61e70..40197fb8f 100644 --- a/src/telnyx/types/phone_numbers/job_update_batch_params.py +++ b/src/telnyx/types/phone_numbers/job_update_batch_params.py @@ -6,7 +6,6 @@ from ..._types import SequenceNotStr from ..._utils import PropertyInfo -from .update_voice_settings_param import UpdateVoiceSettingsParam __all__ = ["JobUpdateBatchParams", "Filter", "FilterVoiceConnectionName"] @@ -64,7 +63,7 @@ class JobUpdateBatchParams(TypedDict, total=False): tags: SequenceNotStr[str] """A list of user-assigned tags to help organize phone numbers.""" - voice: UpdateVoiceSettingsParam + voice: "UpdateVoiceSettingsParam" class FilterVoiceConnectionName(TypedDict, total=False): @@ -142,3 +141,6 @@ class Filter(TypedDict, total=False): Literal["pay-per-minute", "channel"], PropertyInfo(alias="voice.usage_payment_method") ] """Filter by usage_payment_method.""" + + +from .update_voice_settings_param import UpdateVoiceSettingsParam diff --git a/src/telnyx/types/phone_numbers/update_voice_settings_param.py b/src/telnyx/types/phone_numbers/update_voice_settings_param.py index 5e660599f..a1735adad 100644 --- a/src/telnyx/types/phone_numbers/update_voice_settings_param.py +++ b/src/telnyx/types/phone_numbers/update_voice_settings_param.py @@ -4,25 +4,20 @@ from typing_extensions import Literal, TypedDict -from .cnam_listing_param import CnamListingParam -from .call_recording_param import CallRecordingParam -from .media_features_param import MediaFeaturesParam -from .call_forwarding_param import CallForwardingParam - __all__ = ["UpdateVoiceSettingsParam"] class UpdateVoiceSettingsParam(TypedDict, total=False): - call_forwarding: CallForwardingParam + call_forwarding: "CallForwardingParam" """The call forwarding settings for a phone number.""" - call_recording: CallRecordingParam + call_recording: "CallRecordingParam" """The call recording settings for a phone number.""" caller_id_name_enabled: bool """Controls whether the caller ID name is enabled for this phone number.""" - cnam_listing: CnamListingParam + cnam_listing: "CnamListingParam" """The CNAM listing settings for a phone number.""" inbound_call_screening: Literal["disabled", "reject_calls", "flag_calls"] @@ -33,7 +28,7 @@ class UpdateVoiceSettingsParam(TypedDict, total=False): feature has an additional per-number monthly cost associated with it. """ - media_features: MediaFeaturesParam + media_features: "MediaFeaturesParam" """The media features settings for a phone number.""" tech_prefix_enabled: bool @@ -50,3 +45,9 @@ class UpdateVoiceSettingsParam(TypedDict, total=False): """ Controls whether a number is billed per minute or uses your concurrent channels. """ + + +from .cnam_listing_param import CnamListingParam +from .call_recording_param import CallRecordingParam +from .media_features_param import MediaFeaturesParam +from .call_forwarding_param import CallForwardingParam diff --git a/src/telnyx/types/phone_numbers/voice_update_params.py b/src/telnyx/types/phone_numbers/voice_update_params.py index e7a686c6b..e30624539 100644 --- a/src/telnyx/types/phone_numbers/voice_update_params.py +++ b/src/telnyx/types/phone_numbers/voice_update_params.py @@ -4,25 +4,20 @@ from typing_extensions import Literal, TypedDict -from .cnam_listing_param import CnamListingParam -from .call_recording_param import CallRecordingParam -from .media_features_param import MediaFeaturesParam -from .call_forwarding_param import CallForwardingParam - __all__ = ["VoiceUpdateParams"] class VoiceUpdateParams(TypedDict, total=False): - call_forwarding: CallForwardingParam + call_forwarding: "CallForwardingParam" """The call forwarding settings for a phone number.""" - call_recording: CallRecordingParam + call_recording: "CallRecordingParam" """The call recording settings for a phone number.""" caller_id_name_enabled: bool """Controls whether the caller ID name is enabled for this phone number.""" - cnam_listing: CnamListingParam + cnam_listing: "CnamListingParam" """The CNAM listing settings for a phone number.""" inbound_call_screening: Literal["disabled", "reject_calls", "flag_calls"] @@ -33,7 +28,7 @@ class VoiceUpdateParams(TypedDict, total=False): feature has an additional per-number monthly cost associated with it. """ - media_features: MediaFeaturesParam + media_features: "MediaFeaturesParam" """The media features settings for a phone number.""" tech_prefix_enabled: bool @@ -50,3 +45,9 @@ class VoiceUpdateParams(TypedDict, total=False): """ Controls whether a number is billed per minute or uses your concurrent channels. """ + + +from .cnam_listing_param import CnamListingParam +from .call_recording_param import CallRecordingParam +from .media_features_param import MediaFeaturesParam +from .call_forwarding_param import CallForwardingParam diff --git a/src/telnyx/types/physical_address.py b/src/telnyx/types/physical_address.py index 393025227..91dab1c55 100644 --- a/src/telnyx/types/physical_address.py +++ b/src/telnyx/types/physical_address.py @@ -14,12 +14,22 @@ class PhysicalAddress(BaseModel): """State or province code (e.g. `IL`, `ON`).""" city: str + """The city of your registered business address.""" country: str """ISO 3166-1 alpha-2 code (currently `US` or `CA`).""" postal_code: str + """The postal or ZIP code of your registered business address.""" street_address: str + """ + The street address of your registered business, including the building number + and street name. + """ extended_address: Optional[str] = None + """An optional second address line, such as a suite, unit, or floor. + + Leave blank if it does not apply. + """ diff --git a/src/telnyx/types/physical_address_param.py b/src/telnyx/types/physical_address_param.py index b0fd0c4dc..ed987fcbf 100644 --- a/src/telnyx/types/physical_address_param.py +++ b/src/telnyx/types/physical_address_param.py @@ -13,12 +13,22 @@ class PhysicalAddressParam(TypedDict, total=False): """State or province code (e.g. `IL`, `ON`).""" city: Required[str] + """The city of your registered business address.""" country: Required[str] """ISO 3166-1 alpha-2 code (currently `US` or `CA`).""" postal_code: Required[str] + """The postal or ZIP code of your registered business address.""" street_address: Required[str] + """ + The street address of your registered business, including the building number + and street name. + """ extended_address: Optional[str] + """An optional second address line, such as a suite, unit, or floor. + + Leave blank if it does not apply. + """ diff --git a/src/telnyx/types/porting/report_create_params.py b/src/telnyx/types/porting/report_create_params.py index f8e681a6a..70bbfaf9b 100644 --- a/src/telnyx/types/porting/report_create_params.py +++ b/src/telnyx/types/porting/report_create_params.py @@ -4,14 +4,15 @@ from typing_extensions import Literal, Required, TypedDict -from .export_porting_orders_csv_report_param import ExportPortingOrdersCsvReportParam - __all__ = ["ReportCreateParams"] class ReportCreateParams(TypedDict, total=False): - params: Required[ExportPortingOrdersCsvReportParam] + params: Required["ExportPortingOrdersCsvReportParam"] """The parameters for generating a porting orders CSV report.""" report_type: Required[Literal["export_porting_orders_csv"]] """Identifies the type of report""" + + +from .export_porting_orders_csv_report_param import ExportPortingOrdersCsvReportParam diff --git a/src/telnyx/types/porting_order.py b/src/telnyx/types/porting_order.py index 8ab826c3a..414009cc4 100644 --- a/src/telnyx/types/porting_order.py +++ b/src/telnyx/types/porting_order.py @@ -66,7 +66,9 @@ class PortingOrder(BaseModel): phone_number_configuration: Optional[PortingOrderPhoneNumberConfiguration] = None - phone_number_type: Optional[Literal["landline", "local", "mobile", "national", "shared_cost", "toll_free"]] = None + phone_number_type: Optional[ + Literal["landline", "local", "mobile", "multipurpose", "national", "other", "shared_cost", "toll_free"] + ] = None """The type of the phone number""" phone_numbers: Optional[List[PortingPhoneNumber]] = None diff --git a/src/telnyx/types/porting_order_end_user_param.py b/src/telnyx/types/porting_order_end_user_param.py index 9ac780482..6a23af430 100644 --- a/src/telnyx/types/porting_order_end_user_param.py +++ b/src/telnyx/types/porting_order_end_user_param.py @@ -4,13 +4,14 @@ from typing_extensions import TypedDict -from .porting_order_end_user_admin_param import PortingOrderEndUserAdminParam -from .porting_order_end_user_location_param import PortingOrderEndUserLocationParam - __all__ = ["PortingOrderEndUserParam"] class PortingOrderEndUserParam(TypedDict, total=False): - admin: PortingOrderEndUserAdminParam + admin: "PortingOrderEndUserAdminParam" + + location: "PortingOrderEndUserLocationParam" - location: PortingOrderEndUserLocationParam + +from .porting_order_end_user_admin_param import PortingOrderEndUserAdminParam +from .porting_order_end_user_location_param import PortingOrderEndUserLocationParam diff --git a/src/telnyx/types/porting_order_list_params.py b/src/telnyx/types/porting_order_list_params.py index a6955f026..a13a047ee 100644 --- a/src/telnyx/types/porting_order_list_params.py +++ b/src/telnyx/types/porting_order_list_params.py @@ -5,7 +5,6 @@ from typing_extensions import Literal, Annotated, TypedDict from .._utils import PropertyInfo -from .porting_order_type import PortingOrderType __all__ = [ "PortingOrderListParams", @@ -77,7 +76,7 @@ class FilterEndUser(TypedDict, total=False): class FilterMisc(TypedDict, total=False): - type: PortingOrderType + type: "PortingOrderType" """Filter results by porting order type""" @@ -136,3 +135,6 @@ class Sort(TypedDict, total=False): If not given, results are sorted by created_at in descending order. """ + + +from .porting_order_type import PortingOrderType diff --git a/src/telnyx/types/porting_order_misc_param.py b/src/telnyx/types/porting_order_misc_param.py index 39205e647..9c6ab711d 100644 --- a/src/telnyx/types/porting_order_misc_param.py +++ b/src/telnyx/types/porting_order_misc_param.py @@ -5,8 +5,6 @@ from typing import Optional from typing_extensions import Literal, TypedDict -from .porting_order_type import PortingOrderType - __all__ = ["PortingOrderMiscParam"] @@ -26,8 +24,11 @@ class PortingOrderMiscParam(TypedDict, total=False): 'remaining_numbers_action' is 'keep'. """ - type: PortingOrderType + type: "PortingOrderType" """A port can be either 'full' or 'partial'. When type is 'full' the other attributes should be omitted. """ + + +from .porting_order_type import PortingOrderType diff --git a/src/telnyx/types/porting_order_update_params.py b/src/telnyx/types/porting_order_update_params.py index 13ce7569b..6948a8fa0 100644 --- a/src/telnyx/types/porting_order_update_params.py +++ b/src/telnyx/types/porting_order_update_params.py @@ -7,11 +7,6 @@ from typing_extensions import Required, Annotated, TypedDict from .._utils import PropertyInfo -from .porting_order_misc_param import PortingOrderMiscParam -from .porting_order_end_user_param import PortingOrderEndUserParam -from .porting_order_documents_param import PortingOrderDocumentsParam -from .porting_order_user_feedback_param import PortingOrderUserFeedbackParam -from .porting_order_phone_number_configuration_param import PortingOrderPhoneNumberConfigurationParam __all__ = ["PortingOrderUpdateParams", "ActivationSettings", "Messaging", "Requirement"] @@ -23,16 +18,16 @@ class PortingOrderUpdateParams(TypedDict, total=False): customer_reference: str - documents: PortingOrderDocumentsParam + documents: "PortingOrderDocumentsParam" """Can be specified directly or via the `requirement_group_id` parameter.""" - end_user: PortingOrderEndUserParam + end_user: "PortingOrderEndUserParam" messaging: Messaging - misc: Optional[PortingOrderMiscParam] + misc: Optional["PortingOrderMiscParam"] - phone_number_configuration: PortingOrderPhoneNumberConfigurationParam + phone_number_configuration: "PortingOrderPhoneNumberConfigurationParam" requirement_group_id: str """ @@ -46,7 +41,7 @@ class PortingOrderUpdateParams(TypedDict, total=False): requirements: Iterable[Requirement] """List of requirements for porting numbers.""" - user_feedback: PortingOrderUserFeedbackParam + user_feedback: "PortingOrderUserFeedbackParam" webhook_url: str @@ -76,3 +71,10 @@ class Requirement(TypedDict, total=False): requirement_type_id: Required[str] """Identifies the requirement type that the `field_value` fulfills""" + + +from .porting_order_misc_param import PortingOrderMiscParam +from .porting_order_end_user_param import PortingOrderEndUserParam +from .porting_order_documents_param import PortingOrderDocumentsParam +from .porting_order_user_feedback_param import PortingOrderUserFeedbackParam +from .porting_order_phone_number_configuration_param import PortingOrderPhoneNumberConfigurationParam diff --git a/src/telnyx/types/porting_orders/porting_phone_number_block.py b/src/telnyx/types/porting_orders/porting_phone_number_block.py index 2f8c2a174..4be8f8808 100644 --- a/src/telnyx/types/porting_orders/porting_phone_number_block.py +++ b/src/telnyx/types/porting_orders/porting_phone_number_block.py @@ -63,7 +63,9 @@ class PortingPhoneNumberBlock(BaseModel): phone_number_range: Optional[PhoneNumberRange] = None """Specifies the phone number range for this porting phone number block.""" - phone_number_type: Optional[Literal["landline", "local", "mobile", "national", "shared_cost", "toll_free"]] = None + phone_number_type: Optional[ + Literal["landline", "local", "mobile", "multipurpose", "national", "other", "shared_cost", "toll_free"] + ] = None """Specifies the phone number type for this porting phone number block.""" record_type: Optional[str] = None diff --git a/src/telnyx/types/porting_phone_number.py b/src/telnyx/types/porting_phone_number.py index ac98cf861..9bf3d5847 100644 --- a/src/telnyx/types/porting_phone_number.py +++ b/src/telnyx/types/porting_phone_number.py @@ -18,7 +18,9 @@ class PortingPhoneNumber(BaseModel): phone_number: Optional[str] = None """E164 formatted phone number""" - phone_number_type: Optional[Literal["landline", "local", "mobile", "national", "shared_cost", "toll_free"]] = None + phone_number_type: Optional[ + Literal["landline", "local", "mobile", "multipurpose", "national", "other", "shared_cost", "toll_free"] + ] = None """The type of the phone number""" portability_status: Optional[Literal["pending", "confirmed", "provisional"]] = None diff --git a/src/telnyx/types/portouts/report_create_params.py b/src/telnyx/types/portouts/report_create_params.py index 60079564d..17ba0db54 100644 --- a/src/telnyx/types/portouts/report_create_params.py +++ b/src/telnyx/types/portouts/report_create_params.py @@ -4,14 +4,15 @@ from typing_extensions import Literal, Required, TypedDict -from .export_portouts_csv_report_param import ExportPortoutsCsvReportParam - __all__ = ["ReportCreateParams"] class ReportCreateParams(TypedDict, total=False): - params: Required[ExportPortoutsCsvReportParam] + params: Required["ExportPortoutsCsvReportParam"] """The parameters for generating a port-outs CSV report.""" report_type: Required[Literal["export_portouts_csv"]] """Identifies the type of report""" + + +from .export_portouts_csv_report_param import ExportPortoutsCsvReportParam diff --git a/src/telnyx/types/pronunciation_dict_create_params.py b/src/telnyx/types/pronunciation_dict_create_params.py index 13dea5f19..f7a6b10fa 100644 --- a/src/telnyx/types/pronunciation_dict_create_params.py +++ b/src/telnyx/types/pronunciation_dict_create_params.py @@ -5,13 +5,11 @@ from typing import Iterable from typing_extensions import Required, TypedDict -from .pronunciation_dict_item_param import PronunciationDictItemParam - __all__ = ["PronunciationDictCreateParams"] class PronunciationDictCreateParams(TypedDict, total=False): - items: Required[Iterable[PronunciationDictItemParam]] + items: Required[Iterable["PronunciationDictItemParam"]] """List of pronunciation items (alias or phoneme type). At least one item is required. @@ -19,3 +17,6 @@ class PronunciationDictCreateParams(TypedDict, total=False): name: Required[str] """Human-readable name. Must be unique within the organization.""" + + +from .pronunciation_dict_item_param import PronunciationDictItemParam diff --git a/src/telnyx/types/pronunciation_dict_item_param.py b/src/telnyx/types/pronunciation_dict_item_param.py index b22b9ae68..5ce7f3d05 100644 --- a/src/telnyx/types/pronunciation_dict_item_param.py +++ b/src/telnyx/types/pronunciation_dict_item_param.py @@ -5,9 +5,9 @@ from typing import Union from typing_extensions import TypeAlias -from .pronunciation_dict_alias_item_param import PronunciationDictAliasItemParam -from .pronunciation_dict_phoneme_item_param import PronunciationDictPhonemeItemParam - __all__ = ["PronunciationDictItemParam"] -PronunciationDictItemParam: TypeAlias = Union[PronunciationDictAliasItemParam, PronunciationDictPhonemeItemParam] +PronunciationDictItemParam: TypeAlias = Union["PronunciationDictAliasItemParam", "PronunciationDictPhonemeItemParam"] + +from .pronunciation_dict_alias_item_param import PronunciationDictAliasItemParam +from .pronunciation_dict_phoneme_item_param import PronunciationDictPhonemeItemParam diff --git a/src/telnyx/types/pronunciation_dict_update_params.py b/src/telnyx/types/pronunciation_dict_update_params.py index 4d8cecd80..9aee50d6f 100644 --- a/src/telnyx/types/pronunciation_dict_update_params.py +++ b/src/telnyx/types/pronunciation_dict_update_params.py @@ -5,14 +5,15 @@ from typing import Iterable from typing_extensions import TypedDict -from .pronunciation_dict_item_param import PronunciationDictItemParam - __all__ = ["PronunciationDictUpdateParams"] class PronunciationDictUpdateParams(TypedDict, total=False): - items: Iterable[PronunciationDictItemParam] + items: Iterable["PronunciationDictItemParam"] """Updated list of pronunciation items (alias or phoneme type).""" name: str """Updated dictionary name.""" + + +from .pronunciation_dict_item_param import PronunciationDictItemParam diff --git a/src/telnyx/types/rcs/agent_campaign_configuration_param.py b/src/telnyx/types/rcs/agent_campaign_configuration_param.py index f0f4a7f7a..1763dd3a2 100644 --- a/src/telnyx/types/rcs/agent_campaign_configuration_param.py +++ b/src/telnyx/types/rcs/agent_campaign_configuration_param.py @@ -6,8 +6,6 @@ from typing_extensions import Required, TypedDict from ..._types import SequenceNotStr -from .agent_interaction_param import AgentInteractionParam -from .agent_consent_configuration_param import AgentConsentConfigurationParam __all__ = ["AgentCampaignConfigurationParam"] @@ -19,8 +17,12 @@ class AgentCampaignConfigurationParam(TypedDict, total=False): agent_overview: Optional[str] - consent_settings: Optional[AgentConsentConfigurationParam] + consent_settings: Optional["AgentConsentConfigurationParam"] - interactions: Iterable[AgentInteractionParam] + interactions: Iterable["AgentInteractionParam"] message_examples: SequenceNotStr[str] + + +from .agent_interaction_param import AgentInteractionParam +from .agent_consent_configuration_param import AgentConsentConfigurationParam diff --git a/src/telnyx/types/rcs/agent_configuration_param.py b/src/telnyx/types/rcs/agent_configuration_param.py index b5623e36b..1f16bfb4b 100644 --- a/src/telnyx/types/rcs/agent_configuration_param.py +++ b/src/telnyx/types/rcs/agent_configuration_param.py @@ -5,12 +5,6 @@ from typing import Union, Optional from typing_extensions import Required, TypeAlias, TypedDict -from .agent_email_contact_param import AgentEmailContactParam -from .agent_phone_contact_param import AgentPhoneContactParam -from .agent_website_contact_param import AgentWebsiteContactParam -from .agent_testing_configuration_param import AgentTestingConfigurationParam -from .agent_campaign_configuration_param import AgentCampaignConfigurationParam - __all__ = [ "AgentConfigurationParam", "Basics", @@ -21,13 +15,13 @@ class BasicsAgentPhoneContactRequirement(TypedDict, total=False): - phone_number: Required[AgentPhoneContactParam] + phone_number: Required["AgentPhoneContactParam"] brand_color: str description: str - email: Optional[AgentEmailContactParam] + email: Optional["AgentEmailContactParam"] hero_url: str @@ -37,23 +31,23 @@ class BasicsAgentPhoneContactRequirement(TypedDict, total=False): terms_and_conditions_url: str - website: Optional[AgentWebsiteContactParam] + website: Optional["AgentWebsiteContactParam"] class BasicsAgentWebhookContactRequirement(TypedDict, total=False): - website: Required[AgentWebsiteContactParam] + website: Required["AgentWebsiteContactParam"] brand_color: str description: str - email: Optional[AgentEmailContactParam] + email: Optional["AgentEmailContactParam"] hero_url: str logo_url: str - phone_number: Optional[AgentPhoneContactParam] + phone_number: Optional["AgentPhoneContactParam"] privacy_policy_url: str @@ -61,7 +55,7 @@ class BasicsAgentWebhookContactRequirement(TypedDict, total=False): class BasicsAgentProfileContactRequirement(TypedDict, total=False): - email: Required[AgentEmailContactParam] + email: Required["AgentEmailContactParam"] brand_color: str @@ -71,13 +65,13 @@ class BasicsAgentProfileContactRequirement(TypedDict, total=False): logo_url: str - phone_number: Optional[AgentPhoneContactParam] + phone_number: Optional["AgentPhoneContactParam"] privacy_policy_url: str terms_and_conditions_url: str - website: Optional[AgentWebsiteContactParam] + website: Optional["AgentWebsiteContactParam"] Basics: TypeAlias = Union[ @@ -92,6 +86,13 @@ class AgentConfigurationParam(TypedDict, total=False): At least one complete phone, website, or email contact is required. """ - campaign: Optional[AgentCampaignConfigurationParam] + campaign: Optional["AgentCampaignConfigurationParam"] + + testing: Optional["AgentTestingConfigurationParam"] - testing: Optional[AgentTestingConfigurationParam] + +from .agent_email_contact_param import AgentEmailContactParam +from .agent_phone_contact_param import AgentPhoneContactParam +from .agent_website_contact_param import AgentWebsiteContactParam +from .agent_testing_configuration_param import AgentTestingConfigurationParam +from .agent_campaign_configuration_param import AgentCampaignConfigurationParam diff --git a/src/telnyx/types/rcs/agent_create_params.py b/src/telnyx/types/rcs/agent_create_params.py index c6a7fd3dc..49c94911e 100644 --- a/src/telnyx/types/rcs/agent_create_params.py +++ b/src/telnyx/types/rcs/agent_create_params.py @@ -6,8 +6,6 @@ from typing_extensions import Required, Annotated, TypedDict from ..._utils import PropertyInfo -from .agent_use_case import AgentUseCase -from .agent_configuration_param import AgentConfigurationParam __all__ = ["AgentCreateParams"] @@ -15,11 +13,11 @@ class AgentCreateParams(TypedDict, total=False): brand_id: Required[str] - configuration: Required[AgentConfigurationParam] + configuration: Required["AgentConfigurationParam"] display_name: Required[str] - use_case: Required[AgentUseCase] + use_case: Required["AgentUseCase"] idempotency_key: Required[Annotated[str, PropertyInfo(alias="Idempotency-Key")]] @@ -30,3 +28,7 @@ class AgentCreateParams(TypedDict, total=False): When omitted, the agent inherits the brand profile. """ + + +from .agent_use_case import AgentUseCase +from .agent_configuration_param import AgentConfigurationParam diff --git a/src/telnyx/types/rcs/agent_launch_params.py b/src/telnyx/types/rcs/agent_launch_params.py index e67be2614..a76c1403b 100644 --- a/src/telnyx/types/rcs/agent_launch_params.py +++ b/src/telnyx/types/rcs/agent_launch_params.py @@ -6,9 +6,6 @@ from typing_extensions import Required, TypedDict from ..._types import SequenceNotStr -from .agent_interaction_param import AgentInteractionParam -from .agent_consent_configuration_param import AgentConsentConfigurationParam -from .agent_testing_configuration_param import AgentTestingConfigurationParam from .agent_campaign_configuration_param import AgentCampaignConfigurationParam __all__ = ["AgentLaunchParams", "Campaign"] @@ -17,14 +14,19 @@ class AgentLaunchParams(TypedDict, total=False): campaign: Required[Campaign] - testing: Required[AgentTestingConfigurationParam] + testing: Required["AgentTestingConfigurationParam"] class Campaign(AgentCampaignConfigurationParam, total=False): agent_overview: Required[str] # type: ignore - consent_settings: Required[AgentConsentConfigurationParam] # type: ignore + consent_settings: Required["AgentConsentConfigurationParam"] # type: ignore - interactions: Required[Iterable[AgentInteractionParam]] # type: ignore + interactions: Required[Iterable["AgentInteractionParam"]] # type: ignore message_examples: Required[SequenceNotStr[str]] # type: ignore + + +from .agent_interaction_param import AgentInteractionParam +from .agent_consent_configuration_param import AgentConsentConfigurationParam +from .agent_testing_configuration_param import AgentTestingConfigurationParam diff --git a/src/telnyx/types/rcs/agent_update_params.py b/src/telnyx/types/rcs/agent_update_params.py index 262150121..6fab9c977 100644 --- a/src/telnyx/types/rcs/agent_update_params.py +++ b/src/telnyx/types/rcs/agent_update_params.py @@ -4,14 +4,11 @@ from typing_extensions import TypedDict -from .agent_use_case import AgentUseCase -from .agent_configuration_param import AgentConfigurationParam - __all__ = ["AgentUpdateParams"] class AgentUpdateParams(TypedDict, total=False): - configuration: AgentConfigurationParam + configuration: "AgentConfigurationParam" display_name: str @@ -19,4 +16,8 @@ class AgentUpdateParams(TypedDict, total=False): profile_id: str - use_case: AgentUseCase + use_case: "AgentUseCase" + + +from .agent_use_case import AgentUseCase +from .agent_configuration_param import AgentConfigurationParam diff --git a/src/telnyx/types/rcs/brand_create_params.py b/src/telnyx/types/rcs/brand_create_params.py index 773e154b9..7a309eaf1 100644 --- a/src/telnyx/types/rcs/brand_create_params.py +++ b/src/telnyx/types/rcs/brand_create_params.py @@ -5,19 +5,13 @@ from typing import Dict, Optional from typing_extensions import Literal, Required, TypedDict -from .brand_address_param import BrandAddressParam from .brand_contact_param import BrandContactParam -from .brand_identifier_param import BrandIdentifierParam -from .brand_legal_entity_type import BrandLegalEntityType -from .brand_organization_type import BrandOrganizationType -from .ein_brand_identifier_param import EinBrandIdentifierParam -from .stock_symbol_brand_identifier_param import StockSymbolBrandIdentifierParam __all__ = ["BrandCreateParams", "Contacts", "ContactsBrand", "Identifiers"] class BrandCreateParams(TypedDict, total=False): - addresses: Required[Dict[str, BrandAddressParam]] + addresses: Required[Dict[str, "BrandAddressParam"]] contacts: Required[Contacts] """Named business contacts. Use the `brand` key for the required BRAND contact.""" @@ -31,11 +25,11 @@ class BrandCreateParams(TypedDict, total=False): brand's stock symbol. """ - legal_entity_type: Required[BrandLegalEntityType] + legal_entity_type: Required["BrandLegalEntityType"] legal_name: Required[str] - organization_type: Required[BrandOrganizationType] + organization_type: Required["BrandOrganizationType"] website_url: Required[str] @@ -50,18 +44,26 @@ class ContactsBrand(BrandContactParam, total=False): contact_type: Literal["BRAND"] # type: ignore -class Contacts(TypedDict, total=False, extra_items=BrandContactParam): # type: ignore[call-arg] +class Contacts(TypedDict, total=False, extra_items="BrandContactParam"): # type: ignore[call-arg] """Named business contacts. Use the `brand` key for the required BRAND contact.""" brand: Required[ContactsBrand] -class Identifiers(TypedDict, total=False, extra_items=BrandIdentifierParam): # type: ignore[call-arg] +class Identifiers(TypedDict, total=False, extra_items="BrandIdentifierParam"): # type: ignore[call-arg] """Named business identifiers. Use the `ein` key for the required EIN and `stock_symbol` for a public-profit brand's stock symbol. """ - ein: Required[EinBrandIdentifierParam] + ein: Required["EinBrandIdentifierParam"] + + stock_symbol: "StockSymbolBrandIdentifierParam" + - stock_symbol: StockSymbolBrandIdentifierParam +from .brand_address_param import BrandAddressParam +from .brand_contact_param import BrandContactParam +from .brand_legal_entity_type import BrandLegalEntityType +from .brand_organization_type import BrandOrganizationType +from .ein_brand_identifier_param import EinBrandIdentifierParam +from .stock_symbol_brand_identifier_param import StockSymbolBrandIdentifierParam diff --git a/src/telnyx/types/rcs/brand_identifier_param.py b/src/telnyx/types/rcs/brand_identifier_param.py index 46cc04e1c..8773adada 100644 --- a/src/telnyx/types/rcs/brand_identifier_param.py +++ b/src/telnyx/types/rcs/brand_identifier_param.py @@ -5,9 +5,9 @@ from typing import Union from typing_extensions import TypeAlias -from .ein_brand_identifier_param import EinBrandIdentifierParam -from .stock_symbol_brand_identifier_param import StockSymbolBrandIdentifierParam - __all__ = ["BrandIdentifierParam"] -BrandIdentifierParam: TypeAlias = Union[EinBrandIdentifierParam, StockSymbolBrandIdentifierParam] +BrandIdentifierParam: TypeAlias = Union["EinBrandIdentifierParam", "StockSymbolBrandIdentifierParam"] + +from .ein_brand_identifier_param import EinBrandIdentifierParam +from .stock_symbol_brand_identifier_param import StockSymbolBrandIdentifierParam diff --git a/src/telnyx/types/rcs/brand_update_params.py b/src/telnyx/types/rcs/brand_update_params.py index 6868e3998..5d441f2a1 100644 --- a/src/telnyx/types/rcs/brand_update_params.py +++ b/src/telnyx/types/rcs/brand_update_params.py @@ -5,19 +5,13 @@ from typing import Dict from typing_extensions import Literal, Required, TypedDict -from .brand_address_param import BrandAddressParam from .brand_contact_param import BrandContactParam -from .brand_identifier_param import BrandIdentifierParam -from .brand_legal_entity_type import BrandLegalEntityType -from .brand_organization_type import BrandOrganizationType -from .ein_brand_identifier_param import EinBrandIdentifierParam -from .stock_symbol_brand_identifier_param import StockSymbolBrandIdentifierParam __all__ = ["BrandUpdateParams", "Contacts", "ContactsBrand", "Identifiers"] class BrandUpdateParams(TypedDict, total=False): - addresses: Dict[str, BrandAddressParam] + addresses: Dict[str, "BrandAddressParam"] contacts: Contacts """Named business contacts. Use the `brand` key for the required BRAND contact.""" @@ -31,11 +25,11 @@ class BrandUpdateParams(TypedDict, total=False): brand's stock symbol. """ - legal_entity_type: BrandLegalEntityType + legal_entity_type: "BrandLegalEntityType" legal_name: str - organization_type: BrandOrganizationType + organization_type: "BrandOrganizationType" profile_id: str @@ -46,18 +40,26 @@ class ContactsBrand(BrandContactParam, total=False): contact_type: Literal["BRAND"] # type: ignore -class Contacts(TypedDict, total=False, extra_items=BrandContactParam): # type: ignore[call-arg] +class Contacts(TypedDict, total=False, extra_items="BrandContactParam"): # type: ignore[call-arg] """Named business contacts. Use the `brand` key for the required BRAND contact.""" brand: Required[ContactsBrand] -class Identifiers(TypedDict, total=False, extra_items=BrandIdentifierParam): # type: ignore[call-arg] +class Identifiers(TypedDict, total=False, extra_items="BrandIdentifierParam"): # type: ignore[call-arg] """Named business identifiers. Use the `ein` key for the required EIN and `stock_symbol` for a public-profit brand's stock symbol. """ - ein: Required[EinBrandIdentifierParam] + ein: Required["EinBrandIdentifierParam"] + + stock_symbol: "StockSymbolBrandIdentifierParam" + - stock_symbol: StockSymbolBrandIdentifierParam +from .brand_address_param import BrandAddressParam +from .brand_contact_param import BrandContactParam +from .brand_legal_entity_type import BrandLegalEntityType +from .brand_organization_type import BrandOrganizationType +from .ein_brand_identifier_param import EinBrandIdentifierParam +from .stock_symbol_brand_identifier_param import StockSymbolBrandIdentifierParam diff --git a/src/telnyx/types/rcs_agent_message_param.py b/src/telnyx/types/rcs_agent_message_param.py index 7cd73efab..8254d460d 100644 --- a/src/telnyx/types/rcs_agent_message_param.py +++ b/src/telnyx/types/rcs_agent_message_param.py @@ -7,9 +7,6 @@ from typing_extensions import Literal, Required, Annotated, TypedDict from .._utils import PropertyInfo -from .rcs_suggestion_param import RcsSuggestionParam -from .rcs_card_content_param import RcsCardContentParam -from .rcs_content_info_param import RcsContentInfoParam __all__ = [ "RcsAgentMessageParam", @@ -24,7 +21,7 @@ class ContentMessageRichCardCarouselCard(TypedDict, total=False): """Carousel of cards.""" - card_contents: Required[Iterable[RcsCardContentParam]] + card_contents: Required[Iterable["RcsCardContentParam"]] """The list of contents for each card in the carousel. A carousel can have a minimum of 2 cards and a maximum 10 cards. @@ -37,7 +34,7 @@ class ContentMessageRichCardCarouselCard(TypedDict, total=False): class ContentMessageRichCardStandaloneCard(TypedDict, total=False): """Standalone card""" - card_content: Required[RcsCardContentParam] + card_content: Required["RcsCardContentParam"] card_orientation: Required[Literal["CARD_ORIENTATION_UNSPECIFIED", "HORIZONTAL", "VERTICAL"]] """Orientation of the card.""" @@ -55,11 +52,11 @@ class ContentMessageRichCard(TypedDict, total=False): class ContentMessage(TypedDict, total=False): - content_info: RcsContentInfoParam + content_info: "RcsContentInfoParam" rich_card: ContentMessageRichCard - suggestions: Iterable[RcsSuggestionParam] + suggestions: Iterable["RcsSuggestionParam"] """List of suggested actions and replies""" text: str @@ -83,3 +80,8 @@ class RcsAgentMessageParam(TypedDict, total=False): ttl: str """Duration in seconds ending with 's'""" + + +from .rcs_suggestion_param import RcsSuggestionParam +from .rcs_card_content_param import RcsCardContentParam +from .rcs_content_info_param import RcsContentInfoParam diff --git a/src/telnyx/types/rcs_card_content_param.py b/src/telnyx/types/rcs_card_content_param.py index 7077505a7..3f42426f3 100644 --- a/src/telnyx/types/rcs_card_content_param.py +++ b/src/telnyx/types/rcs_card_content_param.py @@ -5,16 +5,13 @@ from typing import Iterable from typing_extensions import Literal, TypedDict -from .rcs_suggestion_param import RcsSuggestionParam -from .rcs_content_info_param import RcsContentInfoParam - __all__ = ["RcsCardContentParam", "Media"] class Media(TypedDict, total=False): """A media file within a rich card.""" - content_info: RcsContentInfoParam + content_info: "RcsContentInfoParam" height: Literal["HEIGHT_UNSPECIFIED", "SHORT", "MEDIUM", "TALL"] """The height of the media within a rich card with a vertical layout. @@ -31,8 +28,12 @@ class RcsCardContentParam(TypedDict, total=False): media: Media """A media file within a rich card.""" - suggestions: Iterable[RcsSuggestionParam] + suggestions: Iterable["RcsSuggestionParam"] """List of suggestions to include in the card. Maximum 10 suggestions.""" title: str """Title of the card (at most 200 characters)""" + + +from .rcs_suggestion_param import RcsSuggestionParam +from .rcs_content_info_param import RcsContentInfoParam diff --git a/src/telnyx/types/requirement_list_params.py b/src/telnyx/types/requirement_list_params.py index 22e603e30..5dc4e74bc 100644 --- a/src/telnyx/types/requirement_list_params.py +++ b/src/telnyx/types/requirement_list_params.py @@ -60,5 +60,5 @@ class Filter(TypedDict, total=False): code """ - phone_number_type: Literal["local", "national", "toll_free"] + phone_number_type: Literal["local", "mobile", "multipurpose", "national", "shared_cost", "toll_free"] """Filters results to those applying to a specific phone_number_type""" diff --git a/src/telnyx/types/room_composition_create_params.py b/src/telnyx/types/room_composition_create_params.py index fcd3a110f..04a173530 100644 --- a/src/telnyx/types/room_composition_create_params.py +++ b/src/telnyx/types/room_composition_create_params.py @@ -5,8 +5,6 @@ from typing import Dict from typing_extensions import TypedDict -from .video_region_param import VideoRegionParam - __all__ = ["RoomCompositionCreateParams"] @@ -24,7 +22,7 @@ class RoomCompositionCreateParams(TypedDict, total=False): session_id: str """id of the room session associated with the room composition.""" - video_layout: Dict[str, VideoRegionParam] + video_layout: Dict[str, "VideoRegionParam"] """Describes the video layout of the room composition in terms of regions.""" webhook_event_failover_url: str @@ -41,3 +39,6 @@ class RoomCompositionCreateParams(TypedDict, total=False): webhook_timeout_secs: int """Specifies how many seconds to wait before timing out a webhook.""" + + +from .video_region_param import VideoRegionParam diff --git a/src/telnyx/types/shared_params/book_appointment_tool.py b/src/telnyx/types/shared_params/book_appointment_tool.py index e0e765ad1..67c46a5a0 100644 --- a/src/telnyx/types/shared_params/book_appointment_tool.py +++ b/src/telnyx/types/shared_params/book_appointment_tool.py @@ -4,12 +4,13 @@ from typing_extensions import Literal, Required, TypedDict -from .book_appointment_tool_params import BookAppointmentToolParams - __all__ = ["BookAppointmentTool"] class BookAppointmentTool(TypedDict, total=False): - book_appointment: Required[BookAppointmentToolParams] + book_appointment: Required["BookAppointmentToolParams"] type: Required[Literal["book_appointment"]] + + +from .book_appointment_tool_params import BookAppointmentToolParams diff --git a/src/telnyx/types/shared_params/call_control_retrieval_tool.py b/src/telnyx/types/shared_params/call_control_retrieval_tool.py index 708cad478..6ab3a6a41 100644 --- a/src/telnyx/types/shared_params/call_control_retrieval_tool.py +++ b/src/telnyx/types/shared_params/call_control_retrieval_tool.py @@ -4,12 +4,13 @@ from typing_extensions import Literal, Required, TypedDict -from .call_control_bucket_ids import CallControlBucketIDs - __all__ = ["CallControlRetrievalTool"] class CallControlRetrievalTool(TypedDict, total=False): - retrieval: Required[CallControlBucketIDs] + retrieval: Required["CallControlBucketIDs"] type: Required[Literal["retrieval"]] + + +from .call_control_bucket_ids import CallControlBucketIDs diff --git a/src/telnyx/types/shared_params/check_availability_tool.py b/src/telnyx/types/shared_params/check_availability_tool.py index 3eec0b7a7..64ada3969 100644 --- a/src/telnyx/types/shared_params/check_availability_tool.py +++ b/src/telnyx/types/shared_params/check_availability_tool.py @@ -4,12 +4,13 @@ from typing_extensions import Literal, Required, TypedDict -from .check_availability_tool_params import CheckAvailabilityToolParams - __all__ = ["CheckAvailabilityTool"] class CheckAvailabilityTool(TypedDict, total=False): - check_availability: Required[CheckAvailabilityToolParams] + check_availability: Required["CheckAvailabilityToolParams"] type: Required[Literal["check_availability"]] + + +from .check_availability_tool_params import CheckAvailabilityToolParams diff --git a/src/telnyx/types/signature_payload_param.py b/src/telnyx/types/signature_payload_param.py new file mode 100644 index 000000000..ef5f700c4 --- /dev/null +++ b/src/telnyx/types/signature_payload_param.py @@ -0,0 +1,19 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Optional +from typing_extensions import Required, TypedDict + +__all__ = ["SignaturePayloadParam"] + + +class SignaturePayloadParam(TypedDict, total=False): + image_base64: Required[str] + """PNG image, base64-encoded.""" + + signer_name: Optional[str] + """Optional. + + When absent the rendered PDF falls back to the enterprise contact's legal name. + """ diff --git a/src/telnyx/types/sim_card_update_params.py b/src/telnyx/types/sim_card_update_params.py index 8fff58992..a95c4b1d4 100644 --- a/src/telnyx/types/sim_card_update_params.py +++ b/src/telnyx/types/sim_card_update_params.py @@ -6,7 +6,6 @@ from typing_extensions import Literal, TypedDict from .._types import SequenceNotStr -from .shared_params.sim_card_status import SimCardStatus __all__ = ["SimCardUpdateParams", "DataLimit"] @@ -25,7 +24,7 @@ class SimCardUpdateParams(TypedDict, total=False): resource. """ - status: SimCardStatus + status: "SimCardStatus" tags: SequenceNotStr[str] """Searchable tags associated with the SIM card""" @@ -37,3 +36,6 @@ class DataLimit(TypedDict, total=False): amount: str unit: Literal["MB", "GB"] + + +from .shared_params.sim_card_status import SimCardStatus diff --git a/src/telnyx/types/speech_to_text_list_providers_params.py b/src/telnyx/types/speech_to_text_list_providers_params.py index 60db7504a..bbeea3cfd 100644 --- a/src/telnyx/types/speech_to_text_list_providers_params.py +++ b/src/telnyx/types/speech_to_text_list_providers_params.py @@ -4,8 +4,6 @@ from typing_extensions import Literal, TypedDict -from .stt_service_type import SttServiceType - __all__ = ["SpeechToTextListProvidersParams"] @@ -33,7 +31,7 @@ class SpeechToTextListProvidersParams(TypedDict, total=False): type will return an empty `data` array rather than an error. """ - service_type: SttServiceType + service_type: "SttServiceType" """Filter to entries that support the given service type. For backward compatibility with the values that briefly shipped before the @@ -42,3 +40,6 @@ class SpeechToTextListProvidersParams(TypedDict, total=False): and normalized to `file_based`, `in_call`, and `ai_assistant` respectively. The response always emits the canonical (post-rename) values. """ + + +from .stt_service_type import SttServiceType diff --git a/src/telnyx/types/spend_limit.py b/src/telnyx/types/spend_limit.py new file mode 100644 index 000000000..2943af686 --- /dev/null +++ b/src/telnyx/types/spend_limit.py @@ -0,0 +1,145 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Optional +from datetime import date, datetime +from typing_extensions import Literal + +from .._models import BaseModel +from .spend_limit_period import SpendLimitPeriod + +__all__ = ["SpendLimit", "Block", "Limit", "Evaluation"] + + +class Block(BaseModel): + """The active block of the period. `null` when the period is not blocked.""" + + blocked_until: date + """ + Exclusive end of the block: it is lifted at 00:00 UTC on this date at the + latest. + """ + + detected_at: datetime + """When the block started.""" + + limit_usd: str + """The limit in USD that the spend went above, as a decimal string.""" + + spend_usd: str + """Spend in USD when the block started, as a decimal string.""" + + +class Limit(BaseModel): + """The limit set on the account for the product and period, whoever set it. + + `null` when none is set. + """ + + amount: Optional[str] = None + """Limit in USD, as a decimal string. `null` when `unlimited` is true.""" + + origin: Literal["self_service", "operator"] + """ + `self_service` when a user of the account set it, `operator` when Telnyx support + did. + """ + + unlimited: bool + """True when the limit was set to explicitly no cap.""" + + updated_at: datetime + """When the limit was last set or changed.""" + + +class Evaluation(BaseModel): + """What a create, update or delete did to the period at once. + + Only present in write responses. + """ + + blocked_now: bool + """The change blocked the product: the spend was already above the new limit.""" + + evaluation_deferred: bool + """The spend could not be checked now. + + The change is saved and applied within a few minutes. + """ + + released: bool + """The change lifted a block of this period.""" + + spend_usd: Optional[str] = None + """Spend in USD used for the check, as a decimal string. + + `null` when the spend was not checked. + """ + + still_blocked_other_period: bool + """ + The other period has an active block, so the product stays blocked whatever this + period's result. + """ + + still_over_limit: bool + """A block of this period remains because the spend is still above the new limit.""" + + note: Optional[str] = None + """Additional information about the result, when there is any.""" + + +class SpendLimit(BaseModel): + """The spend limit, spend and block state of one product and period.""" + + block: Optional[Block] = None + """The active block of the period. `null` when the period is not blocked.""" + + blocked: bool + """The product is blocked for this period. + + Always `false` in write responses; list the limits to read the block state. + """ + + effective_limit_usd: Optional[str] = None + """The limit in USD that is enforced, as a decimal string. `null` means unlimited.""" + + limit: Optional[Limit] = None + """The limit set on the account for the product and period, whoever set it. + + `null` when none is set. + """ + + period: SpendLimitPeriod + """`daily` is the current UTC day; `monthly` is the current UTC calendar month.""" + + period_end: date + """Exclusive end of the current period, a UTC date.""" + + period_start: date + """First UTC day of the current period.""" + + product: str + """Product the entry applies to.""" + + product_name: str + """Display name of the product.""" + + record_type: str + """Identifies the type of the resource.""" + + spend_error: Optional[str] = None + """Set when `spend_usd` is `null`.""" + + spend_usd: Optional[str] = None + """Spend in USD so far in the period, as a decimal string. + + It can lag actual usage by about a minute. `null` when it could not be read. + """ + + evaluation: Optional[Evaluation] = None + """What a create, update or delete did to the period at once. + + Only present in write responses. + """ diff --git a/src/telnyx/types/spend_limit_create_params.py b/src/telnyx/types/spend_limit_create_params.py new file mode 100644 index 000000000..8c1b3048b --- /dev/null +++ b/src/telnyx/types/spend_limit_create_params.py @@ -0,0 +1,44 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Union +from typing_extensions import Literal, Required, TypeAlias, TypedDict + +__all__ = ["SpendLimitCreateParams", "CreateSpendLimitWithAmount", "CreateSpendLimitUnlimited"] + + +class CreateSpendLimitWithAmount(TypedDict, total=False): + amount: Required[float] + """Limit in USD. `0` blocks at the first cent of spend.""" + + product: Required[str] + """Product to limit, as returned in `product` by the list operation.""" + + period: "SpendLimitPeriod" + """`daily` is the current UTC day; `monthly` is the current UTC calendar month.""" + + reason: str + """Why the limit is set or changed, kept for audit.""" + + unlimited: Literal[False] + """Optional; only `false` is allowed together with `amount`.""" + + +class CreateSpendLimitUnlimited(TypedDict, total=False): + product: Required[str] + """Product to limit, as returned in `product` by the list operation.""" + + unlimited: Required[Literal[True]] + """`true`: explicitly no cap.""" + + period: "SpendLimitPeriod" + """`daily` is the current UTC day; `monthly` is the current UTC calendar month.""" + + reason: str + """Why the limit is set or changed, kept for audit.""" + + +SpendLimitCreateParams: TypeAlias = Union[CreateSpendLimitWithAmount, CreateSpendLimitUnlimited] + +from .spend_limit_period import SpendLimitPeriod diff --git a/src/telnyx/types/spend_limit_delete_params.py b/src/telnyx/types/spend_limit_delete_params.py new file mode 100644 index 000000000..2b3b501ee --- /dev/null +++ b/src/telnyx/types/spend_limit_delete_params.py @@ -0,0 +1,18 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import TypedDict + +__all__ = ["SpendLimitDeleteParams"] + + +class SpendLimitDeleteParams(TypedDict, total=False): + period: "SpendLimitPeriod" + """Limit period. Defaults to `daily`; send it explicitly.""" + + reason: str + """Why the limit is removed, kept for audit. At most 500 characters.""" + + +from .spend_limit_period import SpendLimitPeriod diff --git a/src/telnyx/types/spend_limit_list_response.py b/src/telnyx/types/spend_limit_list_response.py new file mode 100644 index 000000000..0dad3a192 --- /dev/null +++ b/src/telnyx/types/spend_limit_list_response.py @@ -0,0 +1,26 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import List, Optional + +from .._models import BaseModel +from .spend_limit import SpendLimit + +__all__ = ["SpendLimitListResponse", "Meta"] + + +class Meta(BaseModel): + page_number: Optional[int] = None + + page_size: Optional[int] = None + + total_pages: Optional[int] = None + + total_results: Optional[int] = None + + +class SpendLimitListResponse(BaseModel): + data: List[SpendLimit] + + meta: Optional[Meta] = None diff --git a/src/telnyx/types/spend_limit_period.py b/src/telnyx/types/spend_limit_period.py new file mode 100644 index 000000000..82ea3a744 --- /dev/null +++ b/src/telnyx/types/spend_limit_period.py @@ -0,0 +1,9 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal, TypeAlias + +__all__ = ["SpendLimitPeriod"] + +SpendLimitPeriod: TypeAlias = Literal["daily", "monthly"] diff --git a/src/telnyx/types/spend_limit_response.py b/src/telnyx/types/spend_limit_response.py new file mode 100644 index 000000000..6d6df8310 --- /dev/null +++ b/src/telnyx/types/spend_limit_response.py @@ -0,0 +1,13 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from .._models import BaseModel +from .spend_limit import SpendLimit + +__all__ = ["SpendLimitResponse"] + + +class SpendLimitResponse(BaseModel): + data: SpendLimit + """The spend limit, spend and block state of one product and period.""" diff --git a/src/telnyx/types/spend_limit_update_params.py b/src/telnyx/types/spend_limit_update_params.py new file mode 100644 index 000000000..0d0251be2 --- /dev/null +++ b/src/telnyx/types/spend_limit_update_params.py @@ -0,0 +1,38 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Union +from typing_extensions import Literal, Required, TypeAlias, TypedDict + +__all__ = ["SpendLimitUpdateParams", "UpdateSpendLimitWithAmount", "UpdateSpendLimitUnlimited"] + + +class UpdateSpendLimitWithAmount(TypedDict, total=False): + amount: Required[float] + """Limit in USD. `0` blocks at the first cent of spend.""" + + period: "SpendLimitPeriod" + """Limit period. Defaults to `daily`; send it explicitly.""" + + reason: str + """Why the limit is set or changed, kept for audit.""" + + unlimited: Literal[False] + """Optional; only `false` is allowed together with `amount`.""" + + +class UpdateSpendLimitUnlimited(TypedDict, total=False): + unlimited: Required[Literal[True]] + """`true`: explicitly no cap.""" + + period: "SpendLimitPeriod" + """Limit period. Defaults to `daily`; send it explicitly.""" + + reason: str + """Why the limit is set or changed, kept for audit.""" + + +SpendLimitUpdateParams: TypeAlias = Union[UpdateSpendLimitWithAmount, UpdateSpendLimitUnlimited] + +from .spend_limit_period import SpendLimitPeriod diff --git a/src/telnyx/types/sub_number_order_update_params.py b/src/telnyx/types/sub_number_order_update_params.py index cf514df80..a29246320 100644 --- a/src/telnyx/types/sub_number_order_update_params.py +++ b/src/telnyx/types/sub_number_order_update_params.py @@ -5,10 +5,11 @@ from typing import Iterable from typing_extensions import TypedDict -from .update_regulatory_requirement_param import UpdateRegulatoryRequirementParam - __all__ = ["SubNumberOrderUpdateParams"] class SubNumberOrderUpdateParams(TypedDict, total=False): - regulatory_requirements: Iterable[UpdateRegulatoryRequirementParam] + regulatory_requirements: Iterable["UpdateRegulatoryRequirementParam"] + + +from .update_regulatory_requirement_param import UpdateRegulatoryRequirementParam diff --git a/src/telnyx/types/terms_of_service/agreement_list_params.py b/src/telnyx/types/terms_of_service/agreement_list_params.py index 7ad6386c0..6244ce581 100644 --- a/src/telnyx/types/terms_of_service/agreement_list_params.py +++ b/src/telnyx/types/terms_of_service/agreement_list_params.py @@ -5,7 +5,6 @@ from typing_extensions import Annotated, TypedDict from ..._utils import PropertyInfo -from .tos_product_type import TosProductType __all__ = ["AgreementListParams"] @@ -20,9 +19,12 @@ class AgreementListParams(TypedDict, total=False): page_size: Annotated[int, PropertyInfo(alias="page[size]")] """Items per page. Maximum 250; values above are clamped to 250.""" - product_type: TosProductType + product_type: "TosProductType" """Optional filter. Omit to list the user's agreements for **every** product (branded_calling and number_reputation); pass a value to return only that product's agreements. """ + + +from .tos_product_type import TosProductType diff --git a/src/telnyx/types/terms_of_service/tos_agreement.py b/src/telnyx/types/terms_of_service/tos_agreement.py index f644d0d2d..658c61e96 100644 --- a/src/telnyx/types/terms_of_service/tos_agreement.py +++ b/src/telnyx/types/terms_of_service/tos_agreement.py @@ -18,15 +18,19 @@ class TosAgreement(BaseModel): """ id: Optional[str] = None + """The unique identifier of this recorded agreement.""" agreed_at: Optional[datetime] = None + """When you accepted this version of the terms.""" created_at: Optional[datetime] = None + """When this agreement record was created.""" product_type: Optional[TosProductType] = None """Telnyx product the Terms of Service apply to.""" terms_version: Optional[str] = None + """The version of the terms you accepted.""" version: Optional[str] = None """Convenience alias of `terms_version`. Both keys are present on every response.""" diff --git a/src/telnyx/types/terms_of_service_retrieve_info_params.py b/src/telnyx/types/terms_of_service_retrieve_info_params.py index 437a56738..c69b03295 100644 --- a/src/telnyx/types/terms_of_service_retrieve_info_params.py +++ b/src/telnyx/types/terms_of_service_retrieve_info_params.py @@ -4,11 +4,12 @@ from typing_extensions import TypedDict -from .terms_of_service.tos_product_type import TosProductType - __all__ = ["TermsOfServiceRetrieveInfoParams"] class TermsOfServiceRetrieveInfoParams(TypedDict, total=False): - product_type: TosProductType + product_type: "TosProductType" """Optional product filter. Omit to return info for all products.""" + + +from .terms_of_service.tos_product_type import TosProductType diff --git a/src/telnyx/types/terms_of_service_retrieve_info_response.py b/src/telnyx/types/terms_of_service_retrieve_info_response.py index c899bc41f..0a801c9cf 100644 --- a/src/telnyx/types/terms_of_service_retrieve_info_response.py +++ b/src/telnyx/types/terms_of_service_retrieve_info_response.py @@ -13,15 +13,19 @@ class Agreement(BaseModel): current_version: Optional[str] = None + """The latest published version of these terms.""" description: Optional[str] = None + """A short summary of the product these terms cover.""" effective_date: Optional[date] = None + """The date this version took effect.""" product_type: Optional[TosProductType] = None """Telnyx product the Terms of Service apply to.""" terms_url: Optional[str] = None + """A link to the full terms text.""" class TermsOfServiceRetrieveInfoResponse(BaseModel): diff --git a/src/telnyx/types/terms_of_service_retrieve_status_params.py b/src/telnyx/types/terms_of_service_retrieve_status_params.py index 099d114a6..acd35a84b 100644 --- a/src/telnyx/types/terms_of_service_retrieve_status_params.py +++ b/src/telnyx/types/terms_of_service_retrieve_status_params.py @@ -4,11 +4,12 @@ from typing_extensions import TypedDict -from .terms_of_service.tos_product_type import TosProductType - __all__ = ["TermsOfServiceRetrieveStatusParams"] class TermsOfServiceRetrieveStatusParams(TypedDict, total=False): - product_type: TosProductType + product_type: "TosProductType" """Which product's ToS to check. Defaults to `branded_calling`.""" + + +from .terms_of_service.tos_product_type import TosProductType diff --git a/src/telnyx/types/terms_of_service_retrieve_status_response.py b/src/telnyx/types/terms_of_service_retrieve_status_response.py index aeefc195c..905e51cd5 100644 --- a/src/telnyx/types/terms_of_service_retrieve_status_response.py +++ b/src/telnyx/types/terms_of_service_retrieve_status_response.py @@ -33,6 +33,7 @@ class Data(BaseModel): """Telnyx product the Terms of Service apply to.""" agreed_at: Optional[datetime] = None + """When you accepted the terms, or null if you have not.""" agreed_version: Optional[str] = None """ diff --git a/src/telnyx/types/texml_application_create_params.py b/src/telnyx/types/texml_application_create_params.py index 37e621a02..314d799a0 100644 --- a/src/telnyx/types/texml_application_create_params.py +++ b/src/telnyx/types/texml_application_create_params.py @@ -5,8 +5,6 @@ from typing_extensions import Literal, Required, TypedDict from .._types import SequenceNotStr -from .dtmf_type import DtmfType -from .anchorsite_override import AnchorsiteOverride __all__ = ["TexmlApplicationCreateParams", "Inbound", "Outbound"] @@ -21,7 +19,7 @@ class TexmlApplicationCreateParams(TypedDict, total=False): active: bool """Specifies whether the connection can be used.""" - anchorsite_override: AnchorsiteOverride + anchorsite_override: "AnchorsiteOverride" """ `Latency` directs Telnyx to route media through the site with the lowest round-trip time to the user's connection. Telnyx calculates this time using ICMP @@ -31,7 +29,7 @@ class TexmlApplicationCreateParams(TypedDict, total=False): call_cost_in_webhooks: bool """Specifies if call cost webhooks should be sent for this TeXML Application.""" - dtmf_type: DtmfType + dtmf_type: "DtmfType" """Sets the type of DTMF digits sent from Telnyx to this Connection. Note that DTMF digits sent to Telnyx will be accepted in all formats. @@ -115,3 +113,7 @@ class Outbound(TypedDict, total=False): outbound_voice_profile_id: str """Identifies the associated outbound voice profile.""" + + +from .dtmf_type import DtmfType +from .anchorsite_override import AnchorsiteOverride diff --git a/src/telnyx/types/texml_application_update_params.py b/src/telnyx/types/texml_application_update_params.py index c37631a7a..c54d29454 100644 --- a/src/telnyx/types/texml_application_update_params.py +++ b/src/telnyx/types/texml_application_update_params.py @@ -5,8 +5,6 @@ from typing_extensions import Literal, Required, TypedDict from .._types import SequenceNotStr -from .dtmf_type import DtmfType -from .anchorsite_override import AnchorsiteOverride __all__ = ["TexmlApplicationUpdateParams", "Inbound", "Outbound"] @@ -21,7 +19,7 @@ class TexmlApplicationUpdateParams(TypedDict, total=False): active: bool """Specifies whether the connection can be used.""" - anchorsite_override: AnchorsiteOverride + anchorsite_override: "AnchorsiteOverride" """ `Latency` directs Telnyx to route media through the site with the lowest round-trip time to the user's connection. Telnyx calculates this time using ICMP @@ -31,7 +29,7 @@ class TexmlApplicationUpdateParams(TypedDict, total=False): call_cost_in_webhooks: bool """Specifies if call cost webhooks should be sent for this TeXML Application.""" - dtmf_type: DtmfType + dtmf_type: "DtmfType" """Sets the type of DTMF digits sent from Telnyx to this Connection. Note that DTMF digits sent to Telnyx will be accepted in all formats. @@ -115,3 +113,7 @@ class Outbound(TypedDict, total=False): outbound_voice_profile_id: str """Identifies the associated outbound voice profile.""" + + +from .dtmf_type import DtmfType +from .anchorsite_override import AnchorsiteOverride diff --git a/src/telnyx/types/text_to_speech_generate_speech_params.py b/src/telnyx/types/text_to_speech_generate_speech_params.py index ee065ab8f..b242c8e86 100644 --- a/src/telnyx/types/text_to_speech_generate_speech_params.py +++ b/src/telnyx/types/text_to_speech_generate_speech_params.py @@ -268,8 +268,9 @@ class Telnyx(TypedDict, total=False): voice_speed: float """Voice speed multiplier. - Applies to all models except `Bayan` and `Sukhan`, which don't support it. - Range: 0.5 to 2.0. + Telnyx `Ultra` voices accept values from 0.6 to 1.5 — requests outside that + range are rejected by the synthesis engine. `KokoroTTS` and `Qwen3TTS` accept + the field but do not apply it. `Bayan` and `Sukhan` don't support it. """ volume: float diff --git a/src/telnyx/types/uac_connection_create_params.py b/src/telnyx/types/uac_connection_create_params.py index b23906b7b..cc3697433 100644 --- a/src/telnyx/types/uac_connection_create_params.py +++ b/src/telnyx/types/uac_connection_create_params.py @@ -6,17 +6,6 @@ from typing_extensions import Literal, Required, TypedDict from .._types import SequenceNotStr -from .dtmf_type import DtmfType -from .encrypted_media import EncryptedMedia -from .uac_outbound_param import UacOutboundParam -from .anchorsite_override import AnchorsiteOverride -from .uac_inbound_request_param import UacInboundRequestParam -from .uac_external_settings_param import UacExternalSettingsParam -from .uac_internal_settings_param import UacInternalSettingsParam -from .connection_noise_suppression import ConnectionNoiseSuppression -from .connection_rtcp_settings_param import ConnectionRtcpSettingsParam -from .shared_params.connection_jitter_buffer import ConnectionJitterBuffer -from .shared_params.connection_noise_suppression_details import ConnectionNoiseSuppressionDetails __all__ = ["UacConnectionCreateParams"] @@ -28,7 +17,7 @@ class UacConnectionCreateParams(TypedDict, total=False): active: bool """Defaults to true""" - anchorsite_override: AnchorsiteOverride + anchorsite_override: "AnchorsiteOverride" """ `Latency` directs Telnyx to route media through the site with the lowest round-trip time to the user's connection. Telnyx calculates this time using ICMP @@ -49,7 +38,7 @@ class UacConnectionCreateParams(TypedDict, total=False): RTP timeout. """ - dtmf_type: DtmfType + dtmf_type: "DtmfType" """Sets the type of DTMF digits sent from Telnyx to this Connection. Note that DTMF digits sent to Telnyx will be accepted in all formats. @@ -61,19 +50,19 @@ class UacConnectionCreateParams(TypedDict, total=False): scenarios. """ - encrypted_media: Optional[EncryptedMedia] + encrypted_media: Optional["EncryptedMedia"] """Enable use of SRTP for encryption. Cannot be set if the transport_portocol is TLS. """ - external_uac_settings: UacExternalSettingsParam + external_uac_settings: "UacExternalSettingsParam" """ External SIP peer settings used by Telnyx when registering to your PBX and routing outbound calls. """ - inbound: UacInboundRequestParam + inbound: "UacInboundRequestParam" """Inbound settings that can be supplied when creating or updating a UAC connection. @@ -81,13 +70,13 @@ class UacConnectionCreateParams(TypedDict, total=False): Telnyx and are not accepted as request parameters. """ - internal_uac_settings: UacInternalSettingsParam + internal_uac_settings: "UacInternalSettingsParam" """Internal Telnyx-side settings for a UAC connection.""" ios_push_credential_id: Optional[str] """The uuid of the push credential for Ios""" - jitter_buffer: ConnectionJitterBuffer + jitter_buffer: "ConnectionJitterBuffer" """Configuration options for Jitter Buffer. Enables Jitter Buffer for RTP streams of SIP Trunking calls. The feature is off @@ -96,7 +85,7 @@ class UacConnectionCreateParams(TypedDict, total=False): smaller values reduce latency but are more sensitive to jitter and reordering. """ - noise_suppression: ConnectionNoiseSuppression + noise_suppression: "ConnectionNoiseSuppression" """Controls when noise suppression is applied to calls. When set to 'inbound', noise suppression is applied to incoming audio. When set @@ -104,7 +93,7 @@ class UacConnectionCreateParams(TypedDict, total=False): in both directions. When set to 'disabled', noise suppression is turned off. """ - noise_suppression_details: ConnectionNoiseSuppressionDetails + noise_suppression_details: "ConnectionNoiseSuppressionDetails" """Configuration options for noise suppression. These settings are stored regardless of the noise_suppression value, but only @@ -120,7 +109,7 @@ class UacConnectionCreateParams(TypedDict, total=False): use T38 on just one leg of the call depending on each leg's settings. """ - outbound: UacOutboundParam + outbound: "UacOutboundParam" password: str """The password to be used as part of the credentials. @@ -128,7 +117,7 @@ class UacConnectionCreateParams(TypedDict, total=False): Must be 8 to 128 characters long. """ - rtcp_settings: ConnectionRtcpSettingsParam + rtcp_settings: "ConnectionRtcpSettingsParam" sip_uri_calling_preference: Literal["disabled", "unrestricted", "internal"] """This feature enables inbound SIP URI calls to your Credential Auth Connection. @@ -170,3 +159,16 @@ class UacConnectionCreateParams(TypedDict, total=False): webhook_timeout_secs: Optional[int] """Specifies how many seconds to wait before timing out a webhook.""" + + +from .dtmf_type import DtmfType +from .encrypted_media import EncryptedMedia +from .uac_outbound_param import UacOutboundParam +from .anchorsite_override import AnchorsiteOverride +from .uac_inbound_request_param import UacInboundRequestParam +from .uac_external_settings_param import UacExternalSettingsParam +from .uac_internal_settings_param import UacInternalSettingsParam +from .connection_noise_suppression import ConnectionNoiseSuppression +from .connection_rtcp_settings_param import ConnectionRtcpSettingsParam +from .shared_params.connection_jitter_buffer import ConnectionJitterBuffer +from .shared_params.connection_noise_suppression_details import ConnectionNoiseSuppressionDetails diff --git a/src/telnyx/types/uac_connection_update_params.py b/src/telnyx/types/uac_connection_update_params.py index f9fb148b4..c4a32dca8 100644 --- a/src/telnyx/types/uac_connection_update_params.py +++ b/src/telnyx/types/uac_connection_update_params.py @@ -6,17 +6,6 @@ from typing_extensions import Literal, TypedDict from .._types import SequenceNotStr -from .dtmf_type import DtmfType -from .encrypted_media import EncryptedMedia -from .uac_outbound_param import UacOutboundParam -from .anchorsite_override import AnchorsiteOverride -from .uac_inbound_request_param import UacInboundRequestParam -from .uac_external_settings_param import UacExternalSettingsParam -from .uac_internal_settings_param import UacInternalSettingsParam -from .connection_noise_suppression import ConnectionNoiseSuppression -from .connection_rtcp_settings_param import ConnectionRtcpSettingsParam -from .shared_params.connection_jitter_buffer import ConnectionJitterBuffer -from .shared_params.connection_noise_suppression_details import ConnectionNoiseSuppressionDetails __all__ = ["UacConnectionUpdateParams"] @@ -25,7 +14,7 @@ class UacConnectionUpdateParams(TypedDict, total=False): active: bool """Defaults to true""" - anchorsite_override: AnchorsiteOverride + anchorsite_override: "AnchorsiteOverride" """ `Latency` directs Telnyx to route media through the site with the lowest round-trip time to the user's connection. Telnyx calculates this time using ICMP @@ -49,7 +38,7 @@ class UacConnectionUpdateParams(TypedDict, total=False): RTP timeout. """ - dtmf_type: DtmfType + dtmf_type: "DtmfType" """Sets the type of DTMF digits sent from Telnyx to this Connection. Note that DTMF digits sent to Telnyx will be accepted in all formats. @@ -61,19 +50,19 @@ class UacConnectionUpdateParams(TypedDict, total=False): scenarios. """ - encrypted_media: Optional[EncryptedMedia] + encrypted_media: Optional["EncryptedMedia"] """Enable use of SRTP for encryption. Cannot be set if the transport_portocol is TLS. """ - external_uac_settings: UacExternalSettingsParam + external_uac_settings: "UacExternalSettingsParam" """ External SIP peer settings used by Telnyx when registering to your PBX and routing outbound calls. """ - inbound: UacInboundRequestParam + inbound: "UacInboundRequestParam" """Inbound settings that can be supplied when creating or updating a UAC connection. @@ -81,13 +70,13 @@ class UacConnectionUpdateParams(TypedDict, total=False): Telnyx and are not accepted as request parameters. """ - internal_uac_settings: UacInternalSettingsParam + internal_uac_settings: "UacInternalSettingsParam" """Internal Telnyx-side settings for a UAC connection.""" ios_push_credential_id: Optional[str] """The uuid of the push credential for Ios""" - jitter_buffer: ConnectionJitterBuffer + jitter_buffer: "ConnectionJitterBuffer" """Configuration options for Jitter Buffer. Enables Jitter Buffer for RTP streams of SIP Trunking calls. The feature is off @@ -96,7 +85,7 @@ class UacConnectionUpdateParams(TypedDict, total=False): smaller values reduce latency but are more sensitive to jitter and reordering. """ - noise_suppression: ConnectionNoiseSuppression + noise_suppression: "ConnectionNoiseSuppression" """Controls when noise suppression is applied to calls. When set to 'inbound', noise suppression is applied to incoming audio. When set @@ -104,7 +93,7 @@ class UacConnectionUpdateParams(TypedDict, total=False): in both directions. When set to 'disabled', noise suppression is turned off. """ - noise_suppression_details: ConnectionNoiseSuppressionDetails + noise_suppression_details: "ConnectionNoiseSuppressionDetails" """Configuration options for noise suppression. These settings are stored regardless of the noise_suppression value, but only @@ -120,7 +109,7 @@ class UacConnectionUpdateParams(TypedDict, total=False): use T38 on just one leg of the call depending on each leg's settings. """ - outbound: UacOutboundParam + outbound: "UacOutboundParam" password: str """The password to be used as part of the credentials. @@ -128,7 +117,7 @@ class UacConnectionUpdateParams(TypedDict, total=False): Must be 8 to 128 characters long. """ - rtcp_settings: ConnectionRtcpSettingsParam + rtcp_settings: "ConnectionRtcpSettingsParam" sip_uri_calling_preference: Literal["disabled", "unrestricted", "internal"] """This feature enables inbound SIP URI calls to your Credential Auth Connection. @@ -166,3 +155,16 @@ class UacConnectionUpdateParams(TypedDict, total=False): webhook_timeout_secs: Optional[int] """Specifies how many seconds to wait before timing out a webhook.""" + + +from .dtmf_type import DtmfType +from .encrypted_media import EncryptedMedia +from .uac_outbound_param import UacOutboundParam +from .anchorsite_override import AnchorsiteOverride +from .uac_inbound_request_param import UacInboundRequestParam +from .uac_external_settings_param import UacExternalSettingsParam +from .uac_internal_settings_param import UacInternalSettingsParam +from .connection_noise_suppression import ConnectionNoiseSuppression +from .connection_rtcp_settings_param import ConnectionRtcpSettingsParam +from .shared_params.connection_jitter_buffer import ConnectionJitterBuffer +from .shared_params.connection_noise_suppression_details import ConnectionNoiseSuppressionDetails diff --git a/src/telnyx/types/unsafe_unwrap_webhook_event.py b/src/telnyx/types/unsafe_unwrap_webhook_event.py index 6ff39948c..9dc256773 100644 --- a/src/telnyx/types/unsafe_unwrap_webhook_event.py +++ b/src/telnyx/types/unsafe_unwrap_webhook_event.py @@ -59,6 +59,7 @@ from .session_status_changed_webhook_event import SessionStatusChangedWebhookEvent from .call_conversation_ended_webhook_event import CallConversationEndedWebhookEvent from .conference_speak_started_webhook_event import ConferenceSpeakStartedWebhookEvent +from .call_conversation_created_webhook_event import CallConversationCreatedWebhookEvent from .conference_playback_ended_webhook_event import ConferencePlaybackEndedWebhookEvent from .hosted_number_order_event_webhook_event import HostedNumberOrderEventWebhookEvent from .conference_recording_saved_webhook_event import ConferenceRecordingSavedWebhookEvent @@ -79,7 +80,11 @@ from .conference_participant_speak_started_webhook_event import ConferenceParticipantSpeakStartedWebhookEvent from .conference_participant_playback_ended_webhook_event import ConferenceParticipantPlaybackEndedWebhookEvent from .call_ai_gather_message_history_updated_webhook_event import CallAIGatherMessageHistoryUpdatedWebhookEvent +from .call_machine_premium_detection_started_webhook_event import CallMachinePremiumDetectionStartedWebhookEvent from .conference_participant_playback_started_webhook_event import ConferenceParticipantPlaybackStartedWebhookEvent +from .call_machine_premium_call_screening_detected_webhook_event import ( + CallMachinePremiumCallScreeningDetectedWebhookEvent, +) __all__ = ["UnsafeUnwrapWebhookEvent"] @@ -91,6 +96,7 @@ ArtifactFailedWebhookEvent, CallAnsweredWebhookEvent, CallBridgedWebhookEvent, + CallConversationCreatedWebhookEvent, CallConversationEndedWebhookEvent, CallConversationInsightsGeneratedWebhookEvent, CallCostWebhookEvent, @@ -107,7 +113,9 @@ CallLeftQueueWebhookEvent, CallMachineDetectionEndedWebhookEvent, CallMachineGreetingEndedWebhookEvent, + CallMachinePremiumCallScreeningDetectedWebhookEvent, CallMachinePremiumDetectionEndedWebhookEvent, + CallMachinePremiumDetectionStartedWebhookEvent, CallMachinePremiumGreetingEndedWebhookEvent, CallPaymentCompletedWebhookEvent, CallPaymentProgressWebhookEvent, diff --git a/src/telnyx/types/unwrap_webhook_event.py b/src/telnyx/types/unwrap_webhook_event.py index d3faec93e..63cdb8e1e 100644 --- a/src/telnyx/types/unwrap_webhook_event.py +++ b/src/telnyx/types/unwrap_webhook_event.py @@ -59,6 +59,7 @@ from .session_status_changed_webhook_event import SessionStatusChangedWebhookEvent from .call_conversation_ended_webhook_event import CallConversationEndedWebhookEvent from .conference_speak_started_webhook_event import ConferenceSpeakStartedWebhookEvent +from .call_conversation_created_webhook_event import CallConversationCreatedWebhookEvent from .conference_playback_ended_webhook_event import ConferencePlaybackEndedWebhookEvent from .hosted_number_order_event_webhook_event import HostedNumberOrderEventWebhookEvent from .conference_recording_saved_webhook_event import ConferenceRecordingSavedWebhookEvent @@ -79,7 +80,11 @@ from .conference_participant_speak_started_webhook_event import ConferenceParticipantSpeakStartedWebhookEvent from .conference_participant_playback_ended_webhook_event import ConferenceParticipantPlaybackEndedWebhookEvent from .call_ai_gather_message_history_updated_webhook_event import CallAIGatherMessageHistoryUpdatedWebhookEvent +from .call_machine_premium_detection_started_webhook_event import CallMachinePremiumDetectionStartedWebhookEvent from .conference_participant_playback_started_webhook_event import ConferenceParticipantPlaybackStartedWebhookEvent +from .call_machine_premium_call_screening_detected_webhook_event import ( + CallMachinePremiumCallScreeningDetectedWebhookEvent, +) __all__ = ["UnwrapWebhookEvent"] @@ -91,6 +96,7 @@ ArtifactFailedWebhookEvent, CallAnsweredWebhookEvent, CallBridgedWebhookEvent, + CallConversationCreatedWebhookEvent, CallConversationEndedWebhookEvent, CallConversationInsightsGeneratedWebhookEvent, CallCostWebhookEvent, @@ -107,7 +113,9 @@ CallLeftQueueWebhookEvent, CallMachineDetectionEndedWebhookEvent, CallMachineGreetingEndedWebhookEvent, + CallMachinePremiumCallScreeningDetectedWebhookEvent, CallMachinePremiumDetectionEndedWebhookEvent, + CallMachinePremiumDetectionStartedWebhookEvent, CallMachinePremiumGreetingEndedWebhookEvent, CallPaymentCompletedWebhookEvent, CallPaymentProgressWebhookEvent, diff --git a/src/telnyx/types/whatsapp/phone_numbers/__init__.py b/src/telnyx/types/whatsapp/phone_numbers/__init__.py index c440e3a2a..5d5dfda95 100644 --- a/src/telnyx/types/whatsapp/phone_numbers/__init__.py +++ b/src/telnyx/types/whatsapp/phone_numbers/__init__.py @@ -6,6 +6,7 @@ from .profile_update_params import ProfileUpdateParams as ProfileUpdateParams from .calling_setting_update_params import CallingSettingUpdateParams as CallingSettingUpdateParams +from .calling_routing_patch_all_params import CallingRoutingPatchAllParams as CallingRoutingPatchAllParams from .conversational_component_patch_all_params import ( ConversationalComponentPatchAllParams as ConversationalComponentPatchAllParams, ) @@ -14,10 +15,13 @@ from .whatsapp_profile_data import WhatsappProfileData as WhatsappProfileData from .profile_update_response import ProfileUpdateResponse as ProfileUpdateResponse from .profile_retrieve_response import ProfileRetrieveResponse as ProfileRetrieveResponse + from .calling_routing_list_response import CallingRoutingListResponse as CallingRoutingListResponse + from .whatsapp_calling_routing_data import WhatsappCallingRoutingData as WhatsappCallingRoutingData from .whatsapp_calling_settings_data import WhatsappCallingSettingsData as WhatsappCallingSettingsData from .calling_setting_update_response import CallingSettingUpdateResponse as CallingSettingUpdateResponse from .calling_setting_retrieve_response import CallingSettingRetrieveResponse as CallingSettingRetrieveResponse from .whatsapp_conversational_component import WhatsappConversationalComponent as WhatsappConversationalComponent + from .calling_routing_patch_all_response import CallingRoutingPatchAllResponse as CallingRoutingPatchAllResponse from .conversational_component_list_response import ( ConversationalComponentListResponse as ConversationalComponentListResponse, ) @@ -63,4 +67,16 @@ def __getattr__(name: str) -> Any: from .conversational_component_patch_all_response import ConversationalComponentPatchAllResponse return ConversationalComponentPatchAllResponse + if name == "WhatsappCallingRoutingData": + from .whatsapp_calling_routing_data import WhatsappCallingRoutingData + + return WhatsappCallingRoutingData + if name == "CallingRoutingListResponse": + from .calling_routing_list_response import CallingRoutingListResponse + + return CallingRoutingListResponse + if name == "CallingRoutingPatchAllResponse": + from .calling_routing_patch_all_response import CallingRoutingPatchAllResponse + + return CallingRoutingPatchAllResponse raise AttributeError(f"module {__name__!r} has no attribute {name!r}") diff --git a/src/telnyx/types/whatsapp/phone_numbers/calling_routing_list_response.py b/src/telnyx/types/whatsapp/phone_numbers/calling_routing_list_response.py new file mode 100644 index 000000000..0d41b1307 --- /dev/null +++ b/src/telnyx/types/whatsapp/phone_numbers/calling_routing_list_response.py @@ -0,0 +1,12 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from ...._models import BaseModel +from .whatsapp_calling_routing_data import WhatsappCallingRoutingData + +__all__ = ["CallingRoutingListResponse"] + + +class CallingRoutingListResponse(BaseModel): + data: WhatsappCallingRoutingData diff --git a/src/telnyx/types/whatsapp/phone_numbers/calling_routing_patch_all_params.py b/src/telnyx/types/whatsapp/phone_numbers/calling_routing_patch_all_params.py new file mode 100644 index 000000000..5095cb0f5 --- /dev/null +++ b/src/telnyx/types/whatsapp/phone_numbers/calling_routing_patch_all_params.py @@ -0,0 +1,18 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Union +from typing_extensions import Required, TypedDict + +__all__ = ["CallingRoutingPatchAllParams"] + + +class CallingRoutingPatchAllParams(TypedDict, total=False): + connection_id: Required[Union[str, int, None]] + """ + ID of the connection to deliver inbound WhatsApp calls to: a positive integer up + to 9223372036854775807, sent as a decimal string or an integer. Send a string to + keep large IDs exact. Non-null values are returned as strings. `null` clears the + routing. + """ diff --git a/src/telnyx/types/whatsapp/phone_numbers/calling_routing_patch_all_response.py b/src/telnyx/types/whatsapp/phone_numbers/calling_routing_patch_all_response.py new file mode 100644 index 000000000..e1c3db518 --- /dev/null +++ b/src/telnyx/types/whatsapp/phone_numbers/calling_routing_patch_all_response.py @@ -0,0 +1,12 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from ...._models import BaseModel +from .whatsapp_calling_routing_data import WhatsappCallingRoutingData + +__all__ = ["CallingRoutingPatchAllResponse"] + + +class CallingRoutingPatchAllResponse(BaseModel): + data: WhatsappCallingRoutingData diff --git a/src/telnyx/types/whatsapp/phone_numbers/whatsapp_calling_routing_data.py b/src/telnyx/types/whatsapp/phone_numbers/whatsapp_calling_routing_data.py new file mode 100644 index 000000000..ec7d1d8c1 --- /dev/null +++ b/src/telnyx/types/whatsapp/phone_numbers/whatsapp_calling_routing_data.py @@ -0,0 +1,21 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Optional +from typing_extensions import Literal + +from ...._models import BaseModel + +__all__ = ["WhatsappCallingRoutingData"] + + +class WhatsappCallingRoutingData(BaseModel): + connection_id: Optional[str] = None + """ID of the routing connection, or `null` when none is set.""" + + phone_number: str + """Phone number in E.164 format, with a leading `+`.""" + + record_type: Literal["whatsapp_calling_routing"] + """Identifies the type of the resource.""" diff --git a/src/telnyx/types/whatsapp/template_create_params.py b/src/telnyx/types/whatsapp/template_create_params.py index 4dc320551..37c78a230 100644 --- a/src/telnyx/types/whatsapp/template_create_params.py +++ b/src/telnyx/types/whatsapp/template_create_params.py @@ -5,12 +5,6 @@ from typing import Union, Iterable from typing_extensions import Literal, Required, TypeAlias, TypedDict -from .whatsapp_template_body_component_param import WhatsappTemplateBodyComponentParam -from .whatsapp_template_footer_component_param import WhatsappTemplateFooterComponentParam -from .whatsapp_template_header_component_param import WhatsappTemplateHeaderComponentParam -from .whatsapp_template_buttons_component_param import WhatsappTemplateButtonsComponentParam -from .whatsapp_template_carousel_component_param import WhatsappTemplateCarouselComponentParam - __all__ = ["TemplateCreateParams", "Component"] @@ -37,9 +31,15 @@ class TemplateCreateParams(TypedDict, total=False): Component: TypeAlias = Union[ - WhatsappTemplateHeaderComponentParam, - WhatsappTemplateBodyComponentParam, - WhatsappTemplateFooterComponentParam, - WhatsappTemplateButtonsComponentParam, - WhatsappTemplateCarouselComponentParam, + "WhatsappTemplateHeaderComponentParam", + "WhatsappTemplateBodyComponentParam", + "WhatsappTemplateFooterComponentParam", + "WhatsappTemplateButtonsComponentParam", + "WhatsappTemplateCarouselComponentParam", ] + +from .whatsapp_template_body_component_param import WhatsappTemplateBodyComponentParam +from .whatsapp_template_footer_component_param import WhatsappTemplateFooterComponentParam +from .whatsapp_template_header_component_param import WhatsappTemplateHeaderComponentParam +from .whatsapp_template_buttons_component_param import WhatsappTemplateButtonsComponentParam +from .whatsapp_template_carousel_component_param import WhatsappTemplateCarouselComponentParam diff --git a/src/telnyx/types/whatsapp_interactive_param.py b/src/telnyx/types/whatsapp_interactive_param.py index e5172a948..3231b33bd 100644 --- a/src/telnyx/types/whatsapp_interactive_param.py +++ b/src/telnyx/types/whatsapp_interactive_param.py @@ -5,8 +5,6 @@ from typing import Iterable from typing_extensions import Literal, TypedDict -from .whatsapp_media_param import WhatsappMediaParam - __all__ = [ "WhatsappInteractiveParam", "Action", @@ -54,11 +52,11 @@ class ActionCardBody(TypedDict, total=False): class ActionCardHeader(TypedDict, total=False): - image: WhatsappMediaParam + image: "WhatsappMediaParam" type: Literal["image", "video"] - video: WhatsappMediaParam + video: "WhatsappMediaParam" class ActionCard(TypedDict, total=False): @@ -137,16 +135,16 @@ class Footer(TypedDict, total=False): class Header(TypedDict, total=False): - document: WhatsappMediaParam + document: "WhatsappMediaParam" - image: WhatsappMediaParam + image: "WhatsappMediaParam" sub_text: str text: str """header text, 60 character maximum""" - video: WhatsappMediaParam + video: "WhatsappMediaParam" class WhatsappInteractiveParam(TypedDict, total=False): @@ -159,3 +157,6 @@ class WhatsappInteractiveParam(TypedDict, total=False): header: Header type: Literal["cta_url", "list", "carousel", "button", "location_request_message"] + + +from .whatsapp_media_param import WhatsappMediaParam diff --git a/src/telnyx/types/whatsapp_message_content_param.py b/src/telnyx/types/whatsapp_message_content_param.py index b5507e9bb..c868b2292 100644 --- a/src/telnyx/types/whatsapp_message_content_param.py +++ b/src/telnyx/types/whatsapp_message_content_param.py @@ -5,12 +5,6 @@ from typing import Iterable from typing_extensions import Literal, Required, TypedDict -from .whatsapp_media_param import WhatsappMediaParam -from .whatsapp_contact_param import WhatsappContactParam -from .whatsapp_location_param import WhatsappLocationParam -from .whatsapp_reaction_param import WhatsappReactionParam -from .whatsapp_interactive_param import WhatsappInteractiveParam - __all__ = [ "WhatsappMessageContentParam", "Template", @@ -83,24 +77,24 @@ class Text(TypedDict, total=False): class WhatsappMessageContentParam(TypedDict, total=False): - audio: WhatsappMediaParam + audio: "WhatsappMediaParam" biz_opaque_callback_data: str """custom data to return with status update""" - contacts: Iterable[WhatsappContactParam] + contacts: Iterable["WhatsappContactParam"] - document: WhatsappMediaParam + document: "WhatsappMediaParam" - image: WhatsappMediaParam + image: "WhatsappMediaParam" - interactive: WhatsappInteractiveParam + interactive: "WhatsappInteractiveParam" - location: WhatsappLocationParam + location: "WhatsappLocationParam" - reaction: WhatsappReactionParam + reaction: "WhatsappReactionParam" - sticker: WhatsappMediaParam + sticker: "WhatsappMediaParam" template: Template """Template message object. @@ -128,4 +122,11 @@ class WhatsappMessageContentParam(TypedDict, total=False): "text", ] - video: WhatsappMediaParam + video: "WhatsappMediaParam" + + +from .whatsapp_media_param import WhatsappMediaParam +from .whatsapp_contact_param import WhatsappContactParam +from .whatsapp_location_param import WhatsappLocationParam +from .whatsapp_reaction_param import WhatsappReactionParam +from .whatsapp_interactive_param import WhatsappInteractiveParam diff --git a/src/telnyx/types/whatsapp_message_template_update_params.py b/src/telnyx/types/whatsapp_message_template_update_params.py index 594f685c4..57c9e9649 100644 --- a/src/telnyx/types/whatsapp_message_template_update_params.py +++ b/src/telnyx/types/whatsapp_message_template_update_params.py @@ -5,12 +5,6 @@ from typing import Union, Iterable from typing_extensions import Literal, TypeAlias, TypedDict -from .whatsapp.whatsapp_template_body_component_param import WhatsappTemplateBodyComponentParam -from .whatsapp.whatsapp_template_footer_component_param import WhatsappTemplateFooterComponentParam -from .whatsapp.whatsapp_template_header_component_param import WhatsappTemplateHeaderComponentParam -from .whatsapp.whatsapp_template_buttons_component_param import WhatsappTemplateButtonsComponentParam -from .whatsapp.whatsapp_template_carousel_component_param import WhatsappTemplateCarouselComponentParam - __all__ = ["WhatsappMessageTemplateUpdateParams", "Component"] @@ -22,9 +16,15 @@ class WhatsappMessageTemplateUpdateParams(TypedDict, total=False): Component: TypeAlias = Union[ - WhatsappTemplateHeaderComponentParam, - WhatsappTemplateBodyComponentParam, - WhatsappTemplateFooterComponentParam, - WhatsappTemplateButtonsComponentParam, - WhatsappTemplateCarouselComponentParam, + "WhatsappTemplateHeaderComponentParam", + "WhatsappTemplateBodyComponentParam", + "WhatsappTemplateFooterComponentParam", + "WhatsappTemplateButtonsComponentParam", + "WhatsappTemplateCarouselComponentParam", ] + +from .whatsapp.whatsapp_template_body_component_param import WhatsappTemplateBodyComponentParam +from .whatsapp.whatsapp_template_footer_component_param import WhatsappTemplateFooterComponentParam +from .whatsapp.whatsapp_template_header_component_param import WhatsappTemplateHeaderComponentParam +from .whatsapp.whatsapp_template_buttons_component_param import WhatsappTemplateButtonsComponentParam +from .whatsapp.whatsapp_template_carousel_component_param import WhatsappTemplateCarouselComponentParam diff --git a/tests/api_resources/ai/assistants/test_deleted.py b/tests/api_resources/ai/assistants/test_deleted.py new file mode 100644 index 000000000..59d829ebf --- /dev/null +++ b/tests/api_resources/ai/assistants/test_deleted.py @@ -0,0 +1,183 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from telnyx import Telnyx, AsyncTelnyx +from tests.utils import assert_matches_type +from telnyx.pagination import SyncDefaultFlatPagination, AsyncDefaultFlatPagination +from telnyx.types.ai.assistants import DeletedAssistant + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestDeleted: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_list(self, client: Telnyx) -> None: + deleted = client.ai.assistants.deleted.list() + assert_matches_type(SyncDefaultFlatPagination[DeletedAssistant], deleted, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_list_with_all_params(self, client: Telnyx) -> None: + deleted = client.ai.assistants.deleted.list( + page_number=1, + page_size=1, + ) + assert_matches_type(SyncDefaultFlatPagination[DeletedAssistant], deleted, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_list(self, client: Telnyx) -> None: + response = client.ai.assistants.deleted.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + deleted = response.parse() + assert_matches_type(SyncDefaultFlatPagination[DeletedAssistant], deleted, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_list(self, client: Telnyx) -> None: + with client.ai.assistants.deleted.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + deleted = response.parse() + assert_matches_type(SyncDefaultFlatPagination[DeletedAssistant], deleted, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_get(self, client: Telnyx) -> None: + deleted = client.ai.assistants.deleted.get( + "assistant_id", + ) + assert_matches_type(DeletedAssistant, deleted, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_get(self, client: Telnyx) -> None: + response = client.ai.assistants.deleted.with_raw_response.get( + "assistant_id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + deleted = response.parse() + assert_matches_type(DeletedAssistant, deleted, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_get(self, client: Telnyx) -> None: + with client.ai.assistants.deleted.with_streaming_response.get( + "assistant_id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + deleted = response.parse() + assert_matches_type(DeletedAssistant, deleted, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_path_params_get(self, client: Telnyx) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `assistant_id` but received ''"): + client.ai.assistants.deleted.with_raw_response.get( + "", + ) + + +class TestAsyncDeleted: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_list(self, async_client: AsyncTelnyx) -> None: + deleted = await async_client.ai.assistants.deleted.list() + assert_matches_type(AsyncDefaultFlatPagination[DeletedAssistant], deleted, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_list_with_all_params(self, async_client: AsyncTelnyx) -> None: + deleted = await async_client.ai.assistants.deleted.list( + page_number=1, + page_size=1, + ) + assert_matches_type(AsyncDefaultFlatPagination[DeletedAssistant], deleted, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_list(self, async_client: AsyncTelnyx) -> None: + response = await async_client.ai.assistants.deleted.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + deleted = await response.parse() + assert_matches_type(AsyncDefaultFlatPagination[DeletedAssistant], deleted, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_list(self, async_client: AsyncTelnyx) -> None: + async with async_client.ai.assistants.deleted.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + deleted = await response.parse() + assert_matches_type(AsyncDefaultFlatPagination[DeletedAssistant], deleted, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_get(self, async_client: AsyncTelnyx) -> None: + deleted = await async_client.ai.assistants.deleted.get( + "assistant_id", + ) + assert_matches_type(DeletedAssistant, deleted, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_get(self, async_client: AsyncTelnyx) -> None: + response = await async_client.ai.assistants.deleted.with_raw_response.get( + "assistant_id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + deleted = await response.parse() + assert_matches_type(DeletedAssistant, deleted, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_get(self, async_client: AsyncTelnyx) -> None: + async with async_client.ai.assistants.deleted.with_streaming_response.get( + "assistant_id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + deleted = await response.parse() + assert_matches_type(DeletedAssistant, deleted, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_path_params_get(self, async_client: AsyncTelnyx) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `assistant_id` but received ''"): + await async_client.ai.assistants.deleted.with_raw_response.get( + "", + ) diff --git a/tests/api_resources/ai/assistants/test_versions.py b/tests/api_resources/ai/assistants/test_versions.py index a101b32ee..a40114c89 100644 --- a/tests/api_resources/ai/assistants/test_versions.py +++ b/tests/api_resources/ai/assistants/test_versions.py @@ -281,6 +281,23 @@ def test_method_update_with_all_params(self, client: Telnyx) -> None: }, ], }, + delegation_settings={ + "enabled": True, + "external_llm": { + "base_url": "base_url", + "model": "model", + "authentication_method": "token", + "certificate_ref": "certificate_ref", + "forward_metadata": True, + "llm_api_key_ref": "llm_api_key_ref", + "token_retrieval_url": "token_retrieval_url", + }, + "instructions": "instructions", + "llm_api_key_ref": "llm_api_key_ref", + "mode": "telnyx", + "model": "model", + "speak_results": True, + }, description="description", dynamic_variables={"foo": "bar"}, dynamic_variables_webhook_timeout_ms=1, @@ -445,6 +462,11 @@ def test_method_update_with_all_params(self, client: Telnyx) -> None: "use_speaker_boost": True, "voice_speed": 0, }, + websocket_settings={ + "auth_ref": "auth_ref", + "enabled": True, + "url": "url", + }, widget_settings={ "agent_thinking_text": "agent_thinking_text", "audio_visualizer_config": { @@ -920,6 +942,23 @@ async def test_method_update_with_all_params(self, async_client: AsyncTelnyx) -> }, ], }, + delegation_settings={ + "enabled": True, + "external_llm": { + "base_url": "base_url", + "model": "model", + "authentication_method": "token", + "certificate_ref": "certificate_ref", + "forward_metadata": True, + "llm_api_key_ref": "llm_api_key_ref", + "token_retrieval_url": "token_retrieval_url", + }, + "instructions": "instructions", + "llm_api_key_ref": "llm_api_key_ref", + "mode": "telnyx", + "model": "model", + "speak_results": True, + }, description="description", dynamic_variables={"foo": "bar"}, dynamic_variables_webhook_timeout_ms=1, @@ -1084,6 +1123,11 @@ async def test_method_update_with_all_params(self, async_client: AsyncTelnyx) -> "use_speaker_boost": True, "voice_speed": 0, }, + websocket_settings={ + "auth_ref": "auth_ref", + "enabled": True, + "url": "url", + }, widget_settings={ "agent_thinking_text": "agent_thinking_text", "audio_visualizer_config": { diff --git a/tests/api_resources/ai/memory/test_namespaces.py b/tests/api_resources/ai/memory/test_namespaces.py index e068a6e61..f9b4174bf 100644 --- a/tests/api_resources/ai/memory/test_namespaces.py +++ b/tests/api_resources/ai/memory/test_namespaces.py @@ -9,7 +9,11 @@ from telnyx import Telnyx, AsyncTelnyx from tests.utils import assert_matches_type -from telnyx.types.ai.memory import NamespaceRetrieveResponse +from telnyx.types.ai.memory import ( + NamespaceListResponse, + NamespaceCreateResponse, + NamespaceRetrieveResponse, +) base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -17,6 +21,40 @@ class TestNamespaces: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_create(self, client: Telnyx) -> None: + namespace = client.ai.memory.namespaces.create( + name="staging", + ) + assert_matches_type(NamespaceCreateResponse, namespace, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_create(self, client: Telnyx) -> None: + response = client.ai.memory.namespaces.with_raw_response.create( + name="staging", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + namespace = response.parse() + assert_matches_type(NamespaceCreateResponse, namespace, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_create(self, client: Telnyx) -> None: + with client.ai.memory.namespaces.with_streaming_response.create( + name="staging", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + namespace = response.parse() + assert_matches_type(NamespaceCreateResponse, namespace, path=["response"]) + + assert cast(Any, response.is_closed) is True + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_method_retrieve(self, client: Telnyx) -> None: @@ -69,12 +107,116 @@ def test_path_params_retrieve(self, client: Telnyx) -> None: namespace="namespace", ) + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_list(self, client: Telnyx) -> None: + namespace = client.ai.memory.namespaces.list() + assert_matches_type(NamespaceListResponse, namespace, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_list(self, client: Telnyx) -> None: + response = client.ai.memory.namespaces.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + namespace = response.parse() + assert_matches_type(NamespaceListResponse, namespace, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_list(self, client: Telnyx) -> None: + with client.ai.memory.namespaces.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + namespace = response.parse() + assert_matches_type(NamespaceListResponse, namespace, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_delete(self, client: Telnyx) -> None: + namespace = client.ai.memory.namespaces.delete( + "namespace", + ) + assert namespace is None + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_delete(self, client: Telnyx) -> None: + response = client.ai.memory.namespaces.with_raw_response.delete( + "namespace", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + namespace = response.parse() + assert namespace is None + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_delete(self, client: Telnyx) -> None: + with client.ai.memory.namespaces.with_streaming_response.delete( + "namespace", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + namespace = response.parse() + assert namespace is None + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_path_params_delete(self, client: Telnyx) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `namespace` but received ''"): + client.ai.memory.namespaces.with_raw_response.delete( + "", + ) + class TestAsyncNamespaces: parametrize = pytest.mark.parametrize( "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] ) + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_create(self, async_client: AsyncTelnyx) -> None: + namespace = await async_client.ai.memory.namespaces.create( + name="staging", + ) + assert_matches_type(NamespaceCreateResponse, namespace, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_create(self, async_client: AsyncTelnyx) -> None: + response = await async_client.ai.memory.namespaces.with_raw_response.create( + name="staging", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + namespace = await response.parse() + assert_matches_type(NamespaceCreateResponse, namespace, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_create(self, async_client: AsyncTelnyx) -> None: + async with async_client.ai.memory.namespaces.with_streaming_response.create( + name="staging", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + namespace = await response.parse() + assert_matches_type(NamespaceCreateResponse, namespace, path=["response"]) + + assert cast(Any, response.is_closed) is True + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_method_retrieve(self, async_client: AsyncTelnyx) -> None: @@ -126,3 +268,73 @@ async def test_path_params_retrieve(self, async_client: AsyncTelnyx) -> None: operation_id="", namespace="namespace", ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_list(self, async_client: AsyncTelnyx) -> None: + namespace = await async_client.ai.memory.namespaces.list() + assert_matches_type(NamespaceListResponse, namespace, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_list(self, async_client: AsyncTelnyx) -> None: + response = await async_client.ai.memory.namespaces.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + namespace = await response.parse() + assert_matches_type(NamespaceListResponse, namespace, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_list(self, async_client: AsyncTelnyx) -> None: + async with async_client.ai.memory.namespaces.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + namespace = await response.parse() + assert_matches_type(NamespaceListResponse, namespace, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_delete(self, async_client: AsyncTelnyx) -> None: + namespace = await async_client.ai.memory.namespaces.delete( + "namespace", + ) + assert namespace is None + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_delete(self, async_client: AsyncTelnyx) -> None: + response = await async_client.ai.memory.namespaces.with_raw_response.delete( + "namespace", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + namespace = await response.parse() + assert namespace is None + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_delete(self, async_client: AsyncTelnyx) -> None: + async with async_client.ai.memory.namespaces.with_streaming_response.delete( + "namespace", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + namespace = await response.parse() + assert namespace is None + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_path_params_delete(self, async_client: AsyncTelnyx) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `namespace` but received ''"): + await async_client.ai.memory.namespaces.with_raw_response.delete( + "", + ) diff --git a/tests/api_resources/ai/test_assistants.py b/tests/api_resources/ai/test_assistants.py index 025c2fc27..903fbaaa2 100644 --- a/tests/api_resources/ai/test_assistants.py +++ b/tests/api_resources/ai/test_assistants.py @@ -15,6 +15,7 @@ AssistantChatResponse, AssistantDeleteResponse, AssistantSendSMSResponse, + AssistantWhatsappResponse, ) base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -222,6 +223,23 @@ def test_method_create_with_all_params(self, client: Telnyx) -> None: }, ], }, + delegation_settings={ + "enabled": True, + "external_llm": { + "base_url": "base_url", + "model": "model", + "authentication_method": "token", + "certificate_ref": "certificate_ref", + "forward_metadata": True, + "llm_api_key_ref": "llm_api_key_ref", + "token_retrieval_url": "token_retrieval_url", + }, + "instructions": "instructions", + "llm_api_key_ref": "llm_api_key_ref", + "mode": "telnyx", + "model": "model", + "speak_results": True, + }, description="description", dynamic_variables={"foo": "bar"}, dynamic_variables_webhook_timeout_ms=1, @@ -383,6 +401,11 @@ def test_method_create_with_all_params(self, client: Telnyx) -> None: "use_speaker_boost": True, "voice_speed": 0, }, + websocket_settings={ + "auth_ref": "auth_ref", + "enabled": True, + "url": "url", + }, widget_settings={ "agent_thinking_text": "agent_thinking_text", "audio_visualizer_config": { @@ -682,6 +705,23 @@ def test_method_update_with_all_params(self, client: Telnyx) -> None: }, ], }, + delegation_settings={ + "enabled": True, + "external_llm": { + "base_url": "base_url", + "model": "model", + "authentication_method": "token", + "certificate_ref": "certificate_ref", + "forward_metadata": True, + "llm_api_key_ref": "llm_api_key_ref", + "token_retrieval_url": "token_retrieval_url", + }, + "instructions": "instructions", + "llm_api_key_ref": "llm_api_key_ref", + "mode": "telnyx", + "model": "model", + "speak_results": True, + }, description="description", dynamic_variables={"foo": "bar"}, dynamic_variables_webhook_timeout_ms=1, @@ -847,6 +887,11 @@ def test_method_update_with_all_params(self, client: Telnyx) -> None: "use_speaker_boost": True, "voice_speed": 0, }, + websocket_settings={ + "auth_ref": "auth_ref", + "enabled": True, + "url": "url", + }, widget_settings={ "agent_thinking_text": "agent_thinking_text", "audio_visualizer_config": { @@ -932,7 +977,16 @@ def test_streaming_response_list(self, client: Telnyx) -> None: @parametrize def test_method_delete(self, client: Telnyx) -> None: assistant = client.ai.assistants.delete( - "assistant_id", + assistant_id="assistant_id", + ) + assert_matches_type(AssistantDeleteResponse, assistant, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_delete_with_all_params(self, client: Telnyx) -> None: + assistant = client.ai.assistants.delete( + assistant_id="assistant_id", + hard_delete=True, ) assert_matches_type(AssistantDeleteResponse, assistant, path=["response"]) @@ -940,7 +994,7 @@ def test_method_delete(self, client: Telnyx) -> None: @parametrize def test_raw_response_delete(self, client: Telnyx) -> None: response = client.ai.assistants.with_raw_response.delete( - "assistant_id", + assistant_id="assistant_id", ) assert response.is_closed is True @@ -952,7 +1006,7 @@ def test_raw_response_delete(self, client: Telnyx) -> None: @parametrize def test_streaming_response_delete(self, client: Telnyx) -> None: with client.ai.assistants.with_streaming_response.delete( - "assistant_id", + assistant_id="assistant_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -967,7 +1021,7 @@ def test_streaming_response_delete(self, client: Telnyx) -> None: def test_path_params_delete(self, client: Telnyx) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `assistant_id` but received ''"): client.ai.assistants.with_raw_response.delete( - "", + assistant_id="", ) @pytest.mark.skip(reason="Mock server tests are disabled") @@ -1173,6 +1227,48 @@ def test_streaming_response_imports(self, client: Telnyx) -> None: assert cast(Any, response.is_closed) is True + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_restore(self, client: Telnyx) -> None: + assistant = client.ai.assistants.restore( + "assistant_id", + ) + assert_matches_type(InferenceEmbedding, assistant, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_restore(self, client: Telnyx) -> None: + response = client.ai.assistants.with_raw_response.restore( + "assistant_id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assistant = response.parse() + assert_matches_type(InferenceEmbedding, assistant, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_restore(self, client: Telnyx) -> None: + with client.ai.assistants.with_streaming_response.restore( + "assistant_id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + assistant = response.parse() + assert_matches_type(InferenceEmbedding, assistant, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_path_params_restore(self, client: Telnyx) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `assistant_id` but received ''"): + client.ai.assistants.with_raw_response.restore( + "", + ) + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_method_send_sms(self, client: Telnyx) -> None: @@ -1237,6 +1333,73 @@ def test_path_params_send_sms(self, client: Telnyx) -> None: to="To", ) + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_whatsapp(self, client: Telnyx) -> None: + assistant = client.ai.assistants.whatsapp( + assistant_id="assistant_id", + content="Send the login verification code 482913 to the customer.", + from_="+13125550001", + to="+13125550002", + ) + assert_matches_type(AssistantWhatsappResponse, assistant, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_whatsapp_with_all_params(self, client: Telnyx) -> None: + assistant = client.ai.assistants.whatsapp( + assistant_id="assistant_id", + content="Send the login verification code 482913 to the customer.", + from_="+13125550001", + to="+13125550002", + conversation_metadata={"order_id": "A1"}, + idempotency_key="8e03978e-40d5-43e8-bc93-6894a57f9326", + ) + assert_matches_type(AssistantWhatsappResponse, assistant, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_whatsapp(self, client: Telnyx) -> None: + response = client.ai.assistants.with_raw_response.whatsapp( + assistant_id="assistant_id", + content="Send the login verification code 482913 to the customer.", + from_="+13125550001", + to="+13125550002", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assistant = response.parse() + assert_matches_type(AssistantWhatsappResponse, assistant, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_whatsapp(self, client: Telnyx) -> None: + with client.ai.assistants.with_streaming_response.whatsapp( + assistant_id="assistant_id", + content="Send the login verification code 482913 to the customer.", + from_="+13125550001", + to="+13125550002", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + assistant = response.parse() + assert_matches_type(AssistantWhatsappResponse, assistant, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_path_params_whatsapp(self, client: Telnyx) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `assistant_id` but received ''"): + client.ai.assistants.with_raw_response.whatsapp( + assistant_id="", + content="Send the login verification code 482913 to the customer.", + from_="+13125550001", + to="+13125550002", + ) + class TestAsyncAssistants: parametrize = pytest.mark.parametrize( @@ -1442,6 +1605,23 @@ async def test_method_create_with_all_params(self, async_client: AsyncTelnyx) -> }, ], }, + delegation_settings={ + "enabled": True, + "external_llm": { + "base_url": "base_url", + "model": "model", + "authentication_method": "token", + "certificate_ref": "certificate_ref", + "forward_metadata": True, + "llm_api_key_ref": "llm_api_key_ref", + "token_retrieval_url": "token_retrieval_url", + }, + "instructions": "instructions", + "llm_api_key_ref": "llm_api_key_ref", + "mode": "telnyx", + "model": "model", + "speak_results": True, + }, description="description", dynamic_variables={"foo": "bar"}, dynamic_variables_webhook_timeout_ms=1, @@ -1603,6 +1783,11 @@ async def test_method_create_with_all_params(self, async_client: AsyncTelnyx) -> "use_speaker_boost": True, "voice_speed": 0, }, + websocket_settings={ + "auth_ref": "auth_ref", + "enabled": True, + "url": "url", + }, widget_settings={ "agent_thinking_text": "agent_thinking_text", "audio_visualizer_config": { @@ -1902,6 +2087,23 @@ async def test_method_update_with_all_params(self, async_client: AsyncTelnyx) -> }, ], }, + delegation_settings={ + "enabled": True, + "external_llm": { + "base_url": "base_url", + "model": "model", + "authentication_method": "token", + "certificate_ref": "certificate_ref", + "forward_metadata": True, + "llm_api_key_ref": "llm_api_key_ref", + "token_retrieval_url": "token_retrieval_url", + }, + "instructions": "instructions", + "llm_api_key_ref": "llm_api_key_ref", + "mode": "telnyx", + "model": "model", + "speak_results": True, + }, description="description", dynamic_variables={"foo": "bar"}, dynamic_variables_webhook_timeout_ms=1, @@ -2067,6 +2269,11 @@ async def test_method_update_with_all_params(self, async_client: AsyncTelnyx) -> "use_speaker_boost": True, "voice_speed": 0, }, + websocket_settings={ + "auth_ref": "auth_ref", + "enabled": True, + "url": "url", + }, widget_settings={ "agent_thinking_text": "agent_thinking_text", "audio_visualizer_config": { @@ -2152,7 +2359,16 @@ async def test_streaming_response_list(self, async_client: AsyncTelnyx) -> None: @parametrize async def test_method_delete(self, async_client: AsyncTelnyx) -> None: assistant = await async_client.ai.assistants.delete( - "assistant_id", + assistant_id="assistant_id", + ) + assert_matches_type(AssistantDeleteResponse, assistant, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_delete_with_all_params(self, async_client: AsyncTelnyx) -> None: + assistant = await async_client.ai.assistants.delete( + assistant_id="assistant_id", + hard_delete=True, ) assert_matches_type(AssistantDeleteResponse, assistant, path=["response"]) @@ -2160,7 +2376,7 @@ async def test_method_delete(self, async_client: AsyncTelnyx) -> None: @parametrize async def test_raw_response_delete(self, async_client: AsyncTelnyx) -> None: response = await async_client.ai.assistants.with_raw_response.delete( - "assistant_id", + assistant_id="assistant_id", ) assert response.is_closed is True @@ -2172,7 +2388,7 @@ async def test_raw_response_delete(self, async_client: AsyncTelnyx) -> None: @parametrize async def test_streaming_response_delete(self, async_client: AsyncTelnyx) -> None: async with async_client.ai.assistants.with_streaming_response.delete( - "assistant_id", + assistant_id="assistant_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -2187,7 +2403,7 @@ async def test_streaming_response_delete(self, async_client: AsyncTelnyx) -> Non async def test_path_params_delete(self, async_client: AsyncTelnyx) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `assistant_id` but received ''"): await async_client.ai.assistants.with_raw_response.delete( - "", + assistant_id="", ) @pytest.mark.skip(reason="Mock server tests are disabled") @@ -2393,6 +2609,48 @@ async def test_streaming_response_imports(self, async_client: AsyncTelnyx) -> No assert cast(Any, response.is_closed) is True + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_restore(self, async_client: AsyncTelnyx) -> None: + assistant = await async_client.ai.assistants.restore( + "assistant_id", + ) + assert_matches_type(InferenceEmbedding, assistant, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_restore(self, async_client: AsyncTelnyx) -> None: + response = await async_client.ai.assistants.with_raw_response.restore( + "assistant_id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assistant = await response.parse() + assert_matches_type(InferenceEmbedding, assistant, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_restore(self, async_client: AsyncTelnyx) -> None: + async with async_client.ai.assistants.with_streaming_response.restore( + "assistant_id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + assistant = await response.parse() + assert_matches_type(InferenceEmbedding, assistant, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_path_params_restore(self, async_client: AsyncTelnyx) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `assistant_id` but received ''"): + await async_client.ai.assistants.with_raw_response.restore( + "", + ) + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_method_send_sms(self, async_client: AsyncTelnyx) -> None: @@ -2456,3 +2714,70 @@ async def test_path_params_send_sms(self, async_client: AsyncTelnyx) -> None: from_="From", to="To", ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_whatsapp(self, async_client: AsyncTelnyx) -> None: + assistant = await async_client.ai.assistants.whatsapp( + assistant_id="assistant_id", + content="Send the login verification code 482913 to the customer.", + from_="+13125550001", + to="+13125550002", + ) + assert_matches_type(AssistantWhatsappResponse, assistant, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_whatsapp_with_all_params(self, async_client: AsyncTelnyx) -> None: + assistant = await async_client.ai.assistants.whatsapp( + assistant_id="assistant_id", + content="Send the login verification code 482913 to the customer.", + from_="+13125550001", + to="+13125550002", + conversation_metadata={"order_id": "A1"}, + idempotency_key="8e03978e-40d5-43e8-bc93-6894a57f9326", + ) + assert_matches_type(AssistantWhatsappResponse, assistant, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_whatsapp(self, async_client: AsyncTelnyx) -> None: + response = await async_client.ai.assistants.with_raw_response.whatsapp( + assistant_id="assistant_id", + content="Send the login verification code 482913 to the customer.", + from_="+13125550001", + to="+13125550002", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + assistant = await response.parse() + assert_matches_type(AssistantWhatsappResponse, assistant, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_whatsapp(self, async_client: AsyncTelnyx) -> None: + async with async_client.ai.assistants.with_streaming_response.whatsapp( + assistant_id="assistant_id", + content="Send the login verification code 482913 to the customer.", + from_="+13125550001", + to="+13125550002", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + assistant = await response.parse() + assert_matches_type(AssistantWhatsappResponse, assistant, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_path_params_whatsapp(self, async_client: AsyncTelnyx) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `assistant_id` but received ''"): + await async_client.ai.assistants.with_raw_response.whatsapp( + assistant_id="", + content="Send the login verification code 482913 to the customer.", + from_="+13125550001", + to="+13125550002", + ) diff --git a/tests/api_resources/ai/test_embeddings.py b/tests/api_resources/ai/test_embeddings.py index b68a178d7..07a45f464 100644 --- a/tests/api_resources/ai/test_embeddings.py +++ b/tests/api_resources/ai/test_embeddings.py @@ -37,7 +37,7 @@ def test_method_create_with_all_params(self, client: Telnyx) -> None: bucket_name="Bucket Name", document_chunk_overlap_size=512, document_chunk_size=1024, - embedding_model="thenlper/gte-large", + embedding_model="intfloat/multilingual-e5-large", loader="default", idempotency_key="8e03978e-40d5-43e8-bc93-6894a57f9326", ) @@ -262,7 +262,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncTelnyx) -> bucket_name="Bucket Name", document_chunk_overlap_size=512, document_chunk_size=1024, - embedding_model="thenlper/gte-large", + embedding_model="intfloat/multilingual-e5-large", loader="default", idempotency_key="8e03978e-40d5-43e8-bc93-6894a57f9326", ) diff --git a/tests/api_resources/ai/test_tools.py b/tests/api_resources/ai/test_tools.py index 3b05dc1a2..fec1c31cc 100644 --- a/tests/api_resources/ai/test_tools.py +++ b/tests/api_resources/ai/test_tools.py @@ -254,7 +254,7 @@ def test_method_delete(self, client: Telnyx) -> None: tool = client.ai.tools.delete( "tool_id", ) - assert_matches_type(object, tool, path=["response"]) + assert tool is None @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -266,7 +266,7 @@ def test_raw_response_delete(self, client: Telnyx) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" tool = response.parse() - assert_matches_type(object, tool, path=["response"]) + assert tool is None @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -278,7 +278,7 @@ def test_streaming_response_delete(self, client: Telnyx) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" tool = response.parse() - assert_matches_type(object, tool, path=["response"]) + assert tool is None assert cast(Any, response.is_closed) is True @@ -530,7 +530,7 @@ async def test_method_delete(self, async_client: AsyncTelnyx) -> None: tool = await async_client.ai.tools.delete( "tool_id", ) - assert_matches_type(object, tool, path=["response"]) + assert tool is None @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -542,7 +542,7 @@ async def test_raw_response_delete(self, async_client: AsyncTelnyx) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" tool = await response.parse() - assert_matches_type(object, tool, path=["response"]) + assert tool is None @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -554,7 +554,7 @@ async def test_streaming_response_delete(self, async_client: AsyncTelnyx) -> Non assert response.http_request.headers.get("X-Stainless-Lang") == "python" tool = await response.parse() - assert_matches_type(object, tool, path=["response"]) + assert tool is None assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/calls/test_actions.py b/tests/api_resources/calls/test_actions.py index 238271476..74ebca1b2 100644 --- a/tests/api_resources/calls/test_actions.py +++ b/tests/api_resources/calls/test_actions.py @@ -174,8 +174,12 @@ def test_method_answer_with_all_params(self, client: Telnyx) -> None: "type": "hangup", } ], + "transcription": { + "language": "en", + "model": "deepgram/flux", + }, "voice_settings": { - "voice": "voice", + "voice": "Telnyx.KokoroTTS.af_heart", "api_key_ref": "api_key_ref", "background_audio": { "type": "predefined_media", @@ -1582,6 +1586,10 @@ def test_method_start_ai_assistant_with_all_params(self, client: Telnyx) -> None "type": "book_appointment", } ], + "transcription": { + "language": "language", + "model": "distil-whisper/distil-large-v2", + }, "voice_settings": { "voice": "voice", "api_key_ref": "api_key_ref", @@ -2851,6 +2859,7 @@ def test_method_transfer_with_all_params(self, client: Telnyx) -> None: "initial_silence_millis": 1000, "maximum_number_of_words": 1000, "maximum_word_length_millis": 2000, + "prompt_end_timeout_millis": 5000, "silence_threshold": 512, "total_analysis_time_millis": 5000, }, @@ -3121,8 +3130,12 @@ async def test_method_answer_with_all_params(self, async_client: AsyncTelnyx) -> "type": "hangup", } ], + "transcription": { + "language": "en", + "model": "deepgram/flux", + }, "voice_settings": { - "voice": "voice", + "voice": "Telnyx.KokoroTTS.af_heart", "api_key_ref": "api_key_ref", "background_audio": { "type": "predefined_media", @@ -4529,6 +4542,10 @@ async def test_method_start_ai_assistant_with_all_params(self, async_client: Asy "type": "book_appointment", } ], + "transcription": { + "language": "language", + "model": "distil-whisper/distil-large-v2", + }, "voice_settings": { "voice": "voice", "api_key_ref": "api_key_ref", @@ -5798,6 +5815,7 @@ async def test_method_transfer_with_all_params(self, async_client: AsyncTelnyx) "initial_silence_millis": 1000, "maximum_number_of_words": 1000, "maximum_word_length_millis": 2000, + "prompt_end_timeout_millis": 5000, "silence_threshold": 512, "total_analysis_time_millis": 5000, }, diff --git a/tests/api_resources/enterprises/test_dir.py b/tests/api_resources/enterprises/test_dir.py index 79e7877b2..b6cca8c3c 100644 --- a/tests/api_resources/enterprises/test_dir.py +++ b/tests/api_resources/enterprises/test_dir.py @@ -47,6 +47,12 @@ def test_method_create_with_all_params(self, client: Telnyx) -> None: certify_ip_ownership=True, certify_no_shaft_content=True, display_name="Acme Plumbing", + bpo_authorizations=[ + { + "bpo_enterprise_id": "4a6192a4-573d-446d-b3ce-aff9117272a6", + "loa_document_id": "2a7e8337-e803-4057-a4ae-26c40eb0bc6c", + } + ], documents=[ { "document_id": "2a7e8337-e803-4057-a4ae-26c40eb0bc6c", @@ -56,6 +62,7 @@ def test_method_create_with_all_params(self, client: Telnyx) -> None: ], logo_url="https://acmeplumbing.example.com/logo-256.bmp", reselling=False, + webhook_url="https://mapleridge.example.com/webhooks/branded-calling", ) assert_matches_type(DirWrapped, dir, path=["response"]) @@ -206,6 +213,12 @@ async def test_method_create_with_all_params(self, async_client: AsyncTelnyx) -> certify_ip_ownership=True, certify_no_shaft_content=True, display_name="Acme Plumbing", + bpo_authorizations=[ + { + "bpo_enterprise_id": "4a6192a4-573d-446d-b3ce-aff9117272a6", + "loa_document_id": "2a7e8337-e803-4057-a4ae-26c40eb0bc6c", + } + ], documents=[ { "document_id": "2a7e8337-e803-4057-a4ae-26c40eb0bc6c", @@ -215,6 +228,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncTelnyx) -> ], logo_url="https://acmeplumbing.example.com/logo-256.bmp", reselling=False, + webhook_url="https://mapleridge.example.com/webhooks/branded-calling", ) assert_matches_type(DirWrapped, dir, path=["response"]) diff --git a/tests/api_resources/enterprises/test_verify_email.py b/tests/api_resources/enterprises/test_verify_email.py new file mode 100644 index 000000000..4b3ea3010 --- /dev/null +++ b/tests/api_resources/enterprises/test_verify_email.py @@ -0,0 +1,200 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from telnyx import Telnyx, AsyncTelnyx +from tests.utils import assert_matches_type +from telnyx.types.enterprises import EnterpriseEmailVerificationStatusWrapped + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestVerifyEmail: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_create(self, client: Telnyx) -> None: + verify_email = client.enterprises.verify_email.create( + "4a6192a4-573d-446d-b3ce-aff9117272a6", + ) + assert_matches_type(EnterpriseEmailVerificationStatusWrapped, verify_email, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_create(self, client: Telnyx) -> None: + response = client.enterprises.verify_email.with_raw_response.create( + "4a6192a4-573d-446d-b3ce-aff9117272a6", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + verify_email = response.parse() + assert_matches_type(EnterpriseEmailVerificationStatusWrapped, verify_email, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_create(self, client: Telnyx) -> None: + with client.enterprises.verify_email.with_streaming_response.create( + "4a6192a4-573d-446d-b3ce-aff9117272a6", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + verify_email = response.parse() + assert_matches_type(EnterpriseEmailVerificationStatusWrapped, verify_email, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_path_params_create(self, client: Telnyx) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `enterprise_id` but received ''"): + client.enterprises.verify_email.with_raw_response.create( + "", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_confirm(self, client: Telnyx) -> None: + verify_email = client.enterprises.verify_email.confirm( + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + code="482915", + ) + assert_matches_type(EnterpriseEmailVerificationStatusWrapped, verify_email, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_confirm(self, client: Telnyx) -> None: + response = client.enterprises.verify_email.with_raw_response.confirm( + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + code="482915", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + verify_email = response.parse() + assert_matches_type(EnterpriseEmailVerificationStatusWrapped, verify_email, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_confirm(self, client: Telnyx) -> None: + with client.enterprises.verify_email.with_streaming_response.confirm( + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + code="482915", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + verify_email = response.parse() + assert_matches_type(EnterpriseEmailVerificationStatusWrapped, verify_email, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_path_params_confirm(self, client: Telnyx) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `enterprise_id` but received ''"): + client.enterprises.verify_email.with_raw_response.confirm( + enterprise_id="", + code="482915", + ) + + +class TestAsyncVerifyEmail: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_create(self, async_client: AsyncTelnyx) -> None: + verify_email = await async_client.enterprises.verify_email.create( + "4a6192a4-573d-446d-b3ce-aff9117272a6", + ) + assert_matches_type(EnterpriseEmailVerificationStatusWrapped, verify_email, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_create(self, async_client: AsyncTelnyx) -> None: + response = await async_client.enterprises.verify_email.with_raw_response.create( + "4a6192a4-573d-446d-b3ce-aff9117272a6", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + verify_email = await response.parse() + assert_matches_type(EnterpriseEmailVerificationStatusWrapped, verify_email, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_create(self, async_client: AsyncTelnyx) -> None: + async with async_client.enterprises.verify_email.with_streaming_response.create( + "4a6192a4-573d-446d-b3ce-aff9117272a6", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + verify_email = await response.parse() + assert_matches_type(EnterpriseEmailVerificationStatusWrapped, verify_email, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_path_params_create(self, async_client: AsyncTelnyx) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `enterprise_id` but received ''"): + await async_client.enterprises.verify_email.with_raw_response.create( + "", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_confirm(self, async_client: AsyncTelnyx) -> None: + verify_email = await async_client.enterprises.verify_email.confirm( + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + code="482915", + ) + assert_matches_type(EnterpriseEmailVerificationStatusWrapped, verify_email, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_confirm(self, async_client: AsyncTelnyx) -> None: + response = await async_client.enterprises.verify_email.with_raw_response.confirm( + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + code="482915", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + verify_email = await response.parse() + assert_matches_type(EnterpriseEmailVerificationStatusWrapped, verify_email, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_confirm(self, async_client: AsyncTelnyx) -> None: + async with async_client.enterprises.verify_email.with_streaming_response.confirm( + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + code="482915", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + verify_email = await response.parse() + assert_matches_type(EnterpriseEmailVerificationStatusWrapped, verify_email, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_path_params_confirm(self, async_client: AsyncTelnyx) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `enterprise_id` but received ''"): + await async_client.enterprises.verify_email.with_raw_response.confirm( + enterprise_id="", + code="482915", + ) diff --git a/tests/api_resources/llm_token_gateway/__init__.py b/tests/api_resources/llm_token_gateway/__init__.py new file mode 100644 index 000000000..fd8019a9a --- /dev/null +++ b/tests/api_resources/llm_token_gateway/__init__.py @@ -0,0 +1 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. diff --git a/tests/api_resources/llm_token_gateway/test_usage.py b/tests/api_resources/llm_token_gateway/test_usage.py new file mode 100644 index 000000000..05eaa51dd --- /dev/null +++ b/tests/api_resources/llm_token_gateway/test_usage.py @@ -0,0 +1,105 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from telnyx import Telnyx, AsyncTelnyx +from tests.utils import assert_matches_type +from telnyx._utils import parse_date +from telnyx.types.llm_token_gateway import UsageRetrieveSummaryResponse + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestUsage: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_retrieve_summary(self, client: Telnyx) -> None: + usage = client.llm_token_gateway.usage.retrieve_summary( + end_date=parse_date("2019-12-27"), + start_date=parse_date("2019-12-27"), + token_group_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert_matches_type(UsageRetrieveSummaryResponse, usage, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_retrieve_summary(self, client: Telnyx) -> None: + response = client.llm_token_gateway.usage.with_raw_response.retrieve_summary( + end_date=parse_date("2019-12-27"), + start_date=parse_date("2019-12-27"), + token_group_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + usage = response.parse() + assert_matches_type(UsageRetrieveSummaryResponse, usage, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_retrieve_summary(self, client: Telnyx) -> None: + with client.llm_token_gateway.usage.with_streaming_response.retrieve_summary( + end_date=parse_date("2019-12-27"), + start_date=parse_date("2019-12-27"), + token_group_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + usage = response.parse() + assert_matches_type(UsageRetrieveSummaryResponse, usage, path=["response"]) + + assert cast(Any, response.is_closed) is True + + +class TestAsyncUsage: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_retrieve_summary(self, async_client: AsyncTelnyx) -> None: + usage = await async_client.llm_token_gateway.usage.retrieve_summary( + end_date=parse_date("2019-12-27"), + start_date=parse_date("2019-12-27"), + token_group_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert_matches_type(UsageRetrieveSummaryResponse, usage, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_retrieve_summary(self, async_client: AsyncTelnyx) -> None: + response = await async_client.llm_token_gateway.usage.with_raw_response.retrieve_summary( + end_date=parse_date("2019-12-27"), + start_date=parse_date("2019-12-27"), + token_group_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + usage = await response.parse() + assert_matches_type(UsageRetrieveSummaryResponse, usage, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_retrieve_summary(self, async_client: AsyncTelnyx) -> None: + async with async_client.llm_token_gateway.usage.with_streaming_response.retrieve_summary( + end_date=parse_date("2019-12-27"), + start_date=parse_date("2019-12-27"), + token_group_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + usage = await response.parse() + assert_matches_type(UsageRetrieveSummaryResponse, usage, path=["response"]) + + assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/test_calls.py b/tests/api_resources/test_calls.py index 644dbdb3c..b0fcbd5b8 100644 --- a/tests/api_resources/test_calls.py +++ b/tests/api_resources/test_calls.py @@ -55,6 +55,7 @@ def test_method_dial_with_all_params(self, client: Telnyx) -> None: "initial_silence_millis": 1000, "maximum_number_of_words": 1000, "maximum_word_length_millis": 2000, + "prompt_end_timeout_millis": 5000, "silence_threshold": 512, "total_analysis_time_millis": 5000, }, @@ -105,6 +106,10 @@ def test_method_dial_with_all_params(self, client: Telnyx) -> None: "type": "book_appointment", } ], + "transcription": { + "language": "language", + "model": "distil-whisper/distil-large-v2", + }, "voice_settings": { "voice": "voice", "api_key_ref": "api_key_ref", @@ -414,6 +419,7 @@ async def test_method_dial_with_all_params(self, async_client: AsyncTelnyx) -> N "initial_silence_millis": 1000, "maximum_number_of_words": 1000, "maximum_word_length_millis": 2000, + "prompt_end_timeout_millis": 5000, "silence_threshold": 512, "total_analysis_time_millis": 5000, }, @@ -464,6 +470,10 @@ async def test_method_dial_with_all_params(self, async_client: AsyncTelnyx) -> N "type": "book_appointment", } ], + "transcription": { + "language": "language", + "model": "distil-whisper/distil-large-v2", + }, "voice_settings": { "voice": "voice", "api_key_ref": "api_key_ref", diff --git a/tests/api_resources/test_dir.py b/tests/api_resources/test_dir.py index 790d52ec9..003bd7592 100644 --- a/tests/api_resources/test_dir.py +++ b/tests/api_resources/test_dir.py @@ -13,8 +13,10 @@ from tests.utils import assert_matches_type from telnyx.types import ( DirWrapped, + DirDeleteResponse, InfringementClaim, DirListDocumentTypesResponse, + DirRetrieveBpoAuthorizationsResponse, ) from telnyx._utils import parse_datetime from telnyx._response import ( @@ -89,6 +91,12 @@ def test_method_update_with_all_params(self, client: Telnyx) -> None: dir_id="16635d38-75a6-4481-82e8-69af60e05011", authorizer_email="dev@stainless.com", authorizer_name="authorizer_name", + bpo_authorizations=[ + { + "bpo_enterprise_id": "4a6192a4-573d-446d-b3ce-aff9117272a6", + "loa_document_id": "2a7e8337-e803-4057-a4ae-26c40eb0bc6c", + } + ], call_reasons=["Appointment reminders", "Billing inquiries", "Lab results"], certify_brand_is_accurate=True, certify_ip_ownership=True, @@ -103,6 +111,7 @@ def test_method_update_with_all_params(self, client: Telnyx) -> None: ], logo_url="https://acmeplumbing.example.com/logo-v2-256.bmp", reselling=True, + webhook_url="https://mapleridge.example.com/webhooks/branded-calling", ) assert_matches_type(DirWrapped, dir, path=["response"]) @@ -190,7 +199,7 @@ def test_method_delete(self, client: Telnyx) -> None: dir = client.dir.delete( "16635d38-75a6-4481-82e8-69af60e05011", ) - assert dir is None + assert_matches_type(DirDeleteResponse, dir, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -202,7 +211,7 @@ def test_raw_response_delete(self, client: Telnyx) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" dir = response.parse() - assert dir is None + assert_matches_type(DirDeleteResponse, dir, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -214,7 +223,7 @@ def test_streaming_response_delete(self, client: Telnyx) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" dir = response.parse() - assert dir is None + assert_matches_type(DirDeleteResponse, dir, path=["response"]) assert cast(Any, response.is_closed) is True @@ -226,6 +235,85 @@ def test_path_params_delete(self, client: Telnyx) -> None: "", ) + @parametrize + @pytest.mark.respx(base_url=base_url) + def test_method_bpo_loa(self, client: Telnyx, respx_mock: MockRouter) -> None: + respx_mock.post("/dir/182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e/bpo_loa").mock( + return_value=httpx.Response(200, json={"foo": "bar"}) + ) + dir = client.dir.bpo_loa( + dir_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + bpo_enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + ) + assert dir.is_closed + assert dir.json() == {"foo": "bar"} + assert cast(Any, dir.is_closed) is True + assert isinstance(dir, BinaryAPIResponse) + + @parametrize + @pytest.mark.respx(base_url=base_url) + def test_method_bpo_loa_with_all_params(self, client: Telnyx, respx_mock: MockRouter) -> None: + respx_mock.post("/dir/182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e/bpo_loa").mock( + return_value=httpx.Response(200, json={"foo": "bar"}) + ) + dir = client.dir.bpo_loa( + dir_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + bpo_enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + signature={ + "image_base64": "x", + "signer_name": "signer_name", + }, + ) + assert dir.is_closed + assert dir.json() == {"foo": "bar"} + assert cast(Any, dir.is_closed) is True + assert isinstance(dir, BinaryAPIResponse) + + @parametrize + @pytest.mark.respx(base_url=base_url) + def test_raw_response_bpo_loa(self, client: Telnyx, respx_mock: MockRouter) -> None: + respx_mock.post("/dir/182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e/bpo_loa").mock( + return_value=httpx.Response(200, json={"foo": "bar"}) + ) + + dir = client.dir.with_raw_response.bpo_loa( + dir_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + bpo_enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + ) + + assert dir.is_closed is True + assert dir.http_request.headers.get("X-Stainless-Lang") == "python" + assert dir.json() == {"foo": "bar"} + assert isinstance(dir, BinaryAPIResponse) + + @parametrize + @pytest.mark.respx(base_url=base_url) + def test_streaming_response_bpo_loa(self, client: Telnyx, respx_mock: MockRouter) -> None: + respx_mock.post("/dir/182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e/bpo_loa").mock( + return_value=httpx.Response(200, json={"foo": "bar"}) + ) + with client.dir.with_streaming_response.bpo_loa( + dir_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + bpo_enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + ) as dir: + assert not dir.is_closed + assert dir.http_request.headers.get("X-Stainless-Lang") == "python" + + assert dir.json() == {"foo": "bar"} + assert cast(Any, dir.is_closed) is True + assert isinstance(dir, StreamedBinaryAPIResponse) + + assert cast(Any, dir.is_closed) is True + + @parametrize + @pytest.mark.respx(base_url=base_url) + def test_path_params_bpo_loa(self, client: Telnyx) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `dir_id` but received ''"): + client.dir.with_raw_response.bpo_loa( + dir_id="", + bpo_enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + ) + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_method_list_document_types(self, client: Telnyx) -> None: @@ -399,6 +487,58 @@ def test_path_params_new_loa(self, client: Telnyx) -> None: phone_numbers=["+13125550000"], ) + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_retrieve_bpo_authorizations(self, client: Telnyx) -> None: + dir = client.dir.retrieve_bpo_authorizations( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + ) + assert_matches_type(DirRetrieveBpoAuthorizationsResponse, dir, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_retrieve_bpo_authorizations_with_all_params(self, client: Telnyx) -> None: + dir = client.dir.retrieve_bpo_authorizations( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + page_number=1, + page_size=20, + ) + assert_matches_type(DirRetrieveBpoAuthorizationsResponse, dir, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_retrieve_bpo_authorizations(self, client: Telnyx) -> None: + response = client.dir.with_raw_response.retrieve_bpo_authorizations( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + dir = response.parse() + assert_matches_type(DirRetrieveBpoAuthorizationsResponse, dir, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_retrieve_bpo_authorizations(self, client: Telnyx) -> None: + with client.dir.with_streaming_response.retrieve_bpo_authorizations( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + dir = response.parse() + assert_matches_type(DirRetrieveBpoAuthorizationsResponse, dir, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_path_params_retrieve_bpo_authorizations(self, client: Telnyx) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `dir_id` but received ''"): + client.dir.with_raw_response.retrieve_bpo_authorizations( + dir_id="", + ) + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_method_submit(self, client: Telnyx) -> None: @@ -589,6 +729,12 @@ async def test_method_update_with_all_params(self, async_client: AsyncTelnyx) -> dir_id="16635d38-75a6-4481-82e8-69af60e05011", authorizer_email="dev@stainless.com", authorizer_name="authorizer_name", + bpo_authorizations=[ + { + "bpo_enterprise_id": "4a6192a4-573d-446d-b3ce-aff9117272a6", + "loa_document_id": "2a7e8337-e803-4057-a4ae-26c40eb0bc6c", + } + ], call_reasons=["Appointment reminders", "Billing inquiries", "Lab results"], certify_brand_is_accurate=True, certify_ip_ownership=True, @@ -603,6 +749,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncTelnyx) -> ], logo_url="https://acmeplumbing.example.com/logo-v2-256.bmp", reselling=True, + webhook_url="https://mapleridge.example.com/webhooks/branded-calling", ) assert_matches_type(DirWrapped, dir, path=["response"]) @@ -690,7 +837,7 @@ async def test_method_delete(self, async_client: AsyncTelnyx) -> None: dir = await async_client.dir.delete( "16635d38-75a6-4481-82e8-69af60e05011", ) - assert dir is None + assert_matches_type(DirDeleteResponse, dir, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -702,7 +849,7 @@ async def test_raw_response_delete(self, async_client: AsyncTelnyx) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" dir = await response.parse() - assert dir is None + assert_matches_type(DirDeleteResponse, dir, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -714,7 +861,7 @@ async def test_streaming_response_delete(self, async_client: AsyncTelnyx) -> Non assert response.http_request.headers.get("X-Stainless-Lang") == "python" dir = await response.parse() - assert dir is None + assert_matches_type(DirDeleteResponse, dir, path=["response"]) assert cast(Any, response.is_closed) is True @@ -726,6 +873,85 @@ async def test_path_params_delete(self, async_client: AsyncTelnyx) -> None: "", ) + @parametrize + @pytest.mark.respx(base_url=base_url) + async def test_method_bpo_loa(self, async_client: AsyncTelnyx, respx_mock: MockRouter) -> None: + respx_mock.post("/dir/182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e/bpo_loa").mock( + return_value=httpx.Response(200, json={"foo": "bar"}) + ) + dir = await async_client.dir.bpo_loa( + dir_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + bpo_enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + ) + assert dir.is_closed + assert await dir.json() == {"foo": "bar"} + assert cast(Any, dir.is_closed) is True + assert isinstance(dir, AsyncBinaryAPIResponse) + + @parametrize + @pytest.mark.respx(base_url=base_url) + async def test_method_bpo_loa_with_all_params(self, async_client: AsyncTelnyx, respx_mock: MockRouter) -> None: + respx_mock.post("/dir/182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e/bpo_loa").mock( + return_value=httpx.Response(200, json={"foo": "bar"}) + ) + dir = await async_client.dir.bpo_loa( + dir_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + bpo_enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + signature={ + "image_base64": "x", + "signer_name": "signer_name", + }, + ) + assert dir.is_closed + assert await dir.json() == {"foo": "bar"} + assert cast(Any, dir.is_closed) is True + assert isinstance(dir, AsyncBinaryAPIResponse) + + @parametrize + @pytest.mark.respx(base_url=base_url) + async def test_raw_response_bpo_loa(self, async_client: AsyncTelnyx, respx_mock: MockRouter) -> None: + respx_mock.post("/dir/182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e/bpo_loa").mock( + return_value=httpx.Response(200, json={"foo": "bar"}) + ) + + dir = await async_client.dir.with_raw_response.bpo_loa( + dir_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + bpo_enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + ) + + assert dir.is_closed is True + assert dir.http_request.headers.get("X-Stainless-Lang") == "python" + assert await dir.json() == {"foo": "bar"} + assert isinstance(dir, AsyncBinaryAPIResponse) + + @parametrize + @pytest.mark.respx(base_url=base_url) + async def test_streaming_response_bpo_loa(self, async_client: AsyncTelnyx, respx_mock: MockRouter) -> None: + respx_mock.post("/dir/182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e/bpo_loa").mock( + return_value=httpx.Response(200, json={"foo": "bar"}) + ) + async with async_client.dir.with_streaming_response.bpo_loa( + dir_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + bpo_enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + ) as dir: + assert not dir.is_closed + assert dir.http_request.headers.get("X-Stainless-Lang") == "python" + + assert await dir.json() == {"foo": "bar"} + assert cast(Any, dir.is_closed) is True + assert isinstance(dir, AsyncStreamedBinaryAPIResponse) + + assert cast(Any, dir.is_closed) is True + + @parametrize + @pytest.mark.respx(base_url=base_url) + async def test_path_params_bpo_loa(self, async_client: AsyncTelnyx) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `dir_id` but received ''"): + await async_client.dir.with_raw_response.bpo_loa( + dir_id="", + bpo_enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + ) + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_method_list_document_types(self, async_client: AsyncTelnyx) -> None: @@ -899,6 +1125,58 @@ async def test_path_params_new_loa(self, async_client: AsyncTelnyx) -> None: phone_numbers=["+13125550000"], ) + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_retrieve_bpo_authorizations(self, async_client: AsyncTelnyx) -> None: + dir = await async_client.dir.retrieve_bpo_authorizations( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + ) + assert_matches_type(DirRetrieveBpoAuthorizationsResponse, dir, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_retrieve_bpo_authorizations_with_all_params(self, async_client: AsyncTelnyx) -> None: + dir = await async_client.dir.retrieve_bpo_authorizations( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + page_number=1, + page_size=20, + ) + assert_matches_type(DirRetrieveBpoAuthorizationsResponse, dir, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_retrieve_bpo_authorizations(self, async_client: AsyncTelnyx) -> None: + response = await async_client.dir.with_raw_response.retrieve_bpo_authorizations( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + dir = await response.parse() + assert_matches_type(DirRetrieveBpoAuthorizationsResponse, dir, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_retrieve_bpo_authorizations(self, async_client: AsyncTelnyx) -> None: + async with async_client.dir.with_streaming_response.retrieve_bpo_authorizations( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + dir = await response.parse() + assert_matches_type(DirRetrieveBpoAuthorizationsResponse, dir, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_path_params_retrieve_bpo_authorizations(self, async_client: AsyncTelnyx) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `dir_id` but received ''"): + await async_client.dir.with_raw_response.retrieve_bpo_authorizations( + dir_id="", + ) + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_method_submit(self, async_client: AsyncTelnyx) -> None: diff --git a/tests/api_resources/test_enterprises.py b/tests/api_resources/test_enterprises.py index 94d61dbb0..de481ecad 100644 --- a/tests/api_resources/test_enterprises.py +++ b/tests/api_resources/test_enterprises.py @@ -360,6 +360,7 @@ def test_method_list(self, client: Telnyx) -> None: def test_method_list_with_all_params(self, client: Telnyx) -> None: enterprise = client.enterprises.list( filter_legal_name_contains="Acme", + filter_role_type="bpo", legal_name="Acme", page_number=1, page_size=10, @@ -817,6 +818,7 @@ async def test_method_list(self, async_client: AsyncTelnyx) -> None: async def test_method_list_with_all_params(self, async_client: AsyncTelnyx) -> None: enterprise = await async_client.enterprises.list( filter_legal_name_contains="Acme", + filter_role_type="bpo", legal_name="Acme", page_number=1, page_size=10, diff --git a/tests/api_resources/test_spend_limits.py b/tests/api_resources/test_spend_limits.py new file mode 100644 index 000000000..df6fc03e6 --- /dev/null +++ b/tests/api_resources/test_spend_limits.py @@ -0,0 +1,611 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from telnyx import Telnyx, AsyncTelnyx +from tests.utils import assert_matches_type +from telnyx.types import ( + SpendLimitResponse, + SpendLimitListResponse, +) + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestSpendLimits: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_create_overload_1(self, client: Telnyx) -> None: + spend_limit = client.spend_limits.create( + amount=100, + product="inference", + ) + assert_matches_type(SpendLimitResponse, spend_limit, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_create_with_all_params_overload_1(self, client: Telnyx) -> None: + spend_limit = client.spend_limits.create( + amount=100, + product="inference", + period="daily", + reason="Team budget", + unlimited=False, + ) + assert_matches_type(SpendLimitResponse, spend_limit, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_create_overload_1(self, client: Telnyx) -> None: + response = client.spend_limits.with_raw_response.create( + amount=100, + product="inference", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + spend_limit = response.parse() + assert_matches_type(SpendLimitResponse, spend_limit, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_create_overload_1(self, client: Telnyx) -> None: + with client.spend_limits.with_streaming_response.create( + amount=100, + product="inference", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + spend_limit = response.parse() + assert_matches_type(SpendLimitResponse, spend_limit, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_create_overload_2(self, client: Telnyx) -> None: + spend_limit = client.spend_limits.create( + product="inference", + unlimited=True, + ) + assert_matches_type(SpendLimitResponse, spend_limit, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_create_with_all_params_overload_2(self, client: Telnyx) -> None: + spend_limit = client.spend_limits.create( + product="inference", + unlimited=True, + period="daily", + reason="Team budget", + ) + assert_matches_type(SpendLimitResponse, spend_limit, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_create_overload_2(self, client: Telnyx) -> None: + response = client.spend_limits.with_raw_response.create( + product="inference", + unlimited=True, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + spend_limit = response.parse() + assert_matches_type(SpendLimitResponse, spend_limit, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_create_overload_2(self, client: Telnyx) -> None: + with client.spend_limits.with_streaming_response.create( + product="inference", + unlimited=True, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + spend_limit = response.parse() + assert_matches_type(SpendLimitResponse, spend_limit, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_update_overload_1(self, client: Telnyx) -> None: + spend_limit = client.spend_limits.update( + product="inference", + amount=100, + ) + assert_matches_type(SpendLimitResponse, spend_limit, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_update_with_all_params_overload_1(self, client: Telnyx) -> None: + spend_limit = client.spend_limits.update( + product="inference", + amount=100, + period="daily", + reason="Raised for the product launch", + unlimited=False, + ) + assert_matches_type(SpendLimitResponse, spend_limit, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_update_overload_1(self, client: Telnyx) -> None: + response = client.spend_limits.with_raw_response.update( + product="inference", + amount=100, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + spend_limit = response.parse() + assert_matches_type(SpendLimitResponse, spend_limit, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_update_overload_1(self, client: Telnyx) -> None: + with client.spend_limits.with_streaming_response.update( + product="inference", + amount=100, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + spend_limit = response.parse() + assert_matches_type(SpendLimitResponse, spend_limit, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_path_params_update_overload_1(self, client: Telnyx) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `product` but received ''"): + client.spend_limits.with_raw_response.update( + product="", + amount=100, + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_update_overload_2(self, client: Telnyx) -> None: + spend_limit = client.spend_limits.update( + product="inference", + unlimited=True, + ) + assert_matches_type(SpendLimitResponse, spend_limit, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_update_with_all_params_overload_2(self, client: Telnyx) -> None: + spend_limit = client.spend_limits.update( + product="inference", + unlimited=True, + period="daily", + reason="Raised for the product launch", + ) + assert_matches_type(SpendLimitResponse, spend_limit, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_update_overload_2(self, client: Telnyx) -> None: + response = client.spend_limits.with_raw_response.update( + product="inference", + unlimited=True, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + spend_limit = response.parse() + assert_matches_type(SpendLimitResponse, spend_limit, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_update_overload_2(self, client: Telnyx) -> None: + with client.spend_limits.with_streaming_response.update( + product="inference", + unlimited=True, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + spend_limit = response.parse() + assert_matches_type(SpendLimitResponse, spend_limit, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_path_params_update_overload_2(self, client: Telnyx) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `product` but received ''"): + client.spend_limits.with_raw_response.update( + product="", + unlimited=True, + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_list(self, client: Telnyx) -> None: + spend_limit = client.spend_limits.list() + assert_matches_type(SpendLimitListResponse, spend_limit, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_list(self, client: Telnyx) -> None: + response = client.spend_limits.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + spend_limit = response.parse() + assert_matches_type(SpendLimitListResponse, spend_limit, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_list(self, client: Telnyx) -> None: + with client.spend_limits.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + spend_limit = response.parse() + assert_matches_type(SpendLimitListResponse, spend_limit, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_delete(self, client: Telnyx) -> None: + spend_limit = client.spend_limits.delete( + product="inference", + ) + assert_matches_type(SpendLimitResponse, spend_limit, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_delete_with_all_params(self, client: Telnyx) -> None: + spend_limit = client.spend_limits.delete( + product="inference", + period="daily", + reason="reason", + ) + assert_matches_type(SpendLimitResponse, spend_limit, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_delete(self, client: Telnyx) -> None: + response = client.spend_limits.with_raw_response.delete( + product="inference", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + spend_limit = response.parse() + assert_matches_type(SpendLimitResponse, spend_limit, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_delete(self, client: Telnyx) -> None: + with client.spend_limits.with_streaming_response.delete( + product="inference", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + spend_limit = response.parse() + assert_matches_type(SpendLimitResponse, spend_limit, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_path_params_delete(self, client: Telnyx) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `product` but received ''"): + client.spend_limits.with_raw_response.delete( + product="", + ) + + +class TestAsyncSpendLimits: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_create_overload_1(self, async_client: AsyncTelnyx) -> None: + spend_limit = await async_client.spend_limits.create( + amount=100, + product="inference", + ) + assert_matches_type(SpendLimitResponse, spend_limit, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_create_with_all_params_overload_1(self, async_client: AsyncTelnyx) -> None: + spend_limit = await async_client.spend_limits.create( + amount=100, + product="inference", + period="daily", + reason="Team budget", + unlimited=False, + ) + assert_matches_type(SpendLimitResponse, spend_limit, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_create_overload_1(self, async_client: AsyncTelnyx) -> None: + response = await async_client.spend_limits.with_raw_response.create( + amount=100, + product="inference", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + spend_limit = await response.parse() + assert_matches_type(SpendLimitResponse, spend_limit, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_create_overload_1(self, async_client: AsyncTelnyx) -> None: + async with async_client.spend_limits.with_streaming_response.create( + amount=100, + product="inference", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + spend_limit = await response.parse() + assert_matches_type(SpendLimitResponse, spend_limit, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_create_overload_2(self, async_client: AsyncTelnyx) -> None: + spend_limit = await async_client.spend_limits.create( + product="inference", + unlimited=True, + ) + assert_matches_type(SpendLimitResponse, spend_limit, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_create_with_all_params_overload_2(self, async_client: AsyncTelnyx) -> None: + spend_limit = await async_client.spend_limits.create( + product="inference", + unlimited=True, + period="daily", + reason="Team budget", + ) + assert_matches_type(SpendLimitResponse, spend_limit, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_create_overload_2(self, async_client: AsyncTelnyx) -> None: + response = await async_client.spend_limits.with_raw_response.create( + product="inference", + unlimited=True, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + spend_limit = await response.parse() + assert_matches_type(SpendLimitResponse, spend_limit, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_create_overload_2(self, async_client: AsyncTelnyx) -> None: + async with async_client.spend_limits.with_streaming_response.create( + product="inference", + unlimited=True, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + spend_limit = await response.parse() + assert_matches_type(SpendLimitResponse, spend_limit, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_update_overload_1(self, async_client: AsyncTelnyx) -> None: + spend_limit = await async_client.spend_limits.update( + product="inference", + amount=100, + ) + assert_matches_type(SpendLimitResponse, spend_limit, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_update_with_all_params_overload_1(self, async_client: AsyncTelnyx) -> None: + spend_limit = await async_client.spend_limits.update( + product="inference", + amount=100, + period="daily", + reason="Raised for the product launch", + unlimited=False, + ) + assert_matches_type(SpendLimitResponse, spend_limit, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_update_overload_1(self, async_client: AsyncTelnyx) -> None: + response = await async_client.spend_limits.with_raw_response.update( + product="inference", + amount=100, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + spend_limit = await response.parse() + assert_matches_type(SpendLimitResponse, spend_limit, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_update_overload_1(self, async_client: AsyncTelnyx) -> None: + async with async_client.spend_limits.with_streaming_response.update( + product="inference", + amount=100, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + spend_limit = await response.parse() + assert_matches_type(SpendLimitResponse, spend_limit, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_path_params_update_overload_1(self, async_client: AsyncTelnyx) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `product` but received ''"): + await async_client.spend_limits.with_raw_response.update( + product="", + amount=100, + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_update_overload_2(self, async_client: AsyncTelnyx) -> None: + spend_limit = await async_client.spend_limits.update( + product="inference", + unlimited=True, + ) + assert_matches_type(SpendLimitResponse, spend_limit, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_update_with_all_params_overload_2(self, async_client: AsyncTelnyx) -> None: + spend_limit = await async_client.spend_limits.update( + product="inference", + unlimited=True, + period="daily", + reason="Raised for the product launch", + ) + assert_matches_type(SpendLimitResponse, spend_limit, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_update_overload_2(self, async_client: AsyncTelnyx) -> None: + response = await async_client.spend_limits.with_raw_response.update( + product="inference", + unlimited=True, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + spend_limit = await response.parse() + assert_matches_type(SpendLimitResponse, spend_limit, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_update_overload_2(self, async_client: AsyncTelnyx) -> None: + async with async_client.spend_limits.with_streaming_response.update( + product="inference", + unlimited=True, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + spend_limit = await response.parse() + assert_matches_type(SpendLimitResponse, spend_limit, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_path_params_update_overload_2(self, async_client: AsyncTelnyx) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `product` but received ''"): + await async_client.spend_limits.with_raw_response.update( + product="", + unlimited=True, + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_list(self, async_client: AsyncTelnyx) -> None: + spend_limit = await async_client.spend_limits.list() + assert_matches_type(SpendLimitListResponse, spend_limit, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_list(self, async_client: AsyncTelnyx) -> None: + response = await async_client.spend_limits.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + spend_limit = await response.parse() + assert_matches_type(SpendLimitListResponse, spend_limit, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_list(self, async_client: AsyncTelnyx) -> None: + async with async_client.spend_limits.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + spend_limit = await response.parse() + assert_matches_type(SpendLimitListResponse, spend_limit, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_delete(self, async_client: AsyncTelnyx) -> None: + spend_limit = await async_client.spend_limits.delete( + product="inference", + ) + assert_matches_type(SpendLimitResponse, spend_limit, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_delete_with_all_params(self, async_client: AsyncTelnyx) -> None: + spend_limit = await async_client.spend_limits.delete( + product="inference", + period="daily", + reason="reason", + ) + assert_matches_type(SpendLimitResponse, spend_limit, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_delete(self, async_client: AsyncTelnyx) -> None: + response = await async_client.spend_limits.with_raw_response.delete( + product="inference", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + spend_limit = await response.parse() + assert_matches_type(SpendLimitResponse, spend_limit, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_delete(self, async_client: AsyncTelnyx) -> None: + async with async_client.spend_limits.with_streaming_response.delete( + product="inference", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + spend_limit = await response.parse() + assert_matches_type(SpendLimitResponse, spend_limit, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_path_params_delete(self, async_client: AsyncTelnyx) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `product` but received ''"): + await async_client.spend_limits.with_raw_response.delete( + product="", + ) diff --git a/tests/api_resources/whatsapp/phone_numbers/test_calling_routing.py b/tests/api_resources/whatsapp/phone_numbers/test_calling_routing.py new file mode 100644 index 000000000..2712a1cde --- /dev/null +++ b/tests/api_resources/whatsapp/phone_numbers/test_calling_routing.py @@ -0,0 +1,203 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from telnyx import Telnyx, AsyncTelnyx +from tests.utils import assert_matches_type +from telnyx.types.whatsapp.phone_numbers import ( + CallingRoutingListResponse, + CallingRoutingPatchAllResponse, +) + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestCallingRouting: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_list(self, client: Telnyx) -> None: + calling_routing = client.whatsapp.phone_numbers.calling_routing.list( + "+13125550100", + ) + assert_matches_type(CallingRoutingListResponse, calling_routing, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_list(self, client: Telnyx) -> None: + response = client.whatsapp.phone_numbers.calling_routing.with_raw_response.list( + "+13125550100", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + calling_routing = response.parse() + assert_matches_type(CallingRoutingListResponse, calling_routing, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_list(self, client: Telnyx) -> None: + with client.whatsapp.phone_numbers.calling_routing.with_streaming_response.list( + "+13125550100", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + calling_routing = response.parse() + assert_matches_type(CallingRoutingListResponse, calling_routing, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_path_params_list(self, client: Telnyx) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.whatsapp.phone_numbers.calling_routing.with_raw_response.list( + "", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_patch_all(self, client: Telnyx) -> None: + calling_routing = client.whatsapp.phone_numbers.calling_routing.patch_all( + id="+13125550100", + connection_id="1234567890", + ) + assert_matches_type(CallingRoutingPatchAllResponse, calling_routing, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_patch_all(self, client: Telnyx) -> None: + response = client.whatsapp.phone_numbers.calling_routing.with_raw_response.patch_all( + id="+13125550100", + connection_id="1234567890", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + calling_routing = response.parse() + assert_matches_type(CallingRoutingPatchAllResponse, calling_routing, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_patch_all(self, client: Telnyx) -> None: + with client.whatsapp.phone_numbers.calling_routing.with_streaming_response.patch_all( + id="+13125550100", + connection_id="1234567890", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + calling_routing = response.parse() + assert_matches_type(CallingRoutingPatchAllResponse, calling_routing, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_path_params_patch_all(self, client: Telnyx) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.whatsapp.phone_numbers.calling_routing.with_raw_response.patch_all( + id="", + connection_id="1234567890", + ) + + +class TestAsyncCallingRouting: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_list(self, async_client: AsyncTelnyx) -> None: + calling_routing = await async_client.whatsapp.phone_numbers.calling_routing.list( + "+13125550100", + ) + assert_matches_type(CallingRoutingListResponse, calling_routing, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_list(self, async_client: AsyncTelnyx) -> None: + response = await async_client.whatsapp.phone_numbers.calling_routing.with_raw_response.list( + "+13125550100", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + calling_routing = await response.parse() + assert_matches_type(CallingRoutingListResponse, calling_routing, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_list(self, async_client: AsyncTelnyx) -> None: + async with async_client.whatsapp.phone_numbers.calling_routing.with_streaming_response.list( + "+13125550100", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + calling_routing = await response.parse() + assert_matches_type(CallingRoutingListResponse, calling_routing, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_path_params_list(self, async_client: AsyncTelnyx) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.whatsapp.phone_numbers.calling_routing.with_raw_response.list( + "", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_patch_all(self, async_client: AsyncTelnyx) -> None: + calling_routing = await async_client.whatsapp.phone_numbers.calling_routing.patch_all( + id="+13125550100", + connection_id="1234567890", + ) + assert_matches_type(CallingRoutingPatchAllResponse, calling_routing, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_patch_all(self, async_client: AsyncTelnyx) -> None: + response = await async_client.whatsapp.phone_numbers.calling_routing.with_raw_response.patch_all( + id="+13125550100", + connection_id="1234567890", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + calling_routing = await response.parse() + assert_matches_type(CallingRoutingPatchAllResponse, calling_routing, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_patch_all(self, async_client: AsyncTelnyx) -> None: + async with async_client.whatsapp.phone_numbers.calling_routing.with_streaming_response.patch_all( + id="+13125550100", + connection_id="1234567890", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + calling_routing = await response.parse() + assert_matches_type(CallingRoutingPatchAllResponse, calling_routing, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_path_params_patch_all(self, async_client: AsyncTelnyx) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.whatsapp.phone_numbers.calling_routing.with_raw_response.patch_all( + id="", + connection_id="1234567890", + ) diff --git a/uv.lock b/uv.lock index 70e1396ba..270ac7c87 100644 --- a/uv.lock +++ b/uv.lock @@ -1,5 +1,5 @@ version = 1 -revision = 3 +revision = 5 requires-python = ">=3.9" resolution-markers = [ "python_full_version >= '3.14' and extra != 'group-6-telnyx-pydantic-v1' and extra == 'group-6-telnyx-pydantic-v2'",