From a2c999f01668f86406e50c6a32fbefc099ae938b Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 5 Jun 2026 18:52:45 +0000 Subject: [PATCH 1/2] feat: NUM-6470: Add branded-calling-v2 OpenAPI specs (external + internal) --- .stats.yml | 8 +- api.md | 229 ++- src/telnyx/_client.py | 186 ++- src/telnyx/resources/__init__.py | 42 + .../resources/ai/assistants/assistants.py | 54 +- .../resources/ai/assistants/canary_deploys.py | 9 +- .../resources/ai/assistants/versions.py | 30 +- src/telnyx/resources/call_reasons.py | 307 +++++ src/telnyx/resources/dir/__init__.py | 61 + src/telnyx/resources/dir/comments.py | 355 +++++ src/telnyx/resources/dir/dir.py | 1227 +++++++++++++++++ .../resources/dir/phone_number_batches.py | 319 +++++ src/telnyx/resources/dir/phone_numbers.py | 445 ++++++ src/telnyx/resources/enterprises/__init__.py | 14 + src/telnyx/resources/enterprises/dir.py | 571 ++++++++ .../resources/enterprises/enterprises.py | 682 ++++++--- .../enterprises/reputation/__init__.py | 14 + .../resources/enterprises/reputation/loa.py | 323 +++++ .../enterprises/reputation/numbers.py | 276 ++-- .../enterprises/reputation/reputation.py | 242 ++-- src/telnyx/resources/infringement_claims.py | 320 +++++ .../resources/public_internet_gateways.py | 16 +- src/telnyx/resources/reputation/numbers.py | 86 +- src/telnyx/resources/reputation/reputation.py | 24 +- .../resources/terms_of_service/__init__.py | 28 + .../resources/terms_of_service/agreements.py | 321 +++++ .../terms_of_service/branded_calling.py | 159 +++ .../terms_of_service/number_reputation.py | 41 +- .../terms_of_service/terms_of_service.py | 257 +++- .../uac_connections/uac_connections.py | 41 +- .../resources/virtual_cross_connects.py | 14 +- src/telnyx/resources/wireguard_interfaces.py | 14 +- src/telnyx/types/__init__.py | 47 +- src/telnyx/types/ai/__init__.py | 20 - .../types/ai/assistant_create_params.py | 267 +++- src/telnyx/types/ai/assistant_integration.py | 30 - .../types/ai/assistant_integration_param.py | 32 - src/telnyx/types/ai/assistant_mcp_server.py | 27 - .../types/ai/assistant_mcp_server_param.py | 29 - src/telnyx/types/ai/assistant_tool.py | 12 +- src/telnyx/types/ai/assistant_tool_param.py | 12 +- .../types/ai/assistant_update_params.py | 267 +++- src/telnyx/types/ai/assistants/__init__.py | 8 - .../assistants/canary_deploy_create_params.py | 65 +- .../ai/assistants/canary_deploy_response.py | 65 +- .../assistants/canary_deploy_update_params.py | 65 +- src/telnyx/types/ai/assistants/clause.py | 24 - .../types/ai/assistants/clause_param.py | 25 - .../types/ai/assistants/rollout_slot.py | 13 - .../types/ai/assistants/rollout_slot_param.py | 15 - .../types/ai/assistants/rule_input_param.py | 30 - src/telnyx/types/ai/assistants/rule_output.py | 28 - src/telnyx/types/ai/assistants/serve.py | 22 - src/telnyx/types/ai/assistants/serve_param.py | 24 - .../ai/assistants/version_update_params.py | 267 +++- src/telnyx/types/ai/external_llm.py | 44 - src/telnyx/types/ai/external_llm_req_param.py | 43 - src/telnyx/types/ai/fallback_config.py | 21 - .../types/ai/fallback_config_req_param.py | 22 - src/telnyx/types/ai/inference_embedding.py | 261 +++- ...ference_embedding_interruption_settings.py | 28 - ...e_embedding_interruption_settings_param.py | 29 - .../types/ai/openai_list_models_response.py | 124 +- .../types/ai/post_conversation_settings.py | 21 - .../post_conversation_settings_req_param.py | 21 - src/telnyx/types/ai/start_speaking_plan.py | 26 - .../types/ai/start_speaking_plan_param.py | 27 - .../ai/transcription_endpointing_plan.py | 23 - .../transcription_endpointing_plan_param.py | 23 - src/telnyx/types/ai/transfer_tool_param.py | 6 +- .../types/ai_retrieve_models_response.py | 124 +- src/telnyx/types/billing_address.py | 8 +- src/telnyx/types/billing_address_param.py | 8 +- src/telnyx/types/billing_contact.py | 5 +- src/telnyx/types/billing_contact_param.py | 5 +- src/telnyx/types/call_dial_params.py | 23 +- src/telnyx/types/call_reason_list_params.py | 25 + src/telnyx/types/call_reason_list_response.py | 17 + .../types/call_reason_validate_params.py | 18 + .../types/call_reason_validate_response.py | 33 + src/telnyx/types/calls/__init__.py | 6 - .../types/calls/action_answer_params.py | 23 +- .../calls/action_gather_using_ai_params.py | 13 +- .../calls/action_gather_using_speak_params.py | 18 +- src/telnyx/types/calls/action_speak_params.py | 13 +- .../calls/action_start_ai_assistant_params.py | 12 +- .../action_start_conversation_relay_params.py | 34 +- .../action_start_transcription_params.py | 65 +- ...cription_engine_assemblyai_config_param.py | 21 - .../transcription_engine_xai_config_param.py | 50 - .../transcription_start_request_param.py | 65 +- .../types/conferences/action_speak_params.py | 13 +- src/telnyx/types/dir/__init__.py | 17 + src/telnyx/types/dir/comment_create_params.py | 15 + .../types/dir/comment_create_response.py | 51 + src/telnyx/types/dir/comment_list_params.py | 35 + src/telnyx/types/dir/comment_list_response.py | 47 + .../types/dir/phone_number_add_params.py | 61 + .../types/dir/phone_number_add_response.py | 82 ++ .../dir/phone_number_batch_list_params.py | 26 + .../dir/phone_number_batch_list_response.py | 141 ++ .../phone_number_batch_retrieve_response.py | 157 +++ .../types/dir/phone_number_list_params.py | 25 + .../types/dir/phone_number_list_response.py | 69 + .../types/dir/phone_number_remove_params.py | 13 + .../types/dir/phone_number_remove_response.py | 48 + .../types/dir_list_document_types_response.py | 50 + .../dir_list_infringement_claims_params.py | 20 + .../dir_list_infringement_claims_response.py | 145 ++ src/telnyx/types/dir_list_params.py | 64 + src/telnyx/types/dir_list_response.py | 135 ++ src/telnyx/types/dir_retrieve_response.py | 139 ++ src/telnyx/types/dir_submit_response.py | 139 ++ .../types/dir_update_infringement_params.py | 71 + .../types/dir_update_infringement_response.py | 139 ++ src/telnyx/types/dir_update_params.py | 41 + src/telnyx/types/dir_update_response.py | 139 ++ ...prise_activate_branded_calling_response.py | 10 + src/telnyx/types/enterprise_create_params.py | 130 +- .../types/enterprise_create_response.py | 4 +- src/telnyx/types/enterprise_list_params.py | 9 +- src/telnyx/types/enterprise_public.py | 52 +- .../types/enterprise_retrieve_response.py | 4 +- src/telnyx/types/enterprise_update_params.py | 80 +- .../types/enterprise_update_response.py | 4 +- src/telnyx/types/enterprises/__init__.py | 4 + src/telnyx/types/enterprises/dir/__init__.py | 3 + .../types/enterprises/dir_create_params.py | 93 ++ .../types/enterprises/dir_create_response.py | 139 ++ .../types/enterprises/dir_list_params.py | 80 ++ .../types/enterprises/dir_list_response.py | 135 ++ .../enterprise_reputation_public.py | 23 +- .../types/enterprises/reputation/__init__.py | 6 + .../reputation/loa_render_params.py | 65 + .../reputation/loa_update_params.py | 16 + .../reputation/loa_update_response.py | 10 + .../reputation/number_associate_params.py | 2 +- .../reputation/number_associate_response.py | 45 +- .../reputation/number_list_params.py | 9 +- .../reputation/number_list_response.py | 25 + .../reputation/number_refresh_params.py | 18 + .../reputation/number_refresh_response.py | 31 + .../reputation/number_retrieve_params.py | 2 +- .../reputation/number_retrieve_response.py | 23 +- .../enterprises/reputation_enable_params.py | 10 +- .../enterprises/reputation_enable_response.py | 4 +- .../reputation_retrieve_response.py | 4 +- .../reputation_update_frequency_params.py | 5 +- .../reputation_update_frequency_response.py | 4 +- .../infringement_claim_contest_params.py | 54 + .../infringement_claim_contest_response.py | 149 ++ .../infringement_claim_retrieve_response.py | 149 ++ src/telnyx/types/model_metadata.py | 124 -- src/telnyx/types/network_interface.py | 19 + .../types/network_list_interfaces_response.py | 31 +- src/telnyx/types/organization_contact.py | 13 +- .../types/organization_contact_param.py | 13 +- src/telnyx/types/physical_address.py | 8 +- src/telnyx/types/physical_address_param.py | 8 +- ...public_internet_gateway_create_response.py | 15 +- ...public_internet_gateway_delete_response.py | 15 +- .../public_internet_gateway_list_response.py | 16 + .../types/public_internet_gateway_read.py | 37 - ...blic_internet_gateway_retrieve_response.py | 15 +- src/telnyx/types/reputation/__init__.py | 1 + .../types/reputation/number_list_params.py | 9 +- .../number_list_response.py} | 14 +- .../reputation/number_retrieve_params.py | 2 +- .../reputation/number_retrieve_response.py | 23 +- src/telnyx/types/shared/__init__.py | 5 - src/telnyx/types/shared/meta_info.py | 21 - src/telnyx/types/shared/reputation_data.py | 14 +- src/telnyx/types/shared/xai_voice_settings.py | 16 - src/telnyx/types/shared_params/__init__.py | 1 - .../types/shared_params/xai_voice_settings.py | 15 - src/telnyx/types/terms_of_service/__init__.py | 6 + .../terms_of_service/agreement_list_params.py | 27 + .../agreement_list_response.py | 30 + .../agreement_retrieve_response.py | 39 + .../branded_calling_agree_response.py | 39 + .../number_reputation_agree_response.py | 39 + .../types/terms_of_service_status_params.py | 16 + .../types/terms_of_service_status_response.py | 47 + src/telnyx/types/uac_connection.py | 196 --- .../types/uac_connection_create_params.py | 132 +- .../types/uac_connection_create_response.py | 390 +++++- .../types/uac_connection_delete_response.py | 390 +++++- .../types/uac_connection_list_response.py | 383 +++++ .../types/uac_connection_retrieve_response.py | 390 +++++- .../types/uac_connection_update_params.py | 132 +- .../types/uac_connection_update_response.py | 390 +++++- src/telnyx/types/uac_external_settings.py | 60 - .../types/uac_external_settings_param.py | 60 - src/telnyx/types/uac_inbound.py | 76 - src/telnyx/types/uac_internal_settings.py | 20 - .../types/uac_internal_settings_param.py | 20 - src/telnyx/types/uac_outbound.py | 66 - src/telnyx/types/uac_outbound_param.py | 64 - .../types/virtual_cross_connect_combined.py | 84 -- .../virtual_cross_connect_create_response.py | 119 +- .../virtual_cross_connect_delete_response.py | 119 +- .../virtual_cross_connect_list_response.py | 121 ++ ...virtual_cross_connect_retrieve_response.py | 119 +- .../virtual_cross_connect_update_response.py | 119 +- .../wireguard_interface_create_response.py | 34 +- .../wireguard_interface_delete_response.py | 34 +- .../wireguard_interface_list_response.py | 36 + src/telnyx/types/wireguard_interface_read.py | 56 - .../wireguard_interface_retrieve_response.py | 34 +- tests/api_resources/dir/__init__.py | 1 + tests/api_resources/dir/test_comments.py | 243 ++++ .../dir/test_phone_number_batches.py | 254 ++++ tests/api_resources/dir/test_phone_numbers.py | 367 +++++ .../enterprises/reputation/test_loa.py | 300 ++++ .../enterprises/reputation/test_numbers.py | 247 ++-- tests/api_resources/enterprises/test_dir.py | 322 +++++ .../enterprises/test_reputation.py | 88 +- .../api_resources/reputation/test_numbers.py | 70 +- .../terms_of_service/test_agreements.py | 185 +++ .../terms_of_service/test_branded_calling.py | 80 ++ .../test_number_reputation.py | 14 +- tests/api_resources/test_call_reasons.py | 170 +++ tests/api_resources/test_dir.py | 814 +++++++++++ tests/api_resources/test_enterprises.py | 559 ++++---- .../api_resources/test_infringement_claims.py | 235 ++++ .../test_public_internet_gateways.py | 20 +- tests/api_resources/test_terms_of_service.py | 96 ++ tests/api_resources/test_uac_connections.py | 20 +- .../test_virtual_cross_connects.py | 18 +- .../test_wireguard_interfaces.py | 30 +- 230 files changed, 17962 insertions(+), 3190 deletions(-) create mode 100644 src/telnyx/resources/call_reasons.py create mode 100644 src/telnyx/resources/dir/__init__.py create mode 100644 src/telnyx/resources/dir/comments.py create mode 100644 src/telnyx/resources/dir/dir.py create mode 100644 src/telnyx/resources/dir/phone_number_batches.py create mode 100644 src/telnyx/resources/dir/phone_numbers.py create mode 100644 src/telnyx/resources/enterprises/dir.py create mode 100644 src/telnyx/resources/enterprises/reputation/loa.py create mode 100644 src/telnyx/resources/infringement_claims.py create mode 100644 src/telnyx/resources/terms_of_service/agreements.py create mode 100644 src/telnyx/resources/terms_of_service/branded_calling.py delete mode 100644 src/telnyx/types/ai/assistant_integration.py delete mode 100644 src/telnyx/types/ai/assistant_integration_param.py delete mode 100644 src/telnyx/types/ai/assistant_mcp_server.py delete mode 100644 src/telnyx/types/ai/assistant_mcp_server_param.py delete mode 100644 src/telnyx/types/ai/assistants/clause.py delete mode 100644 src/telnyx/types/ai/assistants/clause_param.py delete mode 100644 src/telnyx/types/ai/assistants/rollout_slot.py delete mode 100644 src/telnyx/types/ai/assistants/rollout_slot_param.py delete mode 100644 src/telnyx/types/ai/assistants/rule_input_param.py delete mode 100644 src/telnyx/types/ai/assistants/rule_output.py delete mode 100644 src/telnyx/types/ai/assistants/serve.py delete mode 100644 src/telnyx/types/ai/assistants/serve_param.py delete mode 100644 src/telnyx/types/ai/external_llm.py delete mode 100644 src/telnyx/types/ai/external_llm_req_param.py delete mode 100644 src/telnyx/types/ai/fallback_config.py delete mode 100644 src/telnyx/types/ai/fallback_config_req_param.py delete mode 100644 src/telnyx/types/ai/inference_embedding_interruption_settings.py delete mode 100644 src/telnyx/types/ai/inference_embedding_interruption_settings_param.py delete mode 100644 src/telnyx/types/ai/post_conversation_settings.py delete mode 100644 src/telnyx/types/ai/post_conversation_settings_req_param.py delete mode 100644 src/telnyx/types/ai/start_speaking_plan.py delete mode 100644 src/telnyx/types/ai/start_speaking_plan_param.py delete mode 100644 src/telnyx/types/ai/transcription_endpointing_plan.py delete mode 100644 src/telnyx/types/ai/transcription_endpointing_plan_param.py create mode 100644 src/telnyx/types/call_reason_list_params.py create mode 100644 src/telnyx/types/call_reason_list_response.py create mode 100644 src/telnyx/types/call_reason_validate_params.py create mode 100644 src/telnyx/types/call_reason_validate_response.py delete mode 100644 src/telnyx/types/calls/transcription_engine_assemblyai_config_param.py delete mode 100644 src/telnyx/types/calls/transcription_engine_xai_config_param.py create mode 100644 src/telnyx/types/dir/__init__.py create mode 100644 src/telnyx/types/dir/comment_create_params.py create mode 100644 src/telnyx/types/dir/comment_create_response.py create mode 100644 src/telnyx/types/dir/comment_list_params.py create mode 100644 src/telnyx/types/dir/comment_list_response.py create mode 100644 src/telnyx/types/dir/phone_number_add_params.py create mode 100644 src/telnyx/types/dir/phone_number_add_response.py create mode 100644 src/telnyx/types/dir/phone_number_batch_list_params.py create mode 100644 src/telnyx/types/dir/phone_number_batch_list_response.py create mode 100644 src/telnyx/types/dir/phone_number_batch_retrieve_response.py create mode 100644 src/telnyx/types/dir/phone_number_list_params.py create mode 100644 src/telnyx/types/dir/phone_number_list_response.py create mode 100644 src/telnyx/types/dir/phone_number_remove_params.py create mode 100644 src/telnyx/types/dir/phone_number_remove_response.py create mode 100644 src/telnyx/types/dir_list_document_types_response.py create mode 100644 src/telnyx/types/dir_list_infringement_claims_params.py create mode 100644 src/telnyx/types/dir_list_infringement_claims_response.py create mode 100644 src/telnyx/types/dir_list_params.py create mode 100644 src/telnyx/types/dir_list_response.py create mode 100644 src/telnyx/types/dir_retrieve_response.py create mode 100644 src/telnyx/types/dir_submit_response.py create mode 100644 src/telnyx/types/dir_update_infringement_params.py create mode 100644 src/telnyx/types/dir_update_infringement_response.py create mode 100644 src/telnyx/types/dir_update_params.py create mode 100644 src/telnyx/types/dir_update_response.py create mode 100644 src/telnyx/types/enterprise_activate_branded_calling_response.py create mode 100644 src/telnyx/types/enterprises/dir/__init__.py create mode 100644 src/telnyx/types/enterprises/dir_create_params.py create mode 100644 src/telnyx/types/enterprises/dir_create_response.py create mode 100644 src/telnyx/types/enterprises/dir_list_params.py create mode 100644 src/telnyx/types/enterprises/dir_list_response.py create mode 100644 src/telnyx/types/enterprises/reputation/loa_render_params.py create mode 100644 src/telnyx/types/enterprises/reputation/loa_update_params.py create mode 100644 src/telnyx/types/enterprises/reputation/loa_update_response.py create mode 100644 src/telnyx/types/enterprises/reputation/number_list_response.py create mode 100644 src/telnyx/types/enterprises/reputation/number_refresh_params.py create mode 100644 src/telnyx/types/enterprises/reputation/number_refresh_response.py create mode 100644 src/telnyx/types/infringement_claim_contest_params.py create mode 100644 src/telnyx/types/infringement_claim_contest_response.py create mode 100644 src/telnyx/types/infringement_claim_retrieve_response.py delete mode 100644 src/telnyx/types/model_metadata.py create mode 100644 src/telnyx/types/network_interface.py create mode 100644 src/telnyx/types/public_internet_gateway_list_response.py delete mode 100644 src/telnyx/types/public_internet_gateway_read.py rename src/telnyx/types/{shared/reputation_phone_number_with_reputation_data.py => reputation/number_list_response.py} (53%) delete mode 100644 src/telnyx/types/shared/meta_info.py delete mode 100644 src/telnyx/types/shared/xai_voice_settings.py delete mode 100644 src/telnyx/types/shared_params/xai_voice_settings.py create mode 100644 src/telnyx/types/terms_of_service/agreement_list_params.py create mode 100644 src/telnyx/types/terms_of_service/agreement_list_response.py create mode 100644 src/telnyx/types/terms_of_service/agreement_retrieve_response.py create mode 100644 src/telnyx/types/terms_of_service/branded_calling_agree_response.py create mode 100644 src/telnyx/types/terms_of_service/number_reputation_agree_response.py create mode 100644 src/telnyx/types/terms_of_service_status_params.py create mode 100644 src/telnyx/types/terms_of_service_status_response.py delete mode 100644 src/telnyx/types/uac_connection.py create mode 100644 src/telnyx/types/uac_connection_list_response.py delete mode 100644 src/telnyx/types/uac_external_settings.py delete mode 100644 src/telnyx/types/uac_external_settings_param.py delete mode 100644 src/telnyx/types/uac_inbound.py delete mode 100644 src/telnyx/types/uac_internal_settings.py delete mode 100644 src/telnyx/types/uac_internal_settings_param.py delete mode 100644 src/telnyx/types/uac_outbound.py delete mode 100644 src/telnyx/types/uac_outbound_param.py delete mode 100644 src/telnyx/types/virtual_cross_connect_combined.py create mode 100644 src/telnyx/types/virtual_cross_connect_list_response.py create mode 100644 src/telnyx/types/wireguard_interface_list_response.py delete mode 100644 src/telnyx/types/wireguard_interface_read.py create mode 100644 tests/api_resources/dir/__init__.py create mode 100644 tests/api_resources/dir/test_comments.py create mode 100644 tests/api_resources/dir/test_phone_number_batches.py create mode 100644 tests/api_resources/dir/test_phone_numbers.py create mode 100644 tests/api_resources/enterprises/reputation/test_loa.py create mode 100644 tests/api_resources/enterprises/test_dir.py create mode 100644 tests/api_resources/terms_of_service/test_agreements.py create mode 100644 tests/api_resources/terms_of_service/test_branded_calling.py create mode 100644 tests/api_resources/test_call_reasons.py create mode 100644 tests/api_resources/test_dir.py create mode 100644 tests/api_resources/test_infringement_claims.py create mode 100644 tests/api_resources/test_terms_of_service.py diff --git a/.stats.yml b/.stats.yml index e1653505..bbfd6264 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 1047 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/telnyx/telnyx-f0b674236fbd66f50b5a1706fafd8cb681459cf05379967fd1f043d38d6d476d.yml -openapi_spec_hash: 7ae2cfe4f10fc24e4376fd15cd3455e8 -config_hash: da8cae8a6100e4d90af920e222524d09 +configured_endpoints: 1076 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/telnyx/telnyx-7b8d117e2646843c69453ee88c0f30b7384c3764fbbc72c69f10a2b362bc0b44.yml +openapi_spec_hash: c1cb5e3e98c7a71c43fa94dc87635d25 +config_hash: 5ce01cd30f63029e0b785a241c80bae4 diff --git a/api.md b/api.md index ed55ffb2..f8e9a358 100644 --- a/api.md +++ b/api.md @@ -23,7 +23,6 @@ from telnyx.types import ( MessagingFeatureSet, MessagingHostedNumberOrder, MessagingPaginationMeta, - MetaInfo, Metadata, MinimaxVoiceSettings, NetappsLocation, @@ -34,7 +33,6 @@ from telnyx.types import ( PortingOrdersExceptionType, RegionInformation, ReputationData, - ReputationPhoneNumberWithReputationData, ResembleVoiceSettings, RimeVoiceSettings, RoomParticipant, @@ -43,7 +41,6 @@ from telnyx.types import ( SimpleSimCard, SubNumberOrderRegulatoryRequirementWithValue, WhatsappTemplateData, - XaiVoiceSettings, ) ``` @@ -573,7 +570,6 @@ Types: ```python from telnyx.types import ( - ModelMetadata, AICreateResponseDeprecatedResponse, AIRetrieveModelsResponse, AISummarizeResponse, @@ -593,33 +589,22 @@ Types: ```python from telnyx.types.ai import ( Assistant, - AssistantIntegration, - AssistantMcpServer, AssistantTool, AssistantsList, AudioVisualizerConfig, EnabledFeatures, - ExternalLlm, - ExternalLlmReq, - FallbackConfig, - FallbackConfigReq, HangupTool, HangupToolParams, ImportMetadata, InferenceEmbedding, - InferenceEmbeddingInterruptionSettings, InferenceEmbeddingWebhookToolParams, InsightSettings, MessagingSettings, Observability, ObservabilityReq, - PostConversationSettings, - PostConversationSettingsReq, PrivacySettings, RetrievalTool, - StartSpeakingPlan, TelephonySettings, - TranscriptionEndpointingPlan, TranscriptionSettings, TranscriptionSettingsConfig, TransferTool, @@ -710,15 +695,7 @@ Methods: Types: ```python -from telnyx.types.ai.assistants import ( - CanaryDeploy, - CanaryDeployResponse, - Clause, - RolloutSlot, - RuleInput, - RuleOutput, - Serve, -) +from telnyx.types.ai.assistants import CanaryDeploy, CanaryDeployResponse ``` Methods: @@ -1453,13 +1430,11 @@ from telnyx.types.calls import ( TelnyxVoiceSettings, TranscriptionConfig, TranscriptionEngineAConfig, - TranscriptionEngineAssemblyaiConfig, TranscriptionEngineAzureConfig, TranscriptionEngineBConfig, TranscriptionEngineDeepgramConfig, TranscriptionEngineGoogleConfig, TranscriptionEngineTelnyxConfig, - TranscriptionEngineXaiConfig, TranscriptionStartRequest, ActionAddAIAssistantMessagesResponse, ActionAnswerResponse, @@ -3710,9 +3685,9 @@ Types: from telnyx.types import ( NetworkInterface, NetworkInterfaceRegion, - PublicInternetGatewayRead, PublicInternetGatewayCreateResponse, PublicInternetGatewayRetrieveResponse, + PublicInternetGatewayListResponse, PublicInternetGatewayDeleteResponse, ) ``` @@ -3721,7 +3696,7 @@ Methods: - client.public_internet_gateways.create(\*\*params) -> PublicInternetGatewayCreateResponse - client.public_internet_gateways.retrieve(id) -> PublicInternetGatewayRetrieveResponse -- client.public_internet_gateways.list(\*\*params) -> SyncDefaultFlatPagination[PublicInternetGatewayRead] +- client.public_internet_gateways.list(\*\*params) -> SyncDefaultFlatPagination[PublicInternetGatewayListResponse] - client.public_internet_gateways.delete(id) -> PublicInternetGatewayDeleteResponse # Queues @@ -4806,10 +4781,10 @@ Types: ```python from telnyx.types import ( - VirtualCrossConnectCombined, VirtualCrossConnectCreateResponse, VirtualCrossConnectRetrieveResponse, VirtualCrossConnectUpdateResponse, + VirtualCrossConnectListResponse, VirtualCrossConnectDeleteResponse, ) ``` @@ -4819,7 +4794,7 @@ Methods: - client.virtual_cross_connects.create(\*\*params) -> VirtualCrossConnectCreateResponse - client.virtual_cross_connects.retrieve(id) -> VirtualCrossConnectRetrieveResponse - client.virtual_cross_connects.update(id, \*\*params) -> VirtualCrossConnectUpdateResponse -- client.virtual_cross_connects.list(\*\*params) -> SyncDefaultFlatPagination[VirtualCrossConnectCombined] +- client.virtual_cross_connects.list(\*\*params) -> SyncDefaultFlatPagination[VirtualCrossConnectListResponse] - client.virtual_cross_connects.delete(id) -> VirtualCrossConnectDeleteResponse # VirtualCrossConnectsCoverage @@ -4853,9 +4828,9 @@ Types: ```python from telnyx.types import ( - WireguardInterfaceRead, WireguardInterfaceCreateResponse, WireguardInterfaceRetrieveResponse, + WireguardInterfaceListResponse, WireguardInterfaceDeleteResponse, ) ``` @@ -4864,7 +4839,7 @@ Methods: - client.wireguard_interfaces.create(\*\*params) -> WireguardInterfaceCreateResponse - client.wireguard_interfaces.retrieve(id) -> WireguardInterfaceRetrieveResponse -- client.wireguard_interfaces.list(\*\*params) -> SyncDefaultFlatPagination[WireguardInterfaceRead] +- client.wireguard_interfaces.list(\*\*params) -> SyncDefaultFlatPagination[WireguardInterfaceListResponse] - client.wireguard_interfaces.delete(id) -> WireguardInterfaceDeleteResponse # WireguardPeers @@ -5590,6 +5565,7 @@ from telnyx.types import ( EnterpriseCreateResponse, EnterpriseRetrieveResponse, EnterpriseUpdateResponse, + EnterpriseActivateBrandedCallingResponse, ) ``` @@ -5600,6 +5576,7 @@ Methods: - client.enterprises.update(enterprise_id, \*\*params) -> EnterpriseUpdateResponse - client.enterprises.list(\*\*params) -> SyncDefaultFlatPagination[EnterprisePublic] - client.enterprises.delete(enterprise_id) -> None +- client.enterprises.activate_branded_calling(enterprise_id) -> EnterpriseActivateBrandedCallingResponse ## Reputation @@ -5626,15 +5603,47 @@ Methods: Types: ```python -from telnyx.types.enterprises.reputation import NumberRetrieveResponse, NumberAssociateResponse +from telnyx.types.enterprises.reputation import ( + NumberRetrieveResponse, + NumberListResponse, + NumberAssociateResponse, + NumberRefreshResponse, +) ``` Methods: - client.enterprises.reputation.numbers.retrieve(phone_number, \*, enterprise_id, \*\*params) -> NumberRetrieveResponse -- client.enterprises.reputation.numbers.list(enterprise_id, \*\*params) -> SyncDefaultFlatPagination[ReputationPhoneNumberWithReputationData] +- client.enterprises.reputation.numbers.list(enterprise_id, \*\*params) -> SyncDefaultFlatPagination[NumberListResponse] - client.enterprises.reputation.numbers.associate(enterprise_id, \*\*params) -> NumberAssociateResponse - client.enterprises.reputation.numbers.disassociate(phone_number, \*, enterprise_id) -> None +- client.enterprises.reputation.numbers.refresh(enterprise_id, \*\*params) -> NumberRefreshResponse + +### Loa + +Types: + +```python +from telnyx.types.enterprises.reputation import LoaUpdateResponse +``` + +Methods: + +- client.enterprises.reputation.loa.update(enterprise_id, \*\*params) -> LoaUpdateResponse +- client.enterprises.reputation.loa.render(enterprise_id, \*\*params) -> BinaryAPIResponse + +## Dir + +Types: + +```python +from telnyx.types.enterprises import DirCreateResponse, DirListResponse +``` + +Methods: + +- client.enterprises.dir.create(enterprise_id, \*\*params) -> DirCreateResponse +- client.enterprises.dir.list(enterprise_id, \*\*params) -> SyncDefaultFlatPagination[DirListResponse] # Reputation @@ -5643,22 +5652,63 @@ Methods: Types: ```python -from telnyx.types.reputation import NumberRetrieveResponse +from telnyx.types.reputation import NumberRetrieveResponse, NumberListResponse ``` Methods: - client.reputation.numbers.retrieve(phone_number, \*\*params) -> NumberRetrieveResponse -- client.reputation.numbers.list(\*\*params) -> SyncDefaultFlatPagination[ReputationPhoneNumberWithReputationData] +- client.reputation.numbers.list(\*\*params) -> SyncDefaultFlatPagination[NumberListResponse] - client.reputation.numbers.delete(phone_number) -> None # TermsOfService +Types: + +```python +from telnyx.types import TermsOfServiceStatusResponse +``` + +Methods: + +- client.terms_of_service.status(\*\*params) -> TermsOfServiceStatusResponse + ## NumberReputation +Types: + +```python +from telnyx.types.terms_of_service import NumberReputationAgreeResponse +``` + +Methods: + +- client.terms_of_service.number_reputation.agree() -> NumberReputationAgreeResponse + +## Agreements + +Types: + +```python +from telnyx.types.terms_of_service import AgreementRetrieveResponse, AgreementListResponse +``` + +Methods: + +- client.terms_of_service.agreements.retrieve(agreement_id) -> AgreementRetrieveResponse +- client.terms_of_service.agreements.list(\*\*params) -> SyncDefaultFlatPagination[AgreementListResponse] + +## BrandedCalling + +Types: + +```python +from telnyx.types.terms_of_service import BrandedCallingAgreeResponse +``` + Methods: -- client.terms_of_service.number_reputation.agree() -> None +- client.terms_of_service.branded_calling.agree() -> BrandedCallingAgreeResponse # PronunciationDicts @@ -5683,20 +5733,113 @@ Methods: - client.pronunciation_dicts.list(\*\*params) -> SyncDefaultFlatPagination[PronunciationDictData] - client.pronunciation_dicts.delete(id) -> None +# CallReasons + +Types: + +```python +from telnyx.types import CallReasonListResponse, CallReasonValidateResponse +``` + +Methods: + +- client.call_reasons.list(\*\*params) -> SyncDefaultFlatPagination[CallReasonListResponse] +- client.call_reasons.validate(\*\*params) -> CallReasonValidateResponse + +# Dir + +Types: + +```python +from telnyx.types import ( + DirRetrieveResponse, + DirUpdateResponse, + DirListResponse, + DirListDocumentTypesResponse, + DirListInfringementClaimsResponse, + DirSubmitResponse, + DirUpdateInfringementResponse, +) +``` + +Methods: + +- client.dir.retrieve(dir_id) -> DirRetrieveResponse +- client.dir.update(dir_id, \*\*params) -> DirUpdateResponse +- client.dir.list(\*\*params) -> SyncDefaultFlatPagination[DirListResponse] +- client.dir.delete(dir_id) -> None +- client.dir.list_document_types() -> DirListDocumentTypesResponse +- client.dir.list_infringement_claims(dir_id, \*\*params) -> SyncDefaultFlatPagination[DirListInfringementClaimsResponse] +- client.dir.submit(dir_id) -> DirSubmitResponse +- client.dir.update_infringement(dir_id, \*\*params) -> DirUpdateInfringementResponse + +## Comments + +Types: + +```python +from telnyx.types.dir import CommentCreateResponse, CommentListResponse +``` + +Methods: + +- client.dir.comments.create(dir_id, \*\*params) -> CommentCreateResponse +- client.dir.comments.list(dir_id, \*\*params) -> SyncDefaultFlatPagination[CommentListResponse] + +## PhoneNumberBatches + +Types: + +```python +from telnyx.types.dir import PhoneNumberBatchRetrieveResponse, PhoneNumberBatchListResponse +``` + +Methods: + +- client.dir.phone_number_batches.retrieve(batch_id, \*, dir_id) -> PhoneNumberBatchRetrieveResponse +- client.dir.phone_number_batches.list(dir_id, \*\*params) -> SyncDefaultFlatPagination[PhoneNumberBatchListResponse] + +## PhoneNumbers + +Types: + +```python +from telnyx.types.dir import ( + PhoneNumberListResponse, + PhoneNumberAddResponse, + PhoneNumberRemoveResponse, +) +``` + +Methods: + +- client.dir.phone_numbers.list(dir_id, \*\*params) -> SyncDefaultFlatPagination[PhoneNumberListResponse] +- client.dir.phone_numbers.add(dir_id, \*\*params) -> PhoneNumberAddResponse +- client.dir.phone_numbers.remove(dir_id, \*\*params) -> PhoneNumberRemoveResponse + +# InfringementClaims + +Types: + +```python +from telnyx.types import InfringementClaimRetrieveResponse, InfringementClaimContestResponse +``` + +Methods: + +- client.infringement_claims.retrieve(claim_id) -> InfringementClaimRetrieveResponse +- client.infringement_claims.contest(claim_id, \*\*params) -> InfringementClaimContestResponse + # UacConnections Types: ```python from telnyx.types import ( - UacConnection, - UacExternalSettings, - UacInbound, - UacInternalSettings, - UacOutbound, UacConnectionCreateResponse, UacConnectionRetrieveResponse, UacConnectionUpdateResponse, + UacConnectionListResponse, UacConnectionDeleteResponse, ) ``` @@ -5706,7 +5849,7 @@ Methods: - client.uac_connections.create(\*\*params) -> UacConnectionCreateResponse - client.uac_connections.retrieve(id) -> UacConnectionRetrieveResponse - client.uac_connections.update(id, \*\*params) -> UacConnectionUpdateResponse -- client.uac_connections.list(\*\*params) -> SyncDefaultFlatPagination[UacConnection] +- client.uac_connections.list(\*\*params) -> SyncDefaultFlatPagination[UacConnectionListResponse] - client.uac_connections.delete(id) -> UacConnectionDeleteResponse ## Actions diff --git a/src/telnyx/_client.py b/src/telnyx/_client.py index 405a4042..3bf5e231 100644 --- a/src/telnyx/_client.py +++ b/src/telnyx/_client.py @@ -38,6 +38,7 @@ if TYPE_CHECKING: from .resources import ( ai, + dir, ips, list, seti, @@ -81,6 +82,7 @@ ota_updates, short_codes, audit_events, + call_reasons, oauth_grants, requirements, voice_clones, @@ -141,6 +143,7 @@ texml_applications, webhook_deliveries, global_ip_protocols, + infringement_claims, integration_secrets, notification_events, number_block_orders, @@ -211,6 +214,7 @@ from .resources.media import MediaResource, AsyncMediaResource from .resources.oauth import OAuthResource, AsyncOAuthResource from .resources.balance import BalanceResource, AsyncBalanceResource + from .resources.dir.dir import DirResource, AsyncDirResource from .resources.regions import RegionsResource, AsyncRegionsResource from .resources.comments import CommentsResource, AsyncCommentsResource from .resources.invoices import InvoicesResource, AsyncInvoicesResource @@ -229,6 +233,7 @@ from .resources.short_codes import ShortCodesResource, AsyncShortCodesResource from .resources.texml.texml import TexmlResource, AsyncTexmlResource from .resources.audit_events import AuditEventsResource, AsyncAuditEventsResource + from .resources.call_reasons import CallReasonsResource, AsyncCallReasonsResource from .resources.oauth_grants import OAuthGrantsResource, AsyncOAuthGrantsResource from .resources.requirements import RequirementsResource, AsyncRequirementsResource from .resources.voice_clones import VoiceClonesResource, AsyncVoiceClonesResource @@ -287,6 +292,7 @@ from .resources.webhook_deliveries import WebhookDeliveriesResource, AsyncWebhookDeliveriesResource from .resources.addresses.addresses import AddressesResource, AsyncAddressesResource from .resources.global_ip_protocols import GlobalIPProtocolsResource, AsyncGlobalIPProtocolsResource + from .resources.infringement_claims import InfringementClaimsResource, AsyncInfringementClaimsResource from .resources.integration_secrets import IntegrationSecretsResource, AsyncIntegrationSecretsResource from .resources.messaging.messaging import MessagingResource, AsyncMessagingResource from .resources.notification_events import NotificationEventsResource, AsyncNotificationEventsResource @@ -1637,7 +1643,7 @@ def traffic_policy_profiles(self) -> TrafficPolicyProfilesResource: @cached_property def enterprises(self) -> EnterprisesResource: - """Enterprise management for Branded Calling and Number Reputation services""" + """Manage the legal-entity record that owns your DIRs and phone numbers.""" from .resources.enterprises import EnterprisesResource return EnterprisesResource(self) @@ -1650,6 +1656,9 @@ def reputation(self) -> ReputationResource: @cached_property def terms_of_service(self) -> TermsOfServiceResource: + """ + Accept and review the Branded Calling and Phone Number Reputation terms of service. + """ from .resources.terms_of_service import TermsOfServiceResource return TermsOfServiceResource(self) @@ -1664,6 +1673,31 @@ def pronunciation_dicts(self) -> PronunciationDictsResource: return PronunciationDictsResource(self) + @cached_property + def call_reasons(self) -> CallReasonsResource: + """ + Static reference values the API accepts: call reasons, document types, rejection types. + """ + from .resources.call_reasons import CallReasonsResource + + return CallReasonsResource(self) + + @cached_property + def dir(self) -> DirResource: + from .resources.dir import DirResource + + return DirResource(self) + + @cached_property + def infringement_claims(self) -> InfringementClaimsResource: + """Trademark or impersonation claims filed against your DIR. + + Customers may contest a claim with supporting evidence. + """ + from .resources.infringement_claims import InfringementClaimsResource + + return InfringementClaimsResource(self) + @cached_property def uac_connections(self) -> UacConnectionsResource: """UAC connection operations""" @@ -3017,7 +3051,7 @@ def traffic_policy_profiles(self) -> AsyncTrafficPolicyProfilesResource: @cached_property def enterprises(self) -> AsyncEnterprisesResource: - """Enterprise management for Branded Calling and Number Reputation services""" + """Manage the legal-entity record that owns your DIRs and phone numbers.""" from .resources.enterprises import AsyncEnterprisesResource return AsyncEnterprisesResource(self) @@ -3030,6 +3064,9 @@ def reputation(self) -> AsyncReputationResource: @cached_property def terms_of_service(self) -> AsyncTermsOfServiceResource: + """ + Accept and review the Branded Calling and Phone Number Reputation terms of service. + """ from .resources.terms_of_service import AsyncTermsOfServiceResource return AsyncTermsOfServiceResource(self) @@ -3044,6 +3081,31 @@ def pronunciation_dicts(self) -> AsyncPronunciationDictsResource: return AsyncPronunciationDictsResource(self) + @cached_property + def call_reasons(self) -> AsyncCallReasonsResource: + """ + Static reference values the API accepts: call reasons, document types, rejection types. + """ + from .resources.call_reasons import AsyncCallReasonsResource + + return AsyncCallReasonsResource(self) + + @cached_property + def dir(self) -> AsyncDirResource: + from .resources.dir import AsyncDirResource + + return AsyncDirResource(self) + + @cached_property + def infringement_claims(self) -> AsyncInfringementClaimsResource: + """Trademark or impersonation claims filed against your DIR. + + Customers may contest a claim with supporting evidence. + """ + from .resources.infringement_claims import AsyncInfringementClaimsResource + + return AsyncInfringementClaimsResource(self) + @cached_property def uac_connections(self) -> AsyncUacConnectionsResource: """UAC connection operations""" @@ -4333,7 +4395,7 @@ def traffic_policy_profiles(self) -> traffic_policy_profiles.TrafficPolicyProfil @cached_property def enterprises(self) -> enterprises.EnterprisesResourceWithRawResponse: - """Enterprise management for Branded Calling and Number Reputation services""" + """Manage the legal-entity record that owns your DIRs and phone numbers.""" from .resources.enterprises import EnterprisesResourceWithRawResponse return EnterprisesResourceWithRawResponse(self._client.enterprises) @@ -4346,6 +4408,9 @@ def reputation(self) -> reputation.ReputationResourceWithRawResponse: @cached_property def terms_of_service(self) -> terms_of_service.TermsOfServiceResourceWithRawResponse: + """ + Accept and review the Branded Calling and Phone Number Reputation terms of service. + """ from .resources.terms_of_service import TermsOfServiceResourceWithRawResponse return TermsOfServiceResourceWithRawResponse(self._client.terms_of_service) @@ -4360,6 +4425,31 @@ def pronunciation_dicts(self) -> pronunciation_dicts.PronunciationDictsResourceW return PronunciationDictsResourceWithRawResponse(self._client.pronunciation_dicts) + @cached_property + def call_reasons(self) -> call_reasons.CallReasonsResourceWithRawResponse: + """ + Static reference values the API accepts: call reasons, document types, rejection types. + """ + from .resources.call_reasons import CallReasonsResourceWithRawResponse + + return CallReasonsResourceWithRawResponse(self._client.call_reasons) + + @cached_property + def dir(self) -> dir.DirResourceWithRawResponse: + from .resources.dir import DirResourceWithRawResponse + + return DirResourceWithRawResponse(self._client.dir) + + @cached_property + def infringement_claims(self) -> infringement_claims.InfringementClaimsResourceWithRawResponse: + """Trademark or impersonation claims filed against your DIR. + + Customers may contest a claim with supporting evidence. + """ + from .resources.infringement_claims import InfringementClaimsResourceWithRawResponse + + return InfringementClaimsResourceWithRawResponse(self._client.infringement_claims) + @cached_property def uac_connections(self) -> uac_connections.UacConnectionsResourceWithRawResponse: """UAC connection operations""" @@ -5520,7 +5610,7 @@ def traffic_policy_profiles(self) -> traffic_policy_profiles.AsyncTrafficPolicyP @cached_property def enterprises(self) -> enterprises.AsyncEnterprisesResourceWithRawResponse: - """Enterprise management for Branded Calling and Number Reputation services""" + """Manage the legal-entity record that owns your DIRs and phone numbers.""" from .resources.enterprises import AsyncEnterprisesResourceWithRawResponse return AsyncEnterprisesResourceWithRawResponse(self._client.enterprises) @@ -5533,6 +5623,9 @@ def reputation(self) -> reputation.AsyncReputationResourceWithRawResponse: @cached_property def terms_of_service(self) -> terms_of_service.AsyncTermsOfServiceResourceWithRawResponse: + """ + Accept and review the Branded Calling and Phone Number Reputation terms of service. + """ from .resources.terms_of_service import AsyncTermsOfServiceResourceWithRawResponse return AsyncTermsOfServiceResourceWithRawResponse(self._client.terms_of_service) @@ -5547,6 +5640,31 @@ def pronunciation_dicts(self) -> pronunciation_dicts.AsyncPronunciationDictsReso return AsyncPronunciationDictsResourceWithRawResponse(self._client.pronunciation_dicts) + @cached_property + def call_reasons(self) -> call_reasons.AsyncCallReasonsResourceWithRawResponse: + """ + Static reference values the API accepts: call reasons, document types, rejection types. + """ + from .resources.call_reasons import AsyncCallReasonsResourceWithRawResponse + + return AsyncCallReasonsResourceWithRawResponse(self._client.call_reasons) + + @cached_property + def dir(self) -> dir.AsyncDirResourceWithRawResponse: + from .resources.dir import AsyncDirResourceWithRawResponse + + return AsyncDirResourceWithRawResponse(self._client.dir) + + @cached_property + def infringement_claims(self) -> infringement_claims.AsyncInfringementClaimsResourceWithRawResponse: + """Trademark or impersonation claims filed against your DIR. + + Customers may contest a claim with supporting evidence. + """ + from .resources.infringement_claims import AsyncInfringementClaimsResourceWithRawResponse + + return AsyncInfringementClaimsResourceWithRawResponse(self._client.infringement_claims) + @cached_property def uac_connections(self) -> uac_connections.AsyncUacConnectionsResourceWithRawResponse: """UAC connection operations""" @@ -6709,7 +6827,7 @@ def traffic_policy_profiles(self) -> traffic_policy_profiles.TrafficPolicyProfil @cached_property def enterprises(self) -> enterprises.EnterprisesResourceWithStreamingResponse: - """Enterprise management for Branded Calling and Number Reputation services""" + """Manage the legal-entity record that owns your DIRs and phone numbers.""" from .resources.enterprises import EnterprisesResourceWithStreamingResponse return EnterprisesResourceWithStreamingResponse(self._client.enterprises) @@ -6722,6 +6840,9 @@ def reputation(self) -> reputation.ReputationResourceWithStreamingResponse: @cached_property def terms_of_service(self) -> terms_of_service.TermsOfServiceResourceWithStreamingResponse: + """ + Accept and review the Branded Calling and Phone Number Reputation terms of service. + """ from .resources.terms_of_service import TermsOfServiceResourceWithStreamingResponse return TermsOfServiceResourceWithStreamingResponse(self._client.terms_of_service) @@ -6736,6 +6857,31 @@ def pronunciation_dicts(self) -> pronunciation_dicts.PronunciationDictsResourceW return PronunciationDictsResourceWithStreamingResponse(self._client.pronunciation_dicts) + @cached_property + def call_reasons(self) -> call_reasons.CallReasonsResourceWithStreamingResponse: + """ + Static reference values the API accepts: call reasons, document types, rejection types. + """ + from .resources.call_reasons import CallReasonsResourceWithStreamingResponse + + return CallReasonsResourceWithStreamingResponse(self._client.call_reasons) + + @cached_property + def dir(self) -> dir.DirResourceWithStreamingResponse: + from .resources.dir import DirResourceWithStreamingResponse + + return DirResourceWithStreamingResponse(self._client.dir) + + @cached_property + def infringement_claims(self) -> infringement_claims.InfringementClaimsResourceWithStreamingResponse: + """Trademark or impersonation claims filed against your DIR. + + Customers may contest a claim with supporting evidence. + """ + from .resources.infringement_claims import InfringementClaimsResourceWithStreamingResponse + + return InfringementClaimsResourceWithStreamingResponse(self._client.infringement_claims) + @cached_property def uac_connections(self) -> uac_connections.UacConnectionsResourceWithStreamingResponse: """UAC connection operations""" @@ -7944,7 +8090,7 @@ def traffic_policy_profiles( @cached_property def enterprises(self) -> enterprises.AsyncEnterprisesResourceWithStreamingResponse: - """Enterprise management for Branded Calling and Number Reputation services""" + """Manage the legal-entity record that owns your DIRs and phone numbers.""" from .resources.enterprises import AsyncEnterprisesResourceWithStreamingResponse return AsyncEnterprisesResourceWithStreamingResponse(self._client.enterprises) @@ -7957,6 +8103,9 @@ def reputation(self) -> reputation.AsyncReputationResourceWithStreamingResponse: @cached_property def terms_of_service(self) -> terms_of_service.AsyncTermsOfServiceResourceWithStreamingResponse: + """ + Accept and review the Branded Calling and Phone Number Reputation terms of service. + """ from .resources.terms_of_service import AsyncTermsOfServiceResourceWithStreamingResponse return AsyncTermsOfServiceResourceWithStreamingResponse(self._client.terms_of_service) @@ -7971,6 +8120,31 @@ def pronunciation_dicts(self) -> pronunciation_dicts.AsyncPronunciationDictsReso return AsyncPronunciationDictsResourceWithStreamingResponse(self._client.pronunciation_dicts) + @cached_property + def call_reasons(self) -> call_reasons.AsyncCallReasonsResourceWithStreamingResponse: + """ + Static reference values the API accepts: call reasons, document types, rejection types. + """ + from .resources.call_reasons import AsyncCallReasonsResourceWithStreamingResponse + + return AsyncCallReasonsResourceWithStreamingResponse(self._client.call_reasons) + + @cached_property + def dir(self) -> dir.AsyncDirResourceWithStreamingResponse: + from .resources.dir import AsyncDirResourceWithStreamingResponse + + return AsyncDirResourceWithStreamingResponse(self._client.dir) + + @cached_property + def infringement_claims(self) -> infringement_claims.AsyncInfringementClaimsResourceWithStreamingResponse: + """Trademark or impersonation claims filed against your DIR. + + Customers may contest a claim with supporting evidence. + """ + from .resources.infringement_claims import AsyncInfringementClaimsResourceWithStreamingResponse + + return AsyncInfringementClaimsResourceWithStreamingResponse(self._client.infringement_claims) + @cached_property def uac_connections(self) -> uac_connections.AsyncUacConnectionsResourceWithStreamingResponse: """UAC connection operations""" diff --git a/src/telnyx/resources/__init__.py b/src/telnyx/resources/__init__.py index 0c2e32ee..0fde60a8 100644 --- a/src/telnyx/resources/__init__.py +++ b/src/telnyx/resources/__init__.py @@ -8,6 +8,14 @@ AIResourceWithStreamingResponse, AsyncAIResourceWithStreamingResponse, ) +from .dir import ( + DirResource, + AsyncDirResource, + DirResourceWithRawResponse, + AsyncDirResourceWithRawResponse, + DirResourceWithStreamingResponse, + AsyncDirResourceWithStreamingResponse, +) from .ips import ( IPsResource, AsyncIPsResource, @@ -353,6 +361,14 @@ AuditEventsResourceWithStreamingResponse, AsyncAuditEventsResourceWithStreamingResponse, ) +from .call_reasons import ( + CallReasonsResource, + AsyncCallReasonsResource, + CallReasonsResourceWithRawResponse, + AsyncCallReasonsResourceWithRawResponse, + CallReasonsResourceWithStreamingResponse, + AsyncCallReasonsResourceWithStreamingResponse, +) from .oauth_grants import ( OAuthGrantsResource, AsyncOAuthGrantsResource, @@ -833,6 +849,14 @@ GlobalIPProtocolsResourceWithStreamingResponse, AsyncGlobalIPProtocolsResourceWithStreamingResponse, ) +from .infringement_claims import ( + InfringementClaimsResource, + AsyncInfringementClaimsResource, + InfringementClaimsResourceWithRawResponse, + AsyncInfringementClaimsResourceWithRawResponse, + InfringementClaimsResourceWithStreamingResponse, + AsyncInfringementClaimsResourceWithStreamingResponse, +) from .integration_secrets import ( IntegrationSecretsResource, AsyncIntegrationSecretsResource, @@ -2291,6 +2315,24 @@ "AsyncPronunciationDictsResourceWithRawResponse", "PronunciationDictsResourceWithStreamingResponse", "AsyncPronunciationDictsResourceWithStreamingResponse", + "CallReasonsResource", + "AsyncCallReasonsResource", + "CallReasonsResourceWithRawResponse", + "AsyncCallReasonsResourceWithRawResponse", + "CallReasonsResourceWithStreamingResponse", + "AsyncCallReasonsResourceWithStreamingResponse", + "DirResource", + "AsyncDirResource", + "DirResourceWithRawResponse", + "AsyncDirResourceWithRawResponse", + "DirResourceWithStreamingResponse", + "AsyncDirResourceWithStreamingResponse", + "InfringementClaimsResource", + "AsyncInfringementClaimsResource", + "InfringementClaimsResourceWithRawResponse", + "AsyncInfringementClaimsResourceWithRawResponse", + "InfringementClaimsResourceWithStreamingResponse", + "AsyncInfringementClaimsResourceWithStreamingResponse", "UacConnectionsResource", "AsyncUacConnectionsResource", "UacConnectionsResourceWithRawResponse", diff --git a/src/telnyx/resources/ai/assistants/assistants.py b/src/telnyx/resources/ai/assistants/assistants.py index 86b35421..b6e2875c 100644 --- a/src/telnyx/resources/ai/assistants/assistants.py +++ b/src/telnyx/resources/ai/assistants/assistants.py @@ -80,7 +80,6 @@ from ....types.ai.assistant_tool_param import AssistantToolParam from ....types.ai.voice_settings_param import VoiceSettingsParam from ....types.ai.widget_settings_param import WidgetSettingsParam -from ....types.ai.external_llm_req_param import ExternalLlmReqParam from ....types.ai.insight_settings_param import InsightSettingsParam from ....types.ai.privacy_settings_param import PrivacySettingsParam from ....types.ai.assistant_chat_response import AssistantChatResponse @@ -88,13 +87,8 @@ from ....types.ai.messaging_settings_param import MessagingSettingsParam from ....types.ai.telephony_settings_param import TelephonySettingsParam from ....types.ai.assistant_delete_response import AssistantDeleteResponse -from ....types.ai.fallback_config_req_param import FallbackConfigReqParam -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.transcription_settings_param import TranscriptionSettingsParam -from ....types.ai.post_conversation_settings_req_param import PostConversationSettingsReqParam -from ....types.ai.inference_embedding_interruption_settings_param import InferenceEmbeddingInterruptionSettingsParam __all__ = ["AssistantsResource", "AsyncAssistantsResource"] @@ -162,18 +156,18 @@ def create( dynamic_variables_webhook_timeout_ms: int | Omit = omit, dynamic_variables_webhook_url: str | Omit = omit, enabled_features: List[EnabledFeatures] | Omit = omit, - external_llm: ExternalLlmReqParam | Omit = omit, - fallback_config: FallbackConfigReqParam | Omit = omit, + external_llm: assistant_create_params.ExternalLlm | Omit = omit, + fallback_config: assistant_create_params.FallbackConfig | Omit = omit, greeting: str | Omit = omit, insight_settings: InsightSettingsParam | Omit = omit, - integrations: Iterable[AssistantIntegrationParam] | Omit = omit, - interruption_settings: InferenceEmbeddingInterruptionSettingsParam | Omit = omit, + integrations: Iterable[assistant_create_params.Integration] | Omit = omit, + interruption_settings: assistant_create_params.InterruptionSettings | Omit = omit, llm_api_key_ref: str | Omit = omit, - mcp_servers: Iterable[AssistantMcpServerParam] | Omit = omit, + mcp_servers: Iterable[assistant_create_params.McpServer] | Omit = omit, messaging_settings: MessagingSettingsParam | Omit = omit, model: str | Omit = omit, observability_settings: ObservabilityReqParam | Omit = omit, - post_conversation_settings: PostConversationSettingsReqParam | Omit = omit, + post_conversation_settings: assistant_create_params.PostConversationSettings | Omit = omit, privacy_settings: PrivacySettingsParam | Omit = omit, tags: SequenceNotStr[str] | Omit = omit, telephony_settings: TelephonySettingsParam | Omit = omit, @@ -380,20 +374,20 @@ def update( dynamic_variables_webhook_timeout_ms: int | Omit = omit, dynamic_variables_webhook_url: str | Omit = omit, enabled_features: List[EnabledFeatures] | Omit = omit, - external_llm: ExternalLlmReqParam | Omit = omit, - fallback_config: FallbackConfigReqParam | Omit = omit, + external_llm: assistant_update_params.ExternalLlm | Omit = omit, + fallback_config: assistant_update_params.FallbackConfig | Omit = omit, greeting: str | Omit = omit, insight_settings: InsightSettingsParam | Omit = omit, instructions: str | Omit = omit, - integrations: Iterable[AssistantIntegrationParam] | Omit = omit, - interruption_settings: InferenceEmbeddingInterruptionSettingsParam | Omit = omit, + integrations: Iterable[assistant_update_params.Integration] | Omit = omit, + interruption_settings: assistant_update_params.InterruptionSettings | Omit = omit, llm_api_key_ref: str | Omit = omit, - mcp_servers: Iterable[AssistantMcpServerParam] | Omit = omit, + mcp_servers: Iterable[assistant_update_params.McpServer] | Omit = omit, messaging_settings: MessagingSettingsParam | Omit = omit, model: str | Omit = omit, name: str | Omit = omit, observability_settings: ObservabilityReqParam | Omit = omit, - post_conversation_settings: PostConversationSettingsReqParam | Omit = omit, + post_conversation_settings: assistant_update_params.PostConversationSettings | Omit = omit, privacy_settings: PrivacySettingsParam | Omit = omit, promote_to_main: bool | Omit = omit, tags: SequenceNotStr[str] | Omit = omit, @@ -903,18 +897,18 @@ async def create( dynamic_variables_webhook_timeout_ms: int | Omit = omit, dynamic_variables_webhook_url: str | Omit = omit, enabled_features: List[EnabledFeatures] | Omit = omit, - external_llm: ExternalLlmReqParam | Omit = omit, - fallback_config: FallbackConfigReqParam | Omit = omit, + external_llm: assistant_create_params.ExternalLlm | Omit = omit, + fallback_config: assistant_create_params.FallbackConfig | Omit = omit, greeting: str | Omit = omit, insight_settings: InsightSettingsParam | Omit = omit, - integrations: Iterable[AssistantIntegrationParam] | Omit = omit, - interruption_settings: InferenceEmbeddingInterruptionSettingsParam | Omit = omit, + integrations: Iterable[assistant_create_params.Integration] | Omit = omit, + interruption_settings: assistant_create_params.InterruptionSettings | Omit = omit, llm_api_key_ref: str | Omit = omit, - mcp_servers: Iterable[AssistantMcpServerParam] | Omit = omit, + mcp_servers: Iterable[assistant_create_params.McpServer] | Omit = omit, messaging_settings: MessagingSettingsParam | Omit = omit, model: str | Omit = omit, observability_settings: ObservabilityReqParam | Omit = omit, - post_conversation_settings: PostConversationSettingsReqParam | Omit = omit, + post_conversation_settings: assistant_create_params.PostConversationSettings | Omit = omit, privacy_settings: PrivacySettingsParam | Omit = omit, tags: SequenceNotStr[str] | Omit = omit, telephony_settings: TelephonySettingsParam | Omit = omit, @@ -1121,20 +1115,20 @@ async def update( dynamic_variables_webhook_timeout_ms: int | Omit = omit, dynamic_variables_webhook_url: str | Omit = omit, enabled_features: List[EnabledFeatures] | Omit = omit, - external_llm: ExternalLlmReqParam | Omit = omit, - fallback_config: FallbackConfigReqParam | Omit = omit, + external_llm: assistant_update_params.ExternalLlm | Omit = omit, + fallback_config: assistant_update_params.FallbackConfig | Omit = omit, greeting: str | Omit = omit, insight_settings: InsightSettingsParam | Omit = omit, instructions: str | Omit = omit, - integrations: Iterable[AssistantIntegrationParam] | Omit = omit, - interruption_settings: InferenceEmbeddingInterruptionSettingsParam | Omit = omit, + integrations: Iterable[assistant_update_params.Integration] | Omit = omit, + interruption_settings: assistant_update_params.InterruptionSettings | Omit = omit, llm_api_key_ref: str | Omit = omit, - mcp_servers: Iterable[AssistantMcpServerParam] | Omit = omit, + mcp_servers: Iterable[assistant_update_params.McpServer] | Omit = omit, messaging_settings: MessagingSettingsParam | Omit = omit, model: str | Omit = omit, name: str | Omit = omit, observability_settings: ObservabilityReqParam | Omit = omit, - post_conversation_settings: PostConversationSettingsReqParam | Omit = omit, + post_conversation_settings: assistant_update_params.PostConversationSettings | Omit = omit, privacy_settings: PrivacySettingsParam | Omit = omit, promote_to_main: bool | Omit = omit, tags: SequenceNotStr[str] | Omit = omit, diff --git a/src/telnyx/resources/ai/assistants/canary_deploys.py b/src/telnyx/resources/ai/assistants/canary_deploys.py index baf62939..09412a23 100644 --- a/src/telnyx/resources/ai/assistants/canary_deploys.py +++ b/src/telnyx/resources/ai/assistants/canary_deploys.py @@ -18,7 +18,6 @@ ) from ...._base_client import make_request_options from ....types.ai.assistants import canary_deploy_create_params, canary_deploy_update_params -from ....types.ai.assistants.rule_input_param import RuleInputParam from ....types.ai.assistants.canary_deploy_response import CanaryDeployResponse __all__ = ["CanaryDeploysResource", "AsyncCanaryDeploysResource"] @@ -50,7 +49,7 @@ def create( self, assistant_id: str, *, - rules: Iterable[RuleInputParam] | Omit = omit, + rules: Iterable[canary_deploy_create_params.Rule] | 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, @@ -124,7 +123,7 @@ def update( self, assistant_id: str, *, - rules: Iterable[RuleInputParam] | Omit = omit, + rules: Iterable[canary_deploy_update_params.Rule] | 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, @@ -222,7 +221,7 @@ async def create( self, assistant_id: str, *, - rules: Iterable[RuleInputParam] | Omit = omit, + rules: Iterable[canary_deploy_create_params.Rule] | 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, @@ -296,7 +295,7 @@ async def update( self, assistant_id: str, *, - rules: Iterable[RuleInputParam] | Omit = omit, + rules: Iterable[canary_deploy_update_params.Rule] | 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, diff --git a/src/telnyx/resources/ai/assistants/versions.py b/src/telnyx/resources/ai/assistants/versions.py index 270a7c10..a9bcfeb5 100644 --- a/src/telnyx/resources/ai/assistants/versions.py +++ b/src/telnyx/resources/ai/assistants/versions.py @@ -24,18 +24,12 @@ from ....types.ai.assistant_tool_param import AssistantToolParam from ....types.ai.voice_settings_param import VoiceSettingsParam from ....types.ai.widget_settings_param import WidgetSettingsParam -from ....types.ai.external_llm_req_param import ExternalLlmReqParam from ....types.ai.insight_settings_param import InsightSettingsParam from ....types.ai.privacy_settings_param import PrivacySettingsParam 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.fallback_config_req_param import FallbackConfigReqParam -from ....types.ai.assistant_mcp_server_param import AssistantMcpServerParam -from ....types.ai.assistant_integration_param import AssistantIntegrationParam from ....types.ai.transcription_settings_param import TranscriptionSettingsParam -from ....types.ai.post_conversation_settings_req_param import PostConversationSettingsReqParam -from ....types.ai.inference_embedding_interruption_settings_param import InferenceEmbeddingInterruptionSettingsParam __all__ = ["VersionsResource", "AsyncVersionsResource"] @@ -118,20 +112,20 @@ def update( dynamic_variables_webhook_timeout_ms: int | Omit = omit, dynamic_variables_webhook_url: str | Omit = omit, enabled_features: List[EnabledFeatures] | Omit = omit, - external_llm: ExternalLlmReqParam | Omit = omit, - fallback_config: FallbackConfigReqParam | Omit = omit, + external_llm: version_update_params.ExternalLlm | Omit = omit, + fallback_config: version_update_params.FallbackConfig | Omit = omit, greeting: str | Omit = omit, insight_settings: InsightSettingsParam | Omit = omit, instructions: str | Omit = omit, - integrations: Iterable[AssistantIntegrationParam] | Omit = omit, - interruption_settings: InferenceEmbeddingInterruptionSettingsParam | Omit = omit, + integrations: Iterable[version_update_params.Integration] | Omit = omit, + interruption_settings: version_update_params.InterruptionSettings | Omit = omit, llm_api_key_ref: str | Omit = omit, - mcp_servers: Iterable[AssistantMcpServerParam] | Omit = omit, + mcp_servers: Iterable[version_update_params.McpServer] | Omit = omit, messaging_settings: MessagingSettingsParam | Omit = omit, model: str | Omit = omit, name: str | Omit = omit, observability_settings: ObservabilityReqParam | Omit = omit, - post_conversation_settings: PostConversationSettingsReqParam | Omit = omit, + post_conversation_settings: version_update_params.PostConversationSettings | Omit = omit, privacy_settings: PrivacySettingsParam | Omit = omit, tags: SequenceNotStr[str] | Omit = omit, telephony_settings: TelephonySettingsParam | Omit = omit, @@ -487,20 +481,20 @@ async def update( dynamic_variables_webhook_timeout_ms: int | Omit = omit, dynamic_variables_webhook_url: str | Omit = omit, enabled_features: List[EnabledFeatures] | Omit = omit, - external_llm: ExternalLlmReqParam | Omit = omit, - fallback_config: FallbackConfigReqParam | Omit = omit, + external_llm: version_update_params.ExternalLlm | Omit = omit, + fallback_config: version_update_params.FallbackConfig | Omit = omit, greeting: str | Omit = omit, insight_settings: InsightSettingsParam | Omit = omit, instructions: str | Omit = omit, - integrations: Iterable[AssistantIntegrationParam] | Omit = omit, - interruption_settings: InferenceEmbeddingInterruptionSettingsParam | Omit = omit, + integrations: Iterable[version_update_params.Integration] | Omit = omit, + interruption_settings: version_update_params.InterruptionSettings | Omit = omit, llm_api_key_ref: str | Omit = omit, - mcp_servers: Iterable[AssistantMcpServerParam] | Omit = omit, + mcp_servers: Iterable[version_update_params.McpServer] | Omit = omit, messaging_settings: MessagingSettingsParam | Omit = omit, model: str | Omit = omit, name: str | Omit = omit, observability_settings: ObservabilityReqParam | Omit = omit, - post_conversation_settings: PostConversationSettingsReqParam | Omit = omit, + post_conversation_settings: version_update_params.PostConversationSettings | Omit = omit, privacy_settings: PrivacySettingsParam | Omit = omit, tags: SequenceNotStr[str] | Omit = omit, telephony_settings: TelephonySettingsParam | Omit = omit, diff --git a/src/telnyx/resources/call_reasons.py b/src/telnyx/resources/call_reasons.py new file mode 100644 index 00000000..bc104c32 --- /dev/null +++ b/src/telnyx/resources/call_reasons.py @@ -0,0 +1,307 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import httpx + +from ..types import call_reason_list_params +from .._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, 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 ..pagination import SyncDefaultFlatPagination, AsyncDefaultFlatPagination +from .._base_client import AsyncPaginator, make_request_options +from ..types.call_reason_list_response import CallReasonListResponse +from ..types.call_reason_validate_response import CallReasonValidateResponse + +__all__ = ["CallReasonsResource", "AsyncCallReasonsResource"] + + +class CallReasonsResource(SyncAPIResource): + """ + Static reference values the API accepts: call reasons, document types, rejection types. + """ + + @cached_property + def with_raw_response(self) -> CallReasonsResourceWithRawResponse: + """ + 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 CallReasonsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> CallReasonsResourceWithStreamingResponse: + """ + 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 CallReasonsResourceWithStreamingResponse(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[CallReasonListResponse]: + """Telnyx maintains a library of pre-vetted call-reason phrases (e.g. + + "Appointment + reminders", "Billing inquiries") that carry through DIR vetting smoothly. You + can use any string that fits your use case in `DirCreateRequest.call_reasons`, + but matching one of these reduces the chance the vetting team flags the phrasing + for clarification. + + Args: + page_number: 1-based page number. Out-of-range values return an empty page with correct meta. + + page_size: Items per page. Default `100` for this endpoint (the call-reason library is + small and most callers want the whole list in one call). 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 + """ + return self._get_api_list( + "/call_reasons", + page=SyncDefaultFlatPagination[CallReasonListResponse], + 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, + }, + call_reason_list_params.CallReasonListParams, + ), + ), + model=CallReasonListResponse, + ) + + def validate( + self, + *, + body: SequenceNotStr[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, + ) -> CallReasonValidateResponse: + """ + Check up to 10 candidate `call_reasons` strings against Telnyx's vetting + heuristics before sending them on a DIR create or update. The endpoint flags + strings that are likely to be rejected during vetting (too generic, banned + phrases, length issues, etc.) so you can fix them up front. + + Args: + body: **Bare JSON array** of candidate call-reason strings (NOT an object — there is + no top-level `call_reasons` key on this endpoint). 1–10 strings, each ≤64 + 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 + """ + return self._post( + "/call_reasons/validate", + body=maybe_transform(body, SequenceNotStr[str]), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=CallReasonValidateResponse, + ) + + +class AsyncCallReasonsResource(AsyncAPIResource): + """ + Static reference values the API accepts: call reasons, document types, rejection types. + """ + + @cached_property + def with_raw_response(self) -> AsyncCallReasonsResourceWithRawResponse: + """ + 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 AsyncCallReasonsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncCallReasonsResourceWithStreamingResponse: + """ + 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 AsyncCallReasonsResourceWithStreamingResponse(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[CallReasonListResponse, AsyncDefaultFlatPagination[CallReasonListResponse]]: + """Telnyx maintains a library of pre-vetted call-reason phrases (e.g. + + "Appointment + reminders", "Billing inquiries") that carry through DIR vetting smoothly. You + can use any string that fits your use case in `DirCreateRequest.call_reasons`, + but matching one of these reduces the chance the vetting team flags the phrasing + for clarification. + + Args: + page_number: 1-based page number. Out-of-range values return an empty page with correct meta. + + page_size: Items per page. Default `100` for this endpoint (the call-reason library is + small and most callers want the whole list in one call). 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 + """ + return self._get_api_list( + "/call_reasons", + page=AsyncDefaultFlatPagination[CallReasonListResponse], + 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, + }, + call_reason_list_params.CallReasonListParams, + ), + ), + model=CallReasonListResponse, + ) + + async def validate( + self, + *, + body: SequenceNotStr[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, + ) -> CallReasonValidateResponse: + """ + Check up to 10 candidate `call_reasons` strings against Telnyx's vetting + heuristics before sending them on a DIR create or update. The endpoint flags + strings that are likely to be rejected during vetting (too generic, banned + phrases, length issues, etc.) so you can fix them up front. + + Args: + body: **Bare JSON array** of candidate call-reason strings (NOT an object — there is + no top-level `call_reasons` key on this endpoint). 1–10 strings, each ≤64 + 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 + """ + return await self._post( + "/call_reasons/validate", + body=await async_maybe_transform(body, SequenceNotStr[str]), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=CallReasonValidateResponse, + ) + + +class CallReasonsResourceWithRawResponse: + def __init__(self, call_reasons: CallReasonsResource) -> None: + self._call_reasons = call_reasons + + self.list = to_raw_response_wrapper( + call_reasons.list, + ) + self.validate = to_raw_response_wrapper( + call_reasons.validate, + ) + + +class AsyncCallReasonsResourceWithRawResponse: + def __init__(self, call_reasons: AsyncCallReasonsResource) -> None: + self._call_reasons = call_reasons + + self.list = async_to_raw_response_wrapper( + call_reasons.list, + ) + self.validate = async_to_raw_response_wrapper( + call_reasons.validate, + ) + + +class CallReasonsResourceWithStreamingResponse: + def __init__(self, call_reasons: CallReasonsResource) -> None: + self._call_reasons = call_reasons + + self.list = to_streamed_response_wrapper( + call_reasons.list, + ) + self.validate = to_streamed_response_wrapper( + call_reasons.validate, + ) + + +class AsyncCallReasonsResourceWithStreamingResponse: + def __init__(self, call_reasons: AsyncCallReasonsResource) -> None: + self._call_reasons = call_reasons + + self.list = async_to_streamed_response_wrapper( + call_reasons.list, + ) + self.validate = async_to_streamed_response_wrapper( + call_reasons.validate, + ) diff --git a/src/telnyx/resources/dir/__init__.py b/src/telnyx/resources/dir/__init__.py new file mode 100644 index 00000000..df97b4f5 --- /dev/null +++ b/src/telnyx/resources/dir/__init__.py @@ -0,0 +1,61 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from .dir import ( + DirResource, + AsyncDirResource, + DirResourceWithRawResponse, + AsyncDirResourceWithRawResponse, + DirResourceWithStreamingResponse, + AsyncDirResourceWithStreamingResponse, +) +from .comments import ( + CommentsResource, + AsyncCommentsResource, + CommentsResourceWithRawResponse, + AsyncCommentsResourceWithRawResponse, + CommentsResourceWithStreamingResponse, + AsyncCommentsResourceWithStreamingResponse, +) +from .phone_numbers import ( + PhoneNumbersResource, + AsyncPhoneNumbersResource, + PhoneNumbersResourceWithRawResponse, + AsyncPhoneNumbersResourceWithRawResponse, + PhoneNumbersResourceWithStreamingResponse, + AsyncPhoneNumbersResourceWithStreamingResponse, +) +from .phone_number_batches import ( + PhoneNumberBatchesResource, + AsyncPhoneNumberBatchesResource, + PhoneNumberBatchesResourceWithRawResponse, + AsyncPhoneNumberBatchesResourceWithRawResponse, + PhoneNumberBatchesResourceWithStreamingResponse, + AsyncPhoneNumberBatchesResourceWithStreamingResponse, +) + +__all__ = [ + "CommentsResource", + "AsyncCommentsResource", + "CommentsResourceWithRawResponse", + "AsyncCommentsResourceWithRawResponse", + "CommentsResourceWithStreamingResponse", + "AsyncCommentsResourceWithStreamingResponse", + "PhoneNumberBatchesResource", + "AsyncPhoneNumberBatchesResource", + "PhoneNumberBatchesResourceWithRawResponse", + "AsyncPhoneNumberBatchesResourceWithRawResponse", + "PhoneNumberBatchesResourceWithStreamingResponse", + "AsyncPhoneNumberBatchesResourceWithStreamingResponse", + "PhoneNumbersResource", + "AsyncPhoneNumbersResource", + "PhoneNumbersResourceWithRawResponse", + "AsyncPhoneNumbersResourceWithRawResponse", + "PhoneNumbersResourceWithStreamingResponse", + "AsyncPhoneNumbersResourceWithStreamingResponse", + "DirResource", + "AsyncDirResource", + "DirResourceWithRawResponse", + "AsyncDirResourceWithRawResponse", + "DirResourceWithStreamingResponse", + "AsyncDirResourceWithStreamingResponse", +] diff --git a/src/telnyx/resources/dir/comments.py b/src/telnyx/resources/dir/comments.py new file mode 100644 index 00000000..89094488 --- /dev/null +++ b/src/telnyx/resources/dir/comments.py @@ -0,0 +1,355 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal + +import httpx + +from ..._types import Body, Omit, Query, Headers, NotGiven, omit, 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 ...types.dir import comment_list_params, comment_create_params +from ...pagination import SyncDefaultFlatPagination, AsyncDefaultFlatPagination +from ..._base_client import AsyncPaginator, make_request_options +from ...types.dir.comment_list_response import CommentListResponse +from ...types.dir.comment_create_response import CommentCreateResponse + +__all__ = ["CommentsResource", "AsyncCommentsResource"] + + +class CommentsResource(SyncAPIResource): + """ + Read messages from the Telnyx vetting team and reply with clarifying information. + """ + + @cached_property + def with_raw_response(self) -> CommentsResourceWithRawResponse: + """ + 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 CommentsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> CommentsResourceWithStreamingResponse: + """ + 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 CommentsResourceWithStreamingResponse(self) + + def create( + self, + dir_id: str, + *, + content: str, + parent_comment_id: 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, + ) -> CommentCreateResponse: + """ + Post a customer comment on a DIR (for example, to respond to reviewer notes). + Send only `content` (1–5000 chars) and an optional `parent_comment_id`; the + server sets the comment type, visibility, and author automatically. The + enterprise is resolved server-side from the DIR id. + + Args: + content: Comment body. 1–5000 characters. + + parent_comment_id: Optional parent comment id to thread this reply under. + + 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._post( + path_template("/dir/{dir_id}/comments", dir_id=dir_id), + body=maybe_transform( + { + "content": content, + "parent_comment_id": parent_comment_id, + }, + comment_create_params.CommentCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=CommentCreateResponse, + ) + + def list( + self, + dir_id: str, + *, + comment_type: Literal[ + "vetting_comment", + "rejection_reason", + "internal_note", + "notification", + "status_update", + "customer_inquiry", + "admin_response", + ] + | Omit = omit, + 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[CommentListResponse]: + """List the comments on a DIR. + + The enterprise is resolved server-side from the DIR + id. + + Args: + comment_type: + Restrict to comments of this category. Customer-visible categories only: + internal-only comments are filtered out regardless of this filter. + + 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_api_list( + path_template("/dir/{dir_id}/comments", dir_id=dir_id), + page=SyncDefaultFlatPagination[CommentListResponse], + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "comment_type": comment_type, + "page_number": page_number, + "page_size": page_size, + }, + comment_list_params.CommentListParams, + ), + ), + model=CommentListResponse, + ) + + +class AsyncCommentsResource(AsyncAPIResource): + """ + Read messages from the Telnyx vetting team and reply with clarifying information. + """ + + @cached_property + def with_raw_response(self) -> AsyncCommentsResourceWithRawResponse: + """ + 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 AsyncCommentsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncCommentsResourceWithStreamingResponse: + """ + 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 AsyncCommentsResourceWithStreamingResponse(self) + + async def create( + self, + dir_id: str, + *, + content: str, + parent_comment_id: 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, + ) -> CommentCreateResponse: + """ + Post a customer comment on a DIR (for example, to respond to reviewer notes). + Send only `content` (1–5000 chars) and an optional `parent_comment_id`; the + server sets the comment type, visibility, and author automatically. The + enterprise is resolved server-side from the DIR id. + + Args: + content: Comment body. 1–5000 characters. + + parent_comment_id: Optional parent comment id to thread this reply under. + + 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._post( + path_template("/dir/{dir_id}/comments", dir_id=dir_id), + body=await async_maybe_transform( + { + "content": content, + "parent_comment_id": parent_comment_id, + }, + comment_create_params.CommentCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=CommentCreateResponse, + ) + + def list( + self, + dir_id: str, + *, + comment_type: Literal[ + "vetting_comment", + "rejection_reason", + "internal_note", + "notification", + "status_update", + "customer_inquiry", + "admin_response", + ] + | Omit = omit, + 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[CommentListResponse, AsyncDefaultFlatPagination[CommentListResponse]]: + """List the comments on a DIR. + + The enterprise is resolved server-side from the DIR + id. + + Args: + comment_type: + Restrict to comments of this category. Customer-visible categories only: + internal-only comments are filtered out regardless of this filter. + + 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_api_list( + path_template("/dir/{dir_id}/comments", dir_id=dir_id), + page=AsyncDefaultFlatPagination[CommentListResponse], + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "comment_type": comment_type, + "page_number": page_number, + "page_size": page_size, + }, + comment_list_params.CommentListParams, + ), + ), + model=CommentListResponse, + ) + + +class CommentsResourceWithRawResponse: + def __init__(self, comments: CommentsResource) -> None: + self._comments = comments + + self.create = to_raw_response_wrapper( + comments.create, + ) + self.list = to_raw_response_wrapper( + comments.list, + ) + + +class AsyncCommentsResourceWithRawResponse: + def __init__(self, comments: AsyncCommentsResource) -> None: + self._comments = comments + + self.create = async_to_raw_response_wrapper( + comments.create, + ) + self.list = async_to_raw_response_wrapper( + comments.list, + ) + + +class CommentsResourceWithStreamingResponse: + def __init__(self, comments: CommentsResource) -> None: + self._comments = comments + + self.create = to_streamed_response_wrapper( + comments.create, + ) + self.list = to_streamed_response_wrapper( + comments.list, + ) + + +class AsyncCommentsResourceWithStreamingResponse: + def __init__(self, comments: AsyncCommentsResource) -> None: + self._comments = comments + + self.create = async_to_streamed_response_wrapper( + comments.create, + ) + self.list = async_to_streamed_response_wrapper( + comments.list, + ) diff --git a/src/telnyx/resources/dir/dir.py b/src/telnyx/resources/dir/dir.py new file mode 100644 index 00000000..c57fd8d4 --- /dev/null +++ b/src/telnyx/resources/dir/dir.py @@ -0,0 +1,1227 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Union, Iterable, Optional +from datetime import datetime +from typing_extensions import Literal + +import httpx + +from ...types import ( + dir_list_params, + dir_update_params, + dir_update_infringement_params, + dir_list_infringement_claims_params, +) +from ..._types import Body, Omit, Query, Headers, NoneType, NotGiven, SequenceNotStr, omit, not_given +from ..._utils import path_template, maybe_transform, async_maybe_transform +from .comments import ( + CommentsResource, + AsyncCommentsResource, + CommentsResourceWithRawResponse, + AsyncCommentsResourceWithRawResponse, + CommentsResourceWithStreamingResponse, + AsyncCommentsResourceWithStreamingResponse, +) +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 .phone_numbers import ( + PhoneNumbersResource, + AsyncPhoneNumbersResource, + PhoneNumbersResourceWithRawResponse, + AsyncPhoneNumbersResourceWithRawResponse, + PhoneNumbersResourceWithStreamingResponse, + AsyncPhoneNumbersResourceWithStreamingResponse, +) +from ..._base_client import AsyncPaginator, make_request_options +from .phone_number_batches import ( + PhoneNumberBatchesResource, + AsyncPhoneNumberBatchesResource, + PhoneNumberBatchesResourceWithRawResponse, + AsyncPhoneNumberBatchesResourceWithRawResponse, + PhoneNumberBatchesResourceWithStreamingResponse, + AsyncPhoneNumberBatchesResourceWithStreamingResponse, +) +from ...types.dir_list_response import DirListResponse +from ...types.dir_submit_response import DirSubmitResponse +from ...types.dir_update_response import DirUpdateResponse +from ...types.dir_retrieve_response import DirRetrieveResponse +from ...types.dir_list_document_types_response import DirListDocumentTypesResponse +from ...types.dir_update_infringement_response import DirUpdateInfringementResponse +from ...types.dir_list_infringement_claims_response import DirListInfringementClaimsResponse + +__all__ = ["DirResource", "AsyncDirResource"] + + +class DirResource(SyncAPIResource): + @cached_property + def comments(self) -> CommentsResource: + """ + Read messages from the Telnyx vetting team and reply with clarifying information. + """ + return CommentsResource(self._client) + + @cached_property + def phone_number_batches(self) -> PhoneNumberBatchesResource: + """Phone numbers are submitted to Telnyx for vetting in batches. + + Batches group all numbers added in a single request under the same Letter of Authorization. + """ + return PhoneNumberBatchesResource(self._client) + + @cached_property + def phone_numbers(self) -> PhoneNumbersResource: + """ + Associate phone numbers with a verified DIR so calls from those numbers carry the DIR's display identity. + """ + return PhoneNumbersResource(self._client) + + @cached_property + def with_raw_response(self) -> DirResourceWithRawResponse: + """ + 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 DirResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> DirResourceWithStreamingResponse: + """ + 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 DirResourceWithStreamingResponse(self) + + def retrieve( + self, + dir_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, + ) -> DirRetrieveResponse: + """Returns a single DIR by id. + + The enterprise is resolved server-side from the DIR + id. Returns `404` if the DIR does not exist or is not yours. + + 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 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}", dir_id=dir_id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=DirRetrieveResponse, + ) + + def update( + self, + dir_id: str, + *, + authorizer_email: str | Omit = omit, + authorizer_name: str | Omit = omit, + call_reasons: SequenceNotStr[str] | Omit = omit, + display_name: str | Omit = omit, + logo_url: str | Omit = omit, + reselling: 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, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> DirUpdateResponse: + """Edit a DIR. + + Only DIRs in `draft`, `rejected`, `unsuccessful`, or `suspended` are + editable. PATCH is a pure edit — `status` is never changed by this endpoint. To + re-vet after editing, call `POST /v2/dir/{dir_id}/submit` explicitly. + + Args: + authorizer_email: Contact email of the authorizer. Telnyx may send verification or infringement + notices here. + + authorizer_name: Name of the person at your enterprise authorizing this DIR. Must be a real + individual. + + call_reasons: 1–10 reasons your business calls customers. Validate phrasing against + `POST /call_reasons/validate`. + + display_name: Name shown to call recipients. 1–35 characters, no emoji, not whitespace-only. + + logo_url: Publicly accessible HTTPS URL (max 128 chars) to a 256x256 BMP logo (max 1 MB). + + reselling: Set to true if your organization places calls on behalf of other enterprises + (BPO/reseller). Updating this triggers re-vetting on next submit. + + 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._patch( + path_template("/dir/{dir_id}", dir_id=dir_id), + body=maybe_transform( + { + "authorizer_email": authorizer_email, + "authorizer_name": authorizer_name, + "call_reasons": call_reasons, + "display_name": display_name, + "logo_url": logo_url, + "reselling": reselling, + }, + dir_update_params.DirUpdateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=DirUpdateResponse, + ) + + def list( + self, + *, + enterprise_id: str | Omit = omit, + filter_expiring_at_gte: Union[str, datetime] | Omit = omit, + filter_expiring_at_lte: Union[str, datetime] | Omit = omit, + page_number: int | Omit = omit, + page_size: int | Omit = omit, + search: str | Omit = omit, + sort: Literal[ + "created_at", + "-created_at", + "updated_at", + "-updated_at", + "display_name", + "-display_name", + "status", + "-status", + ] + | Omit = omit, + status: Literal[ + "draft", + "submitted", + "in_review", + "verified", + "rejected", + "unsuccessful", + "suspended", + "expired", + "infringement_claimed", + "permanently_rejected", + ] + | 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[DirListResponse]: + """ + Convenience endpoint that returns every DIR you own without scoping to a + specific enterprise. Equivalent to calling + `GET /v2/enterprises/{enterprise_id}/dir` for each enterprise and concatenating + the results, but server-side and paginated as a single list. + + Args: + enterprise_id: Restrict results to a single enterprise. + + filter_expiring_at_gte: Return only DIRs whose `expiring_at` is at or after this ISO-8601 timestamp. + Pairs with the `[lte]` variant to build renewal-window dashboards. + + filter_expiring_at_lte: Return only DIRs whose `expiring_at` is at or before this ISO-8601 timestamp. + + 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. + + search: Case-insensitive partial match on `display_name` or call reason. + + sort: Sort field. Allowed values: `created_at`, `updated_at`, `display_name`, + `status`. Prefix with `-` for descending. Default `-created_at`. + + status: Filter by DIR status. + + 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( + "/dir", + page=SyncDefaultFlatPagination[DirListResponse], + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "enterprise_id": enterprise_id, + "filter_expiring_at_gte": filter_expiring_at_gte, + "filter_expiring_at_lte": filter_expiring_at_lte, + "page_number": page_number, + "page_size": page_size, + "search": search, + "sort": sort, + "status": status, + }, + dir_list_params.DirListParams, + ), + ), + model=DirListResponse, + ) + + def delete( + self, + dir_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, + ) -> None: + """Delete 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. + + 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 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, + ) + + def list_document_types( + 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, + ) -> DirListDocumentTypesResponse: + """ + Reference list of `document_type` values accepted by + `DirCreateRequest.documents[].document_type` and the infringement-contest + endpoint. Each entry has a stable `short_name` (used in API calls) and a + customer-facing description. + """ + return self._get( + "/dir/document_types", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=DirListDocumentTypesResponse, + ) + + def list_infringement_claims( + 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, + ) -> SyncDefaultFlatPagination[DirListInfringementClaimsResponse]: + """Return the trademark or copyright claims filed against this DIR. + + Each claim's + `status` is `pending` (newly filed; DIR auto-suspended), `contested` (you have + submitted contest evidence; awaiting resolution), or `resolved` (final). + Resolution outcomes: `upheld` (claim accepted; DIR stays + suspended/permanently_rejected), `rejected` (claim dismissed; DIR restored to + `verified`), `modified` (partial outcome). + + 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_api_list( + path_template("/dir/{dir_id}/infringement_claims", dir_id=dir_id), + page=SyncDefaultFlatPagination[DirListInfringementClaimsResponse], + 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_list_infringement_claims_params.DirListInfringementClaimsParams, + ), + ), + model=DirListInfringementClaimsResponse, + ) + + def submit( + self, + dir_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, + ) -> DirSubmitResponse: + """Submit a DIR for vetting. + + Sends the DIR back through the vetting cycle from any + non-terminal status. When re-submitting from `suspended` or `expired`, the DIR's + previous Branded Calling registration is torn down transactionally and its phone + numbers flip back to `submitted`. When re-submitting from `verified`, the + existing registration stays live throughout the new vetting cycle. + + Returns `400` from `submitted`/`in_review`/`permanently_rejected`. Returns `409` + if the DIR has an unresolved infringement claim. + + 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 dir_id: + raise ValueError(f"Expected a non-empty value for `dir_id` but received {dir_id!r}") + return self._post( + path_template("/dir/{dir_id}/submit", dir_id=dir_id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=DirSubmitResponse, + ) + + def update_infringement( + self, + dir_id: str, + *, + certify_brand_is_accurate: Literal[True], + certify_ip_ownership: Literal[True], + certify_no_infringement: Literal[True], + certify_no_shaft_content: Literal[True], + infringement_resolution_notes: str, + call_reasons: Optional[SequenceNotStr[str]] | Omit = omit, + display_name: Optional[str] | Omit = omit, + documents: Optional[Iterable[dir_update_infringement_params.Document]] | Omit = omit, + logo_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, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> DirUpdateInfringementResponse: + """ + Push a fix for a DIR that is `suspended` with an open infringement claim back + into vetting. `POST /dir/{dir_id}/submit` is blocked while a claim is open, so + this is the customer-callable path to update the DIR's content and re-certify + before Telnyx adjudicates the claim. All four certification booleans must be + `true`. Optional content fields (`display_name`, `logo_url`, `call_reasons`, + `documents`) update the DIR; documents are append-only. + + Args: + certify_brand_is_accurate: Must be `true`. + + certify_ip_ownership: Must be `true`. + + certify_no_infringement: Must be `true`. + + certify_no_shaft_content: Must be `true`. + + infringement_resolution_notes: Explanation of how the infringement concern was addressed. + + documents: Append-only supporting documents. + + logo_url: Publicly accessible HTTPS URL (max 128 chars) to a 256x256 BMP logo (max 1 MB). + + 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._put( + path_template("/dir/{dir_id}/infringement_update", dir_id=dir_id), + body=maybe_transform( + { + "certify_brand_is_accurate": certify_brand_is_accurate, + "certify_ip_ownership": certify_ip_ownership, + "certify_no_infringement": certify_no_infringement, + "certify_no_shaft_content": certify_no_shaft_content, + "infringement_resolution_notes": infringement_resolution_notes, + "call_reasons": call_reasons, + "display_name": display_name, + "documents": documents, + "logo_url": logo_url, + }, + dir_update_infringement_params.DirUpdateInfringementParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=DirUpdateInfringementResponse, + ) + + +class AsyncDirResource(AsyncAPIResource): + @cached_property + def comments(self) -> AsyncCommentsResource: + """ + Read messages from the Telnyx vetting team and reply with clarifying information. + """ + return AsyncCommentsResource(self._client) + + @cached_property + def phone_number_batches(self) -> AsyncPhoneNumberBatchesResource: + """Phone numbers are submitted to Telnyx for vetting in batches. + + Batches group all numbers added in a single request under the same Letter of Authorization. + """ + return AsyncPhoneNumberBatchesResource(self._client) + + @cached_property + def phone_numbers(self) -> AsyncPhoneNumbersResource: + """ + Associate phone numbers with a verified DIR so calls from those numbers carry the DIR's display identity. + """ + return AsyncPhoneNumbersResource(self._client) + + @cached_property + def with_raw_response(self) -> AsyncDirResourceWithRawResponse: + """ + 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 AsyncDirResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncDirResourceWithStreamingResponse: + """ + 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 AsyncDirResourceWithStreamingResponse(self) + + async def retrieve( + self, + dir_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, + ) -> DirRetrieveResponse: + """Returns a single DIR by id. + + The enterprise is resolved server-side from the DIR + id. Returns `404` if the DIR does not exist or is not yours. + + 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 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}", dir_id=dir_id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=DirRetrieveResponse, + ) + + async def update( + self, + dir_id: str, + *, + authorizer_email: str | Omit = omit, + authorizer_name: str | Omit = omit, + call_reasons: SequenceNotStr[str] | Omit = omit, + display_name: str | Omit = omit, + logo_url: str | Omit = omit, + reselling: 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, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> DirUpdateResponse: + """Edit a DIR. + + Only DIRs in `draft`, `rejected`, `unsuccessful`, or `suspended` are + editable. PATCH is a pure edit — `status` is never changed by this endpoint. To + re-vet after editing, call `POST /v2/dir/{dir_id}/submit` explicitly. + + Args: + authorizer_email: Contact email of the authorizer. Telnyx may send verification or infringement + notices here. + + authorizer_name: Name of the person at your enterprise authorizing this DIR. Must be a real + individual. + + call_reasons: 1–10 reasons your business calls customers. Validate phrasing against + `POST /call_reasons/validate`. + + display_name: Name shown to call recipients. 1–35 characters, no emoji, not whitespace-only. + + logo_url: Publicly accessible HTTPS URL (max 128 chars) to a 256x256 BMP logo (max 1 MB). + + reselling: Set to true if your organization places calls on behalf of other enterprises + (BPO/reseller). Updating this triggers re-vetting on next submit. + + 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._patch( + path_template("/dir/{dir_id}", dir_id=dir_id), + body=await async_maybe_transform( + { + "authorizer_email": authorizer_email, + "authorizer_name": authorizer_name, + "call_reasons": call_reasons, + "display_name": display_name, + "logo_url": logo_url, + "reselling": reselling, + }, + dir_update_params.DirUpdateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=DirUpdateResponse, + ) + + def list( + self, + *, + enterprise_id: str | Omit = omit, + filter_expiring_at_gte: Union[str, datetime] | Omit = omit, + filter_expiring_at_lte: Union[str, datetime] | Omit = omit, + page_number: int | Omit = omit, + page_size: int | Omit = omit, + search: str | Omit = omit, + sort: Literal[ + "created_at", + "-created_at", + "updated_at", + "-updated_at", + "display_name", + "-display_name", + "status", + "-status", + ] + | Omit = omit, + status: Literal[ + "draft", + "submitted", + "in_review", + "verified", + "rejected", + "unsuccessful", + "suspended", + "expired", + "infringement_claimed", + "permanently_rejected", + ] + | 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[DirListResponse, AsyncDefaultFlatPagination[DirListResponse]]: + """ + Convenience endpoint that returns every DIR you own without scoping to a + specific enterprise. Equivalent to calling + `GET /v2/enterprises/{enterprise_id}/dir` for each enterprise and concatenating + the results, but server-side and paginated as a single list. + + Args: + enterprise_id: Restrict results to a single enterprise. + + filter_expiring_at_gte: Return only DIRs whose `expiring_at` is at or after this ISO-8601 timestamp. + Pairs with the `[lte]` variant to build renewal-window dashboards. + + filter_expiring_at_lte: Return only DIRs whose `expiring_at` is at or before this ISO-8601 timestamp. + + 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. + + search: Case-insensitive partial match on `display_name` or call reason. + + sort: Sort field. Allowed values: `created_at`, `updated_at`, `display_name`, + `status`. Prefix with `-` for descending. Default `-created_at`. + + status: Filter by DIR status. + + 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( + "/dir", + page=AsyncDefaultFlatPagination[DirListResponse], + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "enterprise_id": enterprise_id, + "filter_expiring_at_gte": filter_expiring_at_gte, + "filter_expiring_at_lte": filter_expiring_at_lte, + "page_number": page_number, + "page_size": page_size, + "search": search, + "sort": sort, + "status": status, + }, + dir_list_params.DirListParams, + ), + ), + model=DirListResponse, + ) + + async def delete( + self, + dir_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, + ) -> None: + """Delete 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. + + 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 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, + ) + + async def list_document_types( + 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, + ) -> DirListDocumentTypesResponse: + """ + Reference list of `document_type` values accepted by + `DirCreateRequest.documents[].document_type` and the infringement-contest + endpoint. Each entry has a stable `short_name` (used in API calls) and a + customer-facing description. + """ + return await self._get( + "/dir/document_types", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=DirListDocumentTypesResponse, + ) + + def list_infringement_claims( + 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, + ) -> AsyncPaginator[ + DirListInfringementClaimsResponse, AsyncDefaultFlatPagination[DirListInfringementClaimsResponse] + ]: + """Return the trademark or copyright claims filed against this DIR. + + Each claim's + `status` is `pending` (newly filed; DIR auto-suspended), `contested` (you have + submitted contest evidence; awaiting resolution), or `resolved` (final). + Resolution outcomes: `upheld` (claim accepted; DIR stays + suspended/permanently_rejected), `rejected` (claim dismissed; DIR restored to + `verified`), `modified` (partial outcome). + + 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_api_list( + path_template("/dir/{dir_id}/infringement_claims", dir_id=dir_id), + page=AsyncDefaultFlatPagination[DirListInfringementClaimsResponse], + 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_list_infringement_claims_params.DirListInfringementClaimsParams, + ), + ), + model=DirListInfringementClaimsResponse, + ) + + async def submit( + self, + dir_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, + ) -> DirSubmitResponse: + """Submit a DIR for vetting. + + Sends the DIR back through the vetting cycle from any + non-terminal status. When re-submitting from `suspended` or `expired`, the DIR's + previous Branded Calling registration is torn down transactionally and its phone + numbers flip back to `submitted`. When re-submitting from `verified`, the + existing registration stays live throughout the new vetting cycle. + + Returns `400` from `submitted`/`in_review`/`permanently_rejected`. Returns `409` + if the DIR has an unresolved infringement claim. + + 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 dir_id: + raise ValueError(f"Expected a non-empty value for `dir_id` but received {dir_id!r}") + return await self._post( + path_template("/dir/{dir_id}/submit", dir_id=dir_id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=DirSubmitResponse, + ) + + async def update_infringement( + self, + dir_id: str, + *, + certify_brand_is_accurate: Literal[True], + certify_ip_ownership: Literal[True], + certify_no_infringement: Literal[True], + certify_no_shaft_content: Literal[True], + infringement_resolution_notes: str, + call_reasons: Optional[SequenceNotStr[str]] | Omit = omit, + display_name: Optional[str] | Omit = omit, + documents: Optional[Iterable[dir_update_infringement_params.Document]] | Omit = omit, + logo_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, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> DirUpdateInfringementResponse: + """ + Push a fix for a DIR that is `suspended` with an open infringement claim back + into vetting. `POST /dir/{dir_id}/submit` is blocked while a claim is open, so + this is the customer-callable path to update the DIR's content and re-certify + before Telnyx adjudicates the claim. All four certification booleans must be + `true`. Optional content fields (`display_name`, `logo_url`, `call_reasons`, + `documents`) update the DIR; documents are append-only. + + Args: + certify_brand_is_accurate: Must be `true`. + + certify_ip_ownership: Must be `true`. + + certify_no_infringement: Must be `true`. + + certify_no_shaft_content: Must be `true`. + + infringement_resolution_notes: Explanation of how the infringement concern was addressed. + + documents: Append-only supporting documents. + + logo_url: Publicly accessible HTTPS URL (max 128 chars) to a 256x256 BMP logo (max 1 MB). + + 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._put( + path_template("/dir/{dir_id}/infringement_update", dir_id=dir_id), + body=await async_maybe_transform( + { + "certify_brand_is_accurate": certify_brand_is_accurate, + "certify_ip_ownership": certify_ip_ownership, + "certify_no_infringement": certify_no_infringement, + "certify_no_shaft_content": certify_no_shaft_content, + "infringement_resolution_notes": infringement_resolution_notes, + "call_reasons": call_reasons, + "display_name": display_name, + "documents": documents, + "logo_url": logo_url, + }, + dir_update_infringement_params.DirUpdateInfringementParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=DirUpdateInfringementResponse, + ) + + +class DirResourceWithRawResponse: + def __init__(self, dir: DirResource) -> None: + self._dir = dir + + self.retrieve = to_raw_response_wrapper( + dir.retrieve, + ) + self.update = to_raw_response_wrapper( + dir.update, + ) + self.list = to_raw_response_wrapper( + dir.list, + ) + self.delete = to_raw_response_wrapper( + dir.delete, + ) + self.list_document_types = to_raw_response_wrapper( + dir.list_document_types, + ) + self.list_infringement_claims = to_raw_response_wrapper( + dir.list_infringement_claims, + ) + self.submit = to_raw_response_wrapper( + dir.submit, + ) + self.update_infringement = to_raw_response_wrapper( + dir.update_infringement, + ) + + @cached_property + def comments(self) -> CommentsResourceWithRawResponse: + """ + Read messages from the Telnyx vetting team and reply with clarifying information. + """ + return CommentsResourceWithRawResponse(self._dir.comments) + + @cached_property + def phone_number_batches(self) -> PhoneNumberBatchesResourceWithRawResponse: + """Phone numbers are submitted to Telnyx for vetting in batches. + + Batches group all numbers added in a single request under the same Letter of Authorization. + """ + return PhoneNumberBatchesResourceWithRawResponse(self._dir.phone_number_batches) + + @cached_property + def phone_numbers(self) -> PhoneNumbersResourceWithRawResponse: + """ + Associate phone numbers with a verified DIR so calls from those numbers carry the DIR's display identity. + """ + return PhoneNumbersResourceWithRawResponse(self._dir.phone_numbers) + + +class AsyncDirResourceWithRawResponse: + def __init__(self, dir: AsyncDirResource) -> None: + self._dir = dir + + self.retrieve = async_to_raw_response_wrapper( + dir.retrieve, + ) + self.update = async_to_raw_response_wrapper( + dir.update, + ) + self.list = async_to_raw_response_wrapper( + dir.list, + ) + self.delete = async_to_raw_response_wrapper( + dir.delete, + ) + self.list_document_types = async_to_raw_response_wrapper( + dir.list_document_types, + ) + self.list_infringement_claims = async_to_raw_response_wrapper( + dir.list_infringement_claims, + ) + self.submit = async_to_raw_response_wrapper( + dir.submit, + ) + self.update_infringement = async_to_raw_response_wrapper( + dir.update_infringement, + ) + + @cached_property + def comments(self) -> AsyncCommentsResourceWithRawResponse: + """ + Read messages from the Telnyx vetting team and reply with clarifying information. + """ + return AsyncCommentsResourceWithRawResponse(self._dir.comments) + + @cached_property + def phone_number_batches(self) -> AsyncPhoneNumberBatchesResourceWithRawResponse: + """Phone numbers are submitted to Telnyx for vetting in batches. + + Batches group all numbers added in a single request under the same Letter of Authorization. + """ + return AsyncPhoneNumberBatchesResourceWithRawResponse(self._dir.phone_number_batches) + + @cached_property + def phone_numbers(self) -> AsyncPhoneNumbersResourceWithRawResponse: + """ + Associate phone numbers with a verified DIR so calls from those numbers carry the DIR's display identity. + """ + return AsyncPhoneNumbersResourceWithRawResponse(self._dir.phone_numbers) + + +class DirResourceWithStreamingResponse: + def __init__(self, dir: DirResource) -> None: + self._dir = dir + + self.retrieve = to_streamed_response_wrapper( + dir.retrieve, + ) + self.update = to_streamed_response_wrapper( + dir.update, + ) + self.list = to_streamed_response_wrapper( + dir.list, + ) + self.delete = to_streamed_response_wrapper( + dir.delete, + ) + self.list_document_types = to_streamed_response_wrapper( + dir.list_document_types, + ) + self.list_infringement_claims = to_streamed_response_wrapper( + dir.list_infringement_claims, + ) + self.submit = to_streamed_response_wrapper( + dir.submit, + ) + self.update_infringement = to_streamed_response_wrapper( + dir.update_infringement, + ) + + @cached_property + def comments(self) -> CommentsResourceWithStreamingResponse: + """ + Read messages from the Telnyx vetting team and reply with clarifying information. + """ + return CommentsResourceWithStreamingResponse(self._dir.comments) + + @cached_property + def phone_number_batches(self) -> PhoneNumberBatchesResourceWithStreamingResponse: + """Phone numbers are submitted to Telnyx for vetting in batches. + + Batches group all numbers added in a single request under the same Letter of Authorization. + """ + return PhoneNumberBatchesResourceWithStreamingResponse(self._dir.phone_number_batches) + + @cached_property + def phone_numbers(self) -> PhoneNumbersResourceWithStreamingResponse: + """ + Associate phone numbers with a verified DIR so calls from those numbers carry the DIR's display identity. + """ + return PhoneNumbersResourceWithStreamingResponse(self._dir.phone_numbers) + + +class AsyncDirResourceWithStreamingResponse: + def __init__(self, dir: AsyncDirResource) -> None: + self._dir = dir + + self.retrieve = async_to_streamed_response_wrapper( + dir.retrieve, + ) + self.update = async_to_streamed_response_wrapper( + dir.update, + ) + self.list = async_to_streamed_response_wrapper( + dir.list, + ) + self.delete = async_to_streamed_response_wrapper( + dir.delete, + ) + self.list_document_types = async_to_streamed_response_wrapper( + dir.list_document_types, + ) + self.list_infringement_claims = async_to_streamed_response_wrapper( + dir.list_infringement_claims, + ) + self.submit = async_to_streamed_response_wrapper( + dir.submit, + ) + self.update_infringement = async_to_streamed_response_wrapper( + dir.update_infringement, + ) + + @cached_property + def comments(self) -> AsyncCommentsResourceWithStreamingResponse: + """ + Read messages from the Telnyx vetting team and reply with clarifying information. + """ + return AsyncCommentsResourceWithStreamingResponse(self._dir.comments) + + @cached_property + def phone_number_batches(self) -> AsyncPhoneNumberBatchesResourceWithStreamingResponse: + """Phone numbers are submitted to Telnyx for vetting in batches. + + Batches group all numbers added in a single request under the same Letter of Authorization. + """ + return AsyncPhoneNumberBatchesResourceWithStreamingResponse(self._dir.phone_number_batches) + + @cached_property + def phone_numbers(self) -> AsyncPhoneNumbersResourceWithStreamingResponse: + """ + Associate phone numbers with a verified DIR so calls from those numbers carry the DIR's display identity. + """ + return AsyncPhoneNumbersResourceWithStreamingResponse(self._dir.phone_numbers) diff --git a/src/telnyx/resources/dir/phone_number_batches.py b/src/telnyx/resources/dir/phone_number_batches.py new file mode 100644 index 00000000..3dbb75e6 --- /dev/null +++ b/src/telnyx/resources/dir/phone_number_batches.py @@ -0,0 +1,319 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal + +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 ...types.dir import phone_number_batch_list_params +from ...pagination import SyncDefaultFlatPagination, AsyncDefaultFlatPagination +from ..._base_client import AsyncPaginator, make_request_options +from ...types.dir.phone_number_batch_list_response import PhoneNumberBatchListResponse +from ...types.dir.phone_number_batch_retrieve_response import PhoneNumberBatchRetrieveResponse + +__all__ = ["PhoneNumberBatchesResource", "AsyncPhoneNumberBatchesResource"] + + +class PhoneNumberBatchesResource(SyncAPIResource): + """Phone numbers are submitted to Telnyx for vetting in batches. + + Batches group all numbers added in a single request under the same Letter of Authorization. + """ + + @cached_property + def with_raw_response(self) -> PhoneNumberBatchesResourceWithRawResponse: + """ + 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 PhoneNumberBatchesResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> PhoneNumberBatchesResourceWithStreamingResponse: + """ + 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 PhoneNumberBatchesResourceWithStreamingResponse(self) + + def retrieve( + self, + batch_id: str, + *, + dir_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, + ) -> PhoneNumberBatchRetrieveResponse: + """Get a single phone-number batch by id. + + The enterprise is resolved server-side + from the DIR id. + + 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 dir_id: + raise ValueError(f"Expected a non-empty value for `dir_id` but received {dir_id!r}") + if not batch_id: + raise ValueError(f"Expected a non-empty value for `batch_id` but received {batch_id!r}") + return self._get( + path_template("/dir/{dir_id}/phone_number_batches/{batch_id}", dir_id=dir_id, batch_id=batch_id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=PhoneNumberBatchRetrieveResponse, + ) + + def list( + self, + dir_id: str, + *, + filter_status: Literal[ + "submitted", "in_review", "verified", "unsuccessful", "suspended", "expired", "permanently_rejected" + ] + | Omit = omit, + 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[PhoneNumberBatchListResponse]: + """List the phone-number batches submitted under a DIR. + + The enterprise is resolved + server-side from the DIR id. + + Args: + filter_status: Restrict to batches whose aggregate status equals this value. + + 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_api_list( + path_template("/dir/{dir_id}/phone_number_batches", dir_id=dir_id), + page=SyncDefaultFlatPagination[PhoneNumberBatchListResponse], + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "filter_status": filter_status, + "page_number": page_number, + "page_size": page_size, + }, + phone_number_batch_list_params.PhoneNumberBatchListParams, + ), + ), + model=PhoneNumberBatchListResponse, + ) + + +class AsyncPhoneNumberBatchesResource(AsyncAPIResource): + """Phone numbers are submitted to Telnyx for vetting in batches. + + Batches group all numbers added in a single request under the same Letter of Authorization. + """ + + @cached_property + def with_raw_response(self) -> AsyncPhoneNumberBatchesResourceWithRawResponse: + """ + 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 AsyncPhoneNumberBatchesResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncPhoneNumberBatchesResourceWithStreamingResponse: + """ + 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 AsyncPhoneNumberBatchesResourceWithStreamingResponse(self) + + async def retrieve( + self, + batch_id: str, + *, + dir_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, + ) -> PhoneNumberBatchRetrieveResponse: + """Get a single phone-number batch by id. + + The enterprise is resolved server-side + from the DIR id. + + 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 dir_id: + raise ValueError(f"Expected a non-empty value for `dir_id` but received {dir_id!r}") + if not batch_id: + raise ValueError(f"Expected a non-empty value for `batch_id` but received {batch_id!r}") + return await self._get( + path_template("/dir/{dir_id}/phone_number_batches/{batch_id}", dir_id=dir_id, batch_id=batch_id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=PhoneNumberBatchRetrieveResponse, + ) + + def list( + self, + dir_id: str, + *, + filter_status: Literal[ + "submitted", "in_review", "verified", "unsuccessful", "suspended", "expired", "permanently_rejected" + ] + | Omit = omit, + 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[PhoneNumberBatchListResponse, AsyncDefaultFlatPagination[PhoneNumberBatchListResponse]]: + """List the phone-number batches submitted under a DIR. + + The enterprise is resolved + server-side from the DIR id. + + Args: + filter_status: Restrict to batches whose aggregate status equals this value. + + 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_api_list( + path_template("/dir/{dir_id}/phone_number_batches", dir_id=dir_id), + page=AsyncDefaultFlatPagination[PhoneNumberBatchListResponse], + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "filter_status": filter_status, + "page_number": page_number, + "page_size": page_size, + }, + phone_number_batch_list_params.PhoneNumberBatchListParams, + ), + ), + model=PhoneNumberBatchListResponse, + ) + + +class PhoneNumberBatchesResourceWithRawResponse: + def __init__(self, phone_number_batches: PhoneNumberBatchesResource) -> None: + self._phone_number_batches = phone_number_batches + + self.retrieve = to_raw_response_wrapper( + phone_number_batches.retrieve, + ) + self.list = to_raw_response_wrapper( + phone_number_batches.list, + ) + + +class AsyncPhoneNumberBatchesResourceWithRawResponse: + def __init__(self, phone_number_batches: AsyncPhoneNumberBatchesResource) -> None: + self._phone_number_batches = phone_number_batches + + self.retrieve = async_to_raw_response_wrapper( + phone_number_batches.retrieve, + ) + self.list = async_to_raw_response_wrapper( + phone_number_batches.list, + ) + + +class PhoneNumberBatchesResourceWithStreamingResponse: + def __init__(self, phone_number_batches: PhoneNumberBatchesResource) -> None: + self._phone_number_batches = phone_number_batches + + self.retrieve = to_streamed_response_wrapper( + phone_number_batches.retrieve, + ) + self.list = to_streamed_response_wrapper( + phone_number_batches.list, + ) + + +class AsyncPhoneNumberBatchesResourceWithStreamingResponse: + def __init__(self, phone_number_batches: AsyncPhoneNumberBatchesResource) -> None: + self._phone_number_batches = phone_number_batches + + self.retrieve = async_to_streamed_response_wrapper( + phone_number_batches.retrieve, + ) + self.list = async_to_streamed_response_wrapper( + phone_number_batches.list, + ) diff --git a/src/telnyx/resources/dir/phone_numbers.py b/src/telnyx/resources/dir/phone_numbers.py new file mode 100644 index 00000000..e728afab --- /dev/null +++ b/src/telnyx/resources/dir/phone_numbers.py @@ -0,0 +1,445 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Iterable +from typing_extensions import Literal + +import httpx + +from ..._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, 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 ...types.dir import phone_number_add_params, phone_number_list_params, phone_number_remove_params +from ...pagination import SyncDefaultFlatPagination, AsyncDefaultFlatPagination +from ..._base_client import AsyncPaginator, make_request_options +from ...types.dir.phone_number_add_response import PhoneNumberAddResponse +from ...types.dir.phone_number_list_response import PhoneNumberListResponse +from ...types.dir.phone_number_remove_response import PhoneNumberRemoveResponse + +__all__ = ["PhoneNumbersResource", "AsyncPhoneNumbersResource"] + + +class PhoneNumbersResource(SyncAPIResource): + """ + Associate phone numbers with a verified DIR so calls from those numbers carry the DIR's display identity. + """ + + @cached_property + def with_raw_response(self) -> PhoneNumbersResourceWithRawResponse: + """ + 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 PhoneNumbersResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> PhoneNumbersResourceWithStreamingResponse: + """ + 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 PhoneNumbersResourceWithStreamingResponse(self) + + def list( + self, + dir_id: str, + *, + page_number: int | Omit = omit, + page_size: int | Omit = omit, + status: Literal[ + "submitted", "in_review", "verified", "unsuccessful", "suspended", "expired", "permanently_rejected" + ] + | 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[PhoneNumberListResponse]: + """List the phone numbers registered under a DIR. + + The enterprise is resolved + server-side from the DIR id. + + 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. + + status: Filter by phone-number status. + + 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_api_list( + path_template("/dir/{dir_id}/phone_numbers", dir_id=dir_id), + page=SyncDefaultFlatPagination[PhoneNumberListResponse], + 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, + "status": status, + }, + phone_number_list_params.PhoneNumberListParams, + ), + ), + model=PhoneNumberListResponse, + ) + + def add( + self, + dir_id: str, + *, + documents: Iterable[phone_number_add_params.Document], + phone_numbers: SequenceNotStr[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, + ) -> PhoneNumberAddResponse: + """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. + + **Pricing:** This is a billable action. See https://telnyx.com/pricing/numbers + for current pricing. + + Args: + documents: Supporting documents covering this batch. At least one entry with + `document_type: letter_of_authorization` is required — the LOA authorises Telnyx + to register these numbers under the DIR. Each `document_id` must come from the + Telnyx Documents API. Additional document types (e.g. business registration) may + be included alongside the LOA. + + phone_numbers: 1–15 phone numbers in E.164 format. 10-digit US numbers are auto-prefixed with + `1`. + + 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._post( + path_template("/dir/{dir_id}/phone_numbers", dir_id=dir_id), + body=maybe_transform( + { + "documents": documents, + "phone_numbers": phone_numbers, + }, + phone_number_add_params.PhoneNumberAddParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=PhoneNumberAddResponse, + ) + + def remove( + self, + dir_id: str, + *, + phone_numbers: SequenceNotStr[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, + ) -> PhoneNumberRemoveResponse: + """Deregister phone numbers from a DIR. + + The enterprise is resolved server-side from + the DIR id. Returns a partial-success envelope. + + 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 dir_id: + raise ValueError(f"Expected a non-empty value for `dir_id` but received {dir_id!r}") + return self._delete( + path_template("/dir/{dir_id}/phone_numbers", dir_id=dir_id), + body=maybe_transform({"phone_numbers": phone_numbers}, phone_number_remove_params.PhoneNumberRemoveParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=PhoneNumberRemoveResponse, + ) + + +class AsyncPhoneNumbersResource(AsyncAPIResource): + """ + Associate phone numbers with a verified DIR so calls from those numbers carry the DIR's display identity. + """ + + @cached_property + def with_raw_response(self) -> AsyncPhoneNumbersResourceWithRawResponse: + """ + 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 AsyncPhoneNumbersResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncPhoneNumbersResourceWithStreamingResponse: + """ + 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 AsyncPhoneNumbersResourceWithStreamingResponse(self) + + def list( + self, + dir_id: str, + *, + page_number: int | Omit = omit, + page_size: int | Omit = omit, + status: Literal[ + "submitted", "in_review", "verified", "unsuccessful", "suspended", "expired", "permanently_rejected" + ] + | 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[PhoneNumberListResponse, AsyncDefaultFlatPagination[PhoneNumberListResponse]]: + """List the phone numbers registered under a DIR. + + The enterprise is resolved + server-side from the DIR id. + + 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. + + status: Filter by phone-number status. + + 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_api_list( + path_template("/dir/{dir_id}/phone_numbers", dir_id=dir_id), + page=AsyncDefaultFlatPagination[PhoneNumberListResponse], + 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, + "status": status, + }, + phone_number_list_params.PhoneNumberListParams, + ), + ), + model=PhoneNumberListResponse, + ) + + async def add( + self, + dir_id: str, + *, + documents: Iterable[phone_number_add_params.Document], + phone_numbers: SequenceNotStr[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, + ) -> PhoneNumberAddResponse: + """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. + + **Pricing:** This is a billable action. See https://telnyx.com/pricing/numbers + for current pricing. + + Args: + documents: Supporting documents covering this batch. At least one entry with + `document_type: letter_of_authorization` is required — the LOA authorises Telnyx + to register these numbers under the DIR. Each `document_id` must come from the + Telnyx Documents API. Additional document types (e.g. business registration) may + be included alongside the LOA. + + phone_numbers: 1–15 phone numbers in E.164 format. 10-digit US numbers are auto-prefixed with + `1`. + + 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._post( + path_template("/dir/{dir_id}/phone_numbers", dir_id=dir_id), + body=await async_maybe_transform( + { + "documents": documents, + "phone_numbers": phone_numbers, + }, + phone_number_add_params.PhoneNumberAddParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=PhoneNumberAddResponse, + ) + + async def remove( + self, + dir_id: str, + *, + phone_numbers: SequenceNotStr[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, + ) -> PhoneNumberRemoveResponse: + """Deregister phone numbers from a DIR. + + The enterprise is resolved server-side from + the DIR id. Returns a partial-success envelope. + + 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 dir_id: + raise ValueError(f"Expected a non-empty value for `dir_id` but received {dir_id!r}") + return await self._delete( + path_template("/dir/{dir_id}/phone_numbers", dir_id=dir_id), + body=await async_maybe_transform( + {"phone_numbers": phone_numbers}, phone_number_remove_params.PhoneNumberRemoveParams + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=PhoneNumberRemoveResponse, + ) + + +class PhoneNumbersResourceWithRawResponse: + def __init__(self, phone_numbers: PhoneNumbersResource) -> None: + self._phone_numbers = phone_numbers + + self.list = to_raw_response_wrapper( + phone_numbers.list, + ) + self.add = to_raw_response_wrapper( + phone_numbers.add, + ) + self.remove = to_raw_response_wrapper( + phone_numbers.remove, + ) + + +class AsyncPhoneNumbersResourceWithRawResponse: + def __init__(self, phone_numbers: AsyncPhoneNumbersResource) -> None: + self._phone_numbers = phone_numbers + + self.list = async_to_raw_response_wrapper( + phone_numbers.list, + ) + self.add = async_to_raw_response_wrapper( + phone_numbers.add, + ) + self.remove = async_to_raw_response_wrapper( + phone_numbers.remove, + ) + + +class PhoneNumbersResourceWithStreamingResponse: + def __init__(self, phone_numbers: PhoneNumbersResource) -> None: + self._phone_numbers = phone_numbers + + self.list = to_streamed_response_wrapper( + phone_numbers.list, + ) + self.add = to_streamed_response_wrapper( + phone_numbers.add, + ) + self.remove = to_streamed_response_wrapper( + phone_numbers.remove, + ) + + +class AsyncPhoneNumbersResourceWithStreamingResponse: + def __init__(self, phone_numbers: AsyncPhoneNumbersResource) -> None: + self._phone_numbers = phone_numbers + + self.list = async_to_streamed_response_wrapper( + phone_numbers.list, + ) + self.add = async_to_streamed_response_wrapper( + phone_numbers.add, + ) + self.remove = async_to_streamed_response_wrapper( + phone_numbers.remove, + ) diff --git a/src/telnyx/resources/enterprises/__init__.py b/src/telnyx/resources/enterprises/__init__.py index 86b4aea1..f3f33c7f 100644 --- a/src/telnyx/resources/enterprises/__init__.py +++ b/src/telnyx/resources/enterprises/__init__.py @@ -1,5 +1,13 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +from .dir import ( + DirResource, + AsyncDirResource, + DirResourceWithRawResponse, + AsyncDirResourceWithRawResponse, + DirResourceWithStreamingResponse, + AsyncDirResourceWithStreamingResponse, +) from .reputation import ( ReputationResource, AsyncReputationResource, @@ -24,6 +32,12 @@ "AsyncReputationResourceWithRawResponse", "ReputationResourceWithStreamingResponse", "AsyncReputationResourceWithStreamingResponse", + "DirResource", + "AsyncDirResource", + "DirResourceWithRawResponse", + "AsyncDirResourceWithRawResponse", + "DirResourceWithStreamingResponse", + "AsyncDirResourceWithStreamingResponse", "EnterprisesResource", "AsyncEnterprisesResource", "EnterprisesResourceWithRawResponse", diff --git a/src/telnyx/resources/enterprises/dir.py b/src/telnyx/resources/enterprises/dir.py new file mode 100644 index 00000000..a7fc76ad --- /dev/null +++ b/src/telnyx/resources/enterprises/dir.py @@ -0,0 +1,571 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Union, Iterable +from datetime import datetime +from typing_extensions import Literal + +import httpx + +from ..._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, 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 ...pagination import SyncDefaultFlatPagination, AsyncDefaultFlatPagination +from ..._base_client import AsyncPaginator, make_request_options +from ...types.enterprises import dir_list_params, dir_create_params +from ...types.enterprises.dir_list_response import DirListResponse +from ...types.enterprises.dir_create_response import DirCreateResponse + +__all__ = ["DirResource", "AsyncDirResource"] + + +class DirResource(SyncAPIResource): + """ + A Display Identity Record (DIR) is the verified calling identity (display name, logo, call reasons) shown to recipients on outbound calls. + """ + + @cached_property + def with_raw_response(self) -> DirResourceWithRawResponse: + """ + 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 DirResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> DirResourceWithStreamingResponse: + """ + 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 DirResourceWithStreamingResponse(self) + + def create( + self, + enterprise_id: str, + *, + authorizer_email: str, + authorizer_name: str, + certify_brand_is_accurate: Literal[True], + certify_ip_ownership: Literal[True], + certify_no_shaft_content: Literal[True], + display_name: str, + call_reasons: SequenceNotStr[str] | Omit = omit, + documents: Iterable[dir_create_params.Document] | Omit = omit, + logo_url: str | Omit = omit, + reselling: 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, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> DirCreateResponse: + """Create a new DIR under the given enterprise. + + The DIR starts in `draft` status; + it must be submitted (`POST .../submit`) and approved by Telnyx before any phone + number can be attached. + + **Field rules** + + - `display_name`: 1–35 characters, no emoji or whitespace-only strings; this is + the name shown to recipients. + - `call_reasons`: 1–10 strings, each ≤64 characters; describe why your business + calls customers (e.g. 'Appointment reminders', 'Billing inquiries'). Validate + the wording against `POST /call_reasons/validate`. + - `logo_url`: HTTPS URL (max 128 chars) to a 256×256 BMP (max 1 MB). The image + is downloaded and hashed at submission time. + - `documents`: up to 20 entries; each `document_id` must be obtained by + uploading the file via the Telnyx Documents API first. Within one DIR a + `document_id` may only appear once. + - `certify_brand_is_accurate`, `certify_no_shaft_content`, + `certify_ip_ownership` MUST all be `true`. + + **Failure modes** + + - `422` — validation error; `errors[].source.pointer` names the offending field. + - `403` — Branded Calling not activated on this enterprise (see + `POST /enterprises/{id}/branded_calling`). + - `404` — enterprise does not exist or does not belong to your account. + + Args: + authorizer_email: Contact email of the authorizer. Telnyx may send verification or + infringement-notice email here; use a monitored mailbox. + + authorizer_name: Name of the person at your enterprise who is authorizing this DIR registration. + Must be a real individual (used for audit and trademark-claim contests). + + certify_brand_is_accurate: Must be `true`. + + certify_ip_ownership: Must be `true`. Confirms ownership of any logos/trademarks shown. + + certify_no_shaft_content: Must be `true`. Confirms this DIR is not used for SHAFT content (Sex, Hate, + Alcohol, Firearms, Tobacco) where prohibited. + + display_name: Name shown to call recipients. No emoji; not whitespace-only. + + call_reasons: 1–10 reasons your business calls customers. Validate phrasing against + `POST /call_reasons/validate`. + + 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). + + reselling: Set to true if your organization places calls on behalf of other enterprises + (BPO/reseller). + + 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}/dir", enterprise_id=enterprise_id), + body=maybe_transform( + { + "authorizer_email": authorizer_email, + "authorizer_name": authorizer_name, + "certify_brand_is_accurate": certify_brand_is_accurate, + "certify_ip_ownership": certify_ip_ownership, + "certify_no_shaft_content": certify_no_shaft_content, + "display_name": display_name, + "call_reasons": call_reasons, + "documents": documents, + "logo_url": logo_url, + "reselling": reselling, + }, + dir_create_params.DirCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=DirCreateResponse, + ) + + def list( + self, + enterprise_id: str, + *, + filter_expiring_at_gte: Union[str, datetime] | Omit = omit, + filter_expiring_at_lte: Union[str, datetime] | Omit = omit, + filter_expiring_within_days: int | Omit = omit, + page_number: int | Omit = omit, + page_size: int | Omit = omit, + search: str | Omit = omit, + sort: Literal[ + "created_at", + "-created_at", + "updated_at", + "-updated_at", + "display_name", + "-display_name", + "status", + "-status", + "submitted_at", + "-submitted_at", + "verified_at", + "-verified_at", + "expiring_at", + "-expiring_at", + ] + | Omit = omit, + status: Literal[ + "draft", + "submitted", + "in_review", + "verified", + "rejected", + "unsuccessful", + "suspended", + "expired", + "infringement_claimed", + "permanently_rejected", + ] + | 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[DirListResponse]: + """ + Return the DIRs (Display Identity Records) belonging to a single enterprise. + Pagination is JSON:API style (`page[number]`, `page[size]`, max 250). Filterable + by `status`. Searchable by case-insensitive partial match on `display_name` + (`search=`). Sortable by any of `created_at`, `updated_at`, `display_name`, + `status`, `submitted_at`, `verified_at`, `expiring_at` (prefix `-` for + descending; default `-created_at`). Supports the renewal-window filters + `filter[expiring_at][gte]` / `filter[expiring_at][lte]` and the convenience + `filter[expiring_within_days]` (mutually exclusive with the explicit gte/lte + form). + + Args: + filter_expiring_at_gte: Return only DIRs whose `expiring_at` is at or after this ISO-8601 timestamp. + + filter_expiring_at_lte: Return only DIRs whose `expiring_at` is at or before this ISO-8601 timestamp. + + filter_expiring_within_days: Convenience: returns DIRs whose `expiring_at` falls within the next N days + (1–365). Equivalent to setting `filter[expiring_at][gte]=` + + `filter[expiring_at][lte]=`. Mutually exclusive with the explicit + `[gte]`/`[lte]` filters — combining returns 400. + + 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. + + search: Case-insensitive partial match on `display_name`. + + sort: Sort field. Allowed: `created_at`, `updated_at`, `display_name`, `status`, + `submitted_at`, `verified_at`, `expiring_at`. Prefix with `-` for descending. + Default `-created_at`. + + status: Filter by DIR status. + + 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._get_api_list( + path_template("/enterprises/{enterprise_id}/dir", enterprise_id=enterprise_id), + page=SyncDefaultFlatPagination[DirListResponse], + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "filter_expiring_at_gte": filter_expiring_at_gte, + "filter_expiring_at_lte": filter_expiring_at_lte, + "filter_expiring_within_days": filter_expiring_within_days, + "page_number": page_number, + "page_size": page_size, + "search": search, + "sort": sort, + "status": status, + }, + dir_list_params.DirListParams, + ), + ), + model=DirListResponse, + ) + + +class AsyncDirResource(AsyncAPIResource): + """ + A Display Identity Record (DIR) is the verified calling identity (display name, logo, call reasons) shown to recipients on outbound calls. + """ + + @cached_property + def with_raw_response(self) -> AsyncDirResourceWithRawResponse: + """ + 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 AsyncDirResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncDirResourceWithStreamingResponse: + """ + 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 AsyncDirResourceWithStreamingResponse(self) + + async def create( + self, + enterprise_id: str, + *, + authorizer_email: str, + authorizer_name: str, + certify_brand_is_accurate: Literal[True], + certify_ip_ownership: Literal[True], + certify_no_shaft_content: Literal[True], + display_name: str, + call_reasons: SequenceNotStr[str] | Omit = omit, + documents: Iterable[dir_create_params.Document] | Omit = omit, + logo_url: str | Omit = omit, + reselling: 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, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> DirCreateResponse: + """Create a new DIR under the given enterprise. + + The DIR starts in `draft` status; + it must be submitted (`POST .../submit`) and approved by Telnyx before any phone + number can be attached. + + **Field rules** + + - `display_name`: 1–35 characters, no emoji or whitespace-only strings; this is + the name shown to recipients. + - `call_reasons`: 1–10 strings, each ≤64 characters; describe why your business + calls customers (e.g. 'Appointment reminders', 'Billing inquiries'). Validate + the wording against `POST /call_reasons/validate`. + - `logo_url`: HTTPS URL (max 128 chars) to a 256×256 BMP (max 1 MB). The image + is downloaded and hashed at submission time. + - `documents`: up to 20 entries; each `document_id` must be obtained by + uploading the file via the Telnyx Documents API first. Within one DIR a + `document_id` may only appear once. + - `certify_brand_is_accurate`, `certify_no_shaft_content`, + `certify_ip_ownership` MUST all be `true`. + + **Failure modes** + + - `422` — validation error; `errors[].source.pointer` names the offending field. + - `403` — Branded Calling not activated on this enterprise (see + `POST /enterprises/{id}/branded_calling`). + - `404` — enterprise does not exist or does not belong to your account. + + Args: + authorizer_email: Contact email of the authorizer. Telnyx may send verification or + infringement-notice email here; use a monitored mailbox. + + authorizer_name: Name of the person at your enterprise who is authorizing this DIR registration. + Must be a real individual (used for audit and trademark-claim contests). + + certify_brand_is_accurate: Must be `true`. + + certify_ip_ownership: Must be `true`. Confirms ownership of any logos/trademarks shown. + + certify_no_shaft_content: Must be `true`. Confirms this DIR is not used for SHAFT content (Sex, Hate, + Alcohol, Firearms, Tobacco) where prohibited. + + display_name: Name shown to call recipients. No emoji; not whitespace-only. + + call_reasons: 1–10 reasons your business calls customers. Validate phrasing against + `POST /call_reasons/validate`. + + 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). + + reselling: Set to true if your organization places calls on behalf of other enterprises + (BPO/reseller). + + 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}/dir", enterprise_id=enterprise_id), + body=await async_maybe_transform( + { + "authorizer_email": authorizer_email, + "authorizer_name": authorizer_name, + "certify_brand_is_accurate": certify_brand_is_accurate, + "certify_ip_ownership": certify_ip_ownership, + "certify_no_shaft_content": certify_no_shaft_content, + "display_name": display_name, + "call_reasons": call_reasons, + "documents": documents, + "logo_url": logo_url, + "reselling": reselling, + }, + dir_create_params.DirCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=DirCreateResponse, + ) + + def list( + self, + enterprise_id: str, + *, + filter_expiring_at_gte: Union[str, datetime] | Omit = omit, + filter_expiring_at_lte: Union[str, datetime] | Omit = omit, + filter_expiring_within_days: int | Omit = omit, + page_number: int | Omit = omit, + page_size: int | Omit = omit, + search: str | Omit = omit, + sort: Literal[ + "created_at", + "-created_at", + "updated_at", + "-updated_at", + "display_name", + "-display_name", + "status", + "-status", + "submitted_at", + "-submitted_at", + "verified_at", + "-verified_at", + "expiring_at", + "-expiring_at", + ] + | Omit = omit, + status: Literal[ + "draft", + "submitted", + "in_review", + "verified", + "rejected", + "unsuccessful", + "suspended", + "expired", + "infringement_claimed", + "permanently_rejected", + ] + | 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[DirListResponse, AsyncDefaultFlatPagination[DirListResponse]]: + """ + Return the DIRs (Display Identity Records) belonging to a single enterprise. + Pagination is JSON:API style (`page[number]`, `page[size]`, max 250). Filterable + by `status`. Searchable by case-insensitive partial match on `display_name` + (`search=`). Sortable by any of `created_at`, `updated_at`, `display_name`, + `status`, `submitted_at`, `verified_at`, `expiring_at` (prefix `-` for + descending; default `-created_at`). Supports the renewal-window filters + `filter[expiring_at][gte]` / `filter[expiring_at][lte]` and the convenience + `filter[expiring_within_days]` (mutually exclusive with the explicit gte/lte + form). + + Args: + filter_expiring_at_gte: Return only DIRs whose `expiring_at` is at or after this ISO-8601 timestamp. + + filter_expiring_at_lte: Return only DIRs whose `expiring_at` is at or before this ISO-8601 timestamp. + + filter_expiring_within_days: Convenience: returns DIRs whose `expiring_at` falls within the next N days + (1–365). Equivalent to setting `filter[expiring_at][gte]=` + + `filter[expiring_at][lte]=`. Mutually exclusive with the explicit + `[gte]`/`[lte]` filters — combining returns 400. + + 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. + + search: Case-insensitive partial match on `display_name`. + + sort: Sort field. Allowed: `created_at`, `updated_at`, `display_name`, `status`, + `submitted_at`, `verified_at`, `expiring_at`. Prefix with `-` for descending. + Default `-created_at`. + + status: Filter by DIR status. + + 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._get_api_list( + path_template("/enterprises/{enterprise_id}/dir", enterprise_id=enterprise_id), + page=AsyncDefaultFlatPagination[DirListResponse], + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "filter_expiring_at_gte": filter_expiring_at_gte, + "filter_expiring_at_lte": filter_expiring_at_lte, + "filter_expiring_within_days": filter_expiring_within_days, + "page_number": page_number, + "page_size": page_size, + "search": search, + "sort": sort, + "status": status, + }, + dir_list_params.DirListParams, + ), + ), + model=DirListResponse, + ) + + +class DirResourceWithRawResponse: + def __init__(self, dir: DirResource) -> None: + self._dir = dir + + self.create = to_raw_response_wrapper( + dir.create, + ) + self.list = to_raw_response_wrapper( + dir.list, + ) + + +class AsyncDirResourceWithRawResponse: + def __init__(self, dir: AsyncDirResource) -> None: + self._dir = dir + + self.create = async_to_raw_response_wrapper( + dir.create, + ) + self.list = async_to_raw_response_wrapper( + dir.list, + ) + + +class DirResourceWithStreamingResponse: + def __init__(self, dir: DirResource) -> None: + self._dir = dir + + self.create = to_streamed_response_wrapper( + dir.create, + ) + self.list = to_streamed_response_wrapper( + dir.list, + ) + + +class AsyncDirResourceWithStreamingResponse: + def __init__(self, dir: AsyncDirResource) -> None: + self._dir = dir + + self.create = async_to_streamed_response_wrapper( + dir.create, + ) + self.list = async_to_streamed_response_wrapper( + dir.list, + ) diff --git a/src/telnyx/resources/enterprises/enterprises.py b/src/telnyx/resources/enterprises/enterprises.py index 8a9abcee..795ae227 100644 --- a/src/telnyx/resources/enterprises/enterprises.py +++ b/src/telnyx/resources/enterprises/enterprises.py @@ -2,10 +2,19 @@ from __future__ import annotations +from typing import Optional from typing_extensions import Literal import httpx +from .dir import ( + DirResource, + AsyncDirResource, + DirResourceWithRawResponse, + AsyncDirResourceWithRawResponse, + DirResourceWithStreamingResponse, + AsyncDirResourceWithStreamingResponse, +) from ...types import ( enterprise_list_params, enterprise_create_params, @@ -39,19 +48,25 @@ from ...types.enterprise_update_response import EnterpriseUpdateResponse from ...types.organization_contact_param import OrganizationContactParam from ...types.enterprise_retrieve_response import EnterpriseRetrieveResponse +from ...types.enterprise_activate_branded_calling_response import EnterpriseActivateBrandedCallingResponse __all__ = ["EnterprisesResource", "AsyncEnterprisesResource"] class EnterprisesResource(SyncAPIResource): - """Enterprise management for Branded Calling and Number Reputation services""" + """Manage the legal-entity record that owns your DIRs and phone numbers.""" @cached_property def reputation(self) -> ReputationResource: + """Phone-number reputation monitoring (spam-score lookup and tracking).""" + return ReputationResource(self._client) + + @cached_property + def dir(self) -> DirResource: """ - Manage Number Reputation enrollment and check frequency settings for an enterprise + A Display Identity Record (DIR) is the verified calling identity (display name, logo, call reasons) shown to recipients on outbound calls. """ - return ReputationResource(self._client) + return DirResource(self._client) @cached_property def with_raw_response(self) -> EnterprisesResourceWithRawResponse: @@ -80,7 +95,52 @@ def create( country_code: str, doing_business_as: str, fein: str, - industry: str, + industry: Literal[ + "accounting", + "finance", + "billing", + "collections", + "business", + "charity", + "nonprofit", + "communications", + "telecom", + "customer service", + "support", + "delivery", + "shipping", + "logistics", + "education", + "financial", + "banking", + "government", + "public", + "healthcare", + "health", + "pharmacy", + "medical", + "insurance", + "legal", + "law", + "notifications", + "scheduling", + "real estate", + "property", + "retail", + "ecommerce", + "sales", + "marketing", + "software", + "technology", + "tech", + "media", + "surveys", + "market research", + "travel", + "hospitality", + "hotel", + ], + jurisdiction_of_incorporation: str, legal_name: str, number_of_employees: Literal["1-10", "11-50", "51-200", "201-500", "501-2000", "2001-10000", "10001+"], organization_contact: OrganizationContactParam, @@ -88,11 +148,11 @@ def create( organization_physical_address: PhysicalAddressParam, organization_type: Literal["commercial", "government", "non_profit"], website: str, - corporate_registration_number: str | Omit = omit, + corporate_registration_number: Optional[str] | Omit = omit, customer_reference: str | Omit = omit, - dun_bradstreet_number: str | Omit = omit, - primary_business_domain_sic_code: str | Omit = omit, - professional_license_number: str | Omit = omit, + dun_bradstreet_number: Optional[str] | Omit = omit, + primary_business_domain_sic_code: Optional[str] | Omit = omit, + professional_license_number: Optional[str] | Omit = omit, role_type: Literal["enterprise", "bpo"] | 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. @@ -102,57 +162,61 @@ def create( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> EnterpriseCreateResponse: """ - Create a new enterprise for Branded Calling / Number Reputation services. + Create the legal entity that owns your Number Reputation registrations. - Registers the enterprise in the Branded Calling / Number Reputation services, - enabling it to create Display Identity Records (DIRs) or enroll in Number - Reputation monitoring. + The response carries a server-assigned `id` you will use for every subsequent + call. After creating an enterprise and agreeing to the Number Reputation Terms + of Service (`POST /terms_of_service/number_reputation/agree`), enable reputation + monitoring via `POST /enterprises/{enterprise_id}/reputation`. - **Required Fields:** `legal_name`, `doing_business_as`, `organization_type`, - `country_code`, `website`, `fein`, `industry`, `number_of_employees`, - `organization_legal_type`, `organization_contact`, `billing_contact`, - `organization_physical_address`, `billing_address` + An enterprise is shared across Telnyx products; if you also use Branded Calling, + the same enterprise is reused. Args: - country_code: Country code. Currently only 'US' is accepted. + country_code: ISO 3166-1 alpha-2 country code. Currently `US` and `CA` are supported. - doing_business_as: Primary business name / DBA name + fein: US Federal Employer Identification Number (`NN-NNNNNNN`) or Canadian equivalent. - fein: Federal Employer Identification Number. Format: XX-XXXXXXX or 9-digit number - (minimum 9 digits). + industry: Industry classification. - industry: Industry classification. Case-insensitive. Accepted values: accounting, finance, - billing, collections, business, charity, nonprofit, communications, telecom, - customer service, support, delivery, shipping, logistics, education, financial, - banking, government, public, healthcare, health, pharmacy, medical, insurance, - legal, law, notifications, scheduling, real estate, property, retail, ecommerce, - sales, marketing, software, technology, tech, media, surveys, market research, - travel, hospitality, hotel + legal_name: Legal name of the enterprise. - legal_name: Legal name of the enterprise + number_of_employees: Approximate headcount range. Used for vetting heuristics; pick the bucket that + contains your current employee count. - number_of_employees: Employee count range + organization_legal_type: + Legal-entity form. Pick the form that matches your incorporation documents: - organization_contact: Organization contact information. Note: the response returns this object with - the phone field as 'phone' (not 'phone_number'). + - `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_legal_type: Legal structure type + organization_type: + Organization category for vetting purposes: - organization_type: Type of organization + - `commercial` — for-profit business entities (LLC, corp, partnership, sole + proprietorship). Most callers fall here. + - `government` — federal/state/local government bodies. + - `non_profit` — registered 501(c)(3)/equivalent (incl. educational + institutions, charities, religious organisations). - website: Enterprise website URL. Accepts any string — no URL format validation enforced. + corporate_registration_number: Optional corporate-registration / company-number identifier. - corporate_registration_number: Corporate registration number (optional) + customer_reference: Optional free-form string the caller can attach for their own bookkeeping. + Telnyx does not interpret it. - customer_reference: Optional customer reference identifier for your own tracking + dun_bradstreet_number: Optional D-U-N-S Number. - dun_bradstreet_number: D-U-N-S Number (optional) + primary_business_domain_sic_code: Optional SIC code for the primary line of business. - primary_business_domain_sic_code: SIC Code (optional) + professional_license_number: Optional professional-license number for regulated industries. - professional_license_number: Professional license number (optional) - - role_type: Role type in Branded Calling / Number Reputation services + 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. extra_headers: Send extra headers @@ -172,6 +236,7 @@ def create( "doing_business_as": doing_business_as, "fein": fein, "industry": industry, + "jurisdiction_of_incorporation": jurisdiction_of_incorporation, "legal_name": legal_name, "number_of_employees": number_of_employees, "organization_contact": organization_contact, @@ -205,8 +270,10 @@ def retrieve( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> EnterpriseRetrieveResponse: - """ - Retrieve details of a specific enterprise by ID. + """Retrieve a single enterprise by id. + + Returns `404` if the id does not exist or + does not belong to your account. Args: extra_headers: Send extra headers @@ -233,20 +300,65 @@ def update( *, billing_address: BillingAddressParam | Omit = omit, billing_contact: BillingContactParam | Omit = omit, - corporate_registration_number: str | Omit = omit, + corporate_registration_number: Optional[str] | Omit = omit, customer_reference: str | Omit = omit, doing_business_as: str | Omit = omit, - dun_bradstreet_number: str | Omit = omit, + dun_bradstreet_number: Optional[str] | Omit = omit, fein: str | Omit = omit, - industry: str | Omit = omit, - legal_name: str | Omit = omit, - number_of_employees: Literal["1-10", "11-50", "51-200", "201-500", "501-2000", "2001-10000", "10001+"] + industry: Literal[ + "accounting", + "finance", + "billing", + "collections", + "business", + "charity", + "nonprofit", + "communications", + "telecom", + "customer service", + "support", + "delivery", + "shipping", + "logistics", + "education", + "financial", + "banking", + "government", + "public", + "healthcare", + "health", + "pharmacy", + "medical", + "insurance", + "legal", + "law", + "notifications", + "scheduling", + "real estate", + "property", + "retail", + "ecommerce", + "sales", + "marketing", + "software", + "technology", + "tech", + "media", + "surveys", + "market research", + "travel", + "hospitality", + "hotel", + ] | Omit = omit, + jurisdiction_of_incorporation: str | Omit = omit, + legal_name: str | Omit = omit, + number_of_employees: str | Omit = omit, organization_contact: OrganizationContactParam | Omit = omit, - organization_legal_type: Literal["corporation", "llc", "partnership", "nonprofit", "other"] | Omit = omit, + organization_legal_type: str | Omit = omit, organization_physical_address: PhysicalAddressParam | Omit = omit, - primary_business_domain_sic_code: str | Omit = omit, - professional_license_number: str | Omit = omit, + primary_business_domain_sic_code: Optional[str] | Omit = omit, + professional_license_number: Optional[str] | Omit = omit, website: 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. @@ -255,38 +367,18 @@ def update( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> EnterpriseUpdateResponse: - """Update enterprise information. + """Replace the enterprise's mutable fields. - All fields are optional — only the provided - fields will be updated. + Only mutable fields may be sent. + Server-assigned and immutable fields (`id`, `record_type`, `created_at`, + `updated_at`, status fields, `organization_type`, `country_code`, `role_type`) + cannot be changed: including any of them in the body is rejected with + `400 Bad Request` (`Field 'X' is not allowed in this request`). Args: - corporate_registration_number: Corporate registration number - - customer_reference: Customer reference identifier - - doing_business_as: DBA name - - dun_bradstreet_number: D-U-N-S Number - - fein: Federal Employer Identification Number. Format: XX-XXXXXXX or XXXXXXXXX - - industry: Industry classification - - legal_name: Legal name of the enterprise - - number_of_employees: Employee count range + jurisdiction_of_incorporation: Updated state/province/country of incorporation. Optional on update. - organization_contact: Organization contact information. Note: the response returns this object with - the phone field as 'phone' (not 'phone_number'). - - organization_legal_type: Legal structure type - - primary_business_domain_sic_code: SIC Code - - professional_license_number: Professional license number - - website: Company website URL + legal_name: Legal name of the enterprise. extra_headers: Send extra headers @@ -310,6 +402,7 @@ def update( "dun_bradstreet_number": dun_bradstreet_number, "fein": fein, "industry": industry, + "jurisdiction_of_incorporation": jurisdiction_of_incorporation, "legal_name": legal_name, "number_of_employees": number_of_employees, "organization_contact": organization_contact, @@ -340,15 +433,17 @@ def list( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SyncDefaultFlatPagination[EnterprisePublic]: - """ - Retrieve a paginated list of enterprises associated with your account. + """Return the enterprises you own, paginated. + + The default page size is 20; the + maximum is 250. Args: - legal_name: Filter by legal name (partial match) + legal_name: Filter by legal name (partial match). - page_number: Page number (1-indexed) + page_number: 1-based page number. Out-of-range values return an empty page with correct meta. - page_size: Number of items per page + page_size: Items per page. Default 10. Maximum 250; values above are clamped to 250. extra_headers: Send extra headers @@ -389,9 +484,12 @@ def delete( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: - """Delete an enterprise and all associated resources. + """Delete an enterprise. - This action is irreversible. + Fails with `400` if the enterprise still has dependent + resources (e.g. active reputation settings or registered numbers); remove those + first. Returns `404` if the enterprise does not exist or does not belong to your + account. Args: extra_headers: Send extra headers @@ -413,16 +511,73 @@ def delete( cast_to=NoneType, ) + def activate_branded_calling( + 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, + ) -> EnterpriseActivateBrandedCallingResponse: + """ + Branded Calling is a paid product that must be activated on each enterprise. + Activation is idempotent: + + - First call: marks the enterprise as activated and begins onboarding it with + the Branded Calling platform asynchronously. Returns `200` with + `branded_calling_enabled: true`. + - Re-call after success: no-op, returns the same enterprise body. + - Re-call after a prior failure: re-queues onboarding, returns `200`. + + Prerequisite: the calling user must have agreed to the Branded Calling Terms of + Service (`POST /terms_of_service/branded_calling/agree`). Without that, this + endpoint returns `403 terms_of_service_not_accepted`. + + Failure modes: + + - `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. + + 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}/branded_calling", enterprise_id=enterprise_id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=EnterpriseActivateBrandedCallingResponse, + ) + class AsyncEnterprisesResource(AsyncAPIResource): - """Enterprise management for Branded Calling and Number Reputation services""" + """Manage the legal-entity record that owns your DIRs and phone numbers.""" @cached_property def reputation(self) -> AsyncReputationResource: + """Phone-number reputation monitoring (spam-score lookup and tracking).""" + return AsyncReputationResource(self._client) + + @cached_property + def dir(self) -> AsyncDirResource: """ - Manage Number Reputation enrollment and check frequency settings for an enterprise + A Display Identity Record (DIR) is the verified calling identity (display name, logo, call reasons) shown to recipients on outbound calls. """ - return AsyncReputationResource(self._client) + return AsyncDirResource(self._client) @cached_property def with_raw_response(self) -> AsyncEnterprisesResourceWithRawResponse: @@ -451,7 +606,52 @@ async def create( country_code: str, doing_business_as: str, fein: str, - industry: str, + industry: Literal[ + "accounting", + "finance", + "billing", + "collections", + "business", + "charity", + "nonprofit", + "communications", + "telecom", + "customer service", + "support", + "delivery", + "shipping", + "logistics", + "education", + "financial", + "banking", + "government", + "public", + "healthcare", + "health", + "pharmacy", + "medical", + "insurance", + "legal", + "law", + "notifications", + "scheduling", + "real estate", + "property", + "retail", + "ecommerce", + "sales", + "marketing", + "software", + "technology", + "tech", + "media", + "surveys", + "market research", + "travel", + "hospitality", + "hotel", + ], + jurisdiction_of_incorporation: str, legal_name: str, number_of_employees: Literal["1-10", "11-50", "51-200", "201-500", "501-2000", "2001-10000", "10001+"], organization_contact: OrganizationContactParam, @@ -459,11 +659,11 @@ async def create( organization_physical_address: PhysicalAddressParam, organization_type: Literal["commercial", "government", "non_profit"], website: str, - corporate_registration_number: str | Omit = omit, + corporate_registration_number: Optional[str] | Omit = omit, customer_reference: str | Omit = omit, - dun_bradstreet_number: str | Omit = omit, - primary_business_domain_sic_code: str | Omit = omit, - professional_license_number: str | Omit = omit, + dun_bradstreet_number: Optional[str] | Omit = omit, + primary_business_domain_sic_code: Optional[str] | Omit = omit, + professional_license_number: Optional[str] | Omit = omit, role_type: Literal["enterprise", "bpo"] | 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. @@ -473,57 +673,61 @@ async def create( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> EnterpriseCreateResponse: """ - Create a new enterprise for Branded Calling / Number Reputation services. + Create the legal entity that owns your Number Reputation registrations. - Registers the enterprise in the Branded Calling / Number Reputation services, - enabling it to create Display Identity Records (DIRs) or enroll in Number - Reputation monitoring. + The response carries a server-assigned `id` you will use for every subsequent + call. After creating an enterprise and agreeing to the Number Reputation Terms + of Service (`POST /terms_of_service/number_reputation/agree`), enable reputation + monitoring via `POST /enterprises/{enterprise_id}/reputation`. - **Required Fields:** `legal_name`, `doing_business_as`, `organization_type`, - `country_code`, `website`, `fein`, `industry`, `number_of_employees`, - `organization_legal_type`, `organization_contact`, `billing_contact`, - `organization_physical_address`, `billing_address` + An enterprise is shared across Telnyx products; if you also use Branded Calling, + the same enterprise is reused. Args: - country_code: Country code. Currently only 'US' is accepted. + country_code: ISO 3166-1 alpha-2 country code. Currently `US` and `CA` are supported. - doing_business_as: Primary business name / DBA name + fein: US Federal Employer Identification Number (`NN-NNNNNNN`) or Canadian equivalent. - fein: Federal Employer Identification Number. Format: XX-XXXXXXX or 9-digit number - (minimum 9 digits). + industry: Industry classification. - industry: Industry classification. Case-insensitive. Accepted values: accounting, finance, - billing, collections, business, charity, nonprofit, communications, telecom, - customer service, support, delivery, shipping, logistics, education, financial, - banking, government, public, healthcare, health, pharmacy, medical, insurance, - legal, law, notifications, scheduling, real estate, property, retail, ecommerce, - sales, marketing, software, technology, tech, media, surveys, market research, - travel, hospitality, hotel + legal_name: Legal name of the enterprise. - legal_name: Legal name of the enterprise + number_of_employees: Approximate headcount range. Used for vetting heuristics; pick the bucket that + contains your current employee count. - number_of_employees: Employee count range + organization_legal_type: + Legal-entity form. Pick the form that matches your incorporation documents: - organization_contact: Organization contact information. Note: the response returns this object with - the phone field as 'phone' (not 'phone_number'). + - `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_legal_type: Legal structure type + organization_type: + Organization category for vetting purposes: - organization_type: Type of organization + - `commercial` — for-profit business entities (LLC, corp, partnership, sole + proprietorship). Most callers fall here. + - `government` — federal/state/local government bodies. + - `non_profit` — registered 501(c)(3)/equivalent (incl. educational + institutions, charities, religious organisations). - website: Enterprise website URL. Accepts any string — no URL format validation enforced. + corporate_registration_number: Optional corporate-registration / company-number identifier. - corporate_registration_number: Corporate registration number (optional) + customer_reference: Optional free-form string the caller can attach for their own bookkeeping. + Telnyx does not interpret it. - customer_reference: Optional customer reference identifier for your own tracking + dun_bradstreet_number: Optional D-U-N-S Number. - dun_bradstreet_number: D-U-N-S Number (optional) + primary_business_domain_sic_code: Optional SIC code for the primary line of business. - primary_business_domain_sic_code: SIC Code (optional) + professional_license_number: Optional professional-license number for regulated industries. - professional_license_number: Professional license number (optional) - - role_type: Role type in Branded Calling / Number Reputation services + 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. extra_headers: Send extra headers @@ -543,6 +747,7 @@ async def create( "doing_business_as": doing_business_as, "fein": fein, "industry": industry, + "jurisdiction_of_incorporation": jurisdiction_of_incorporation, "legal_name": legal_name, "number_of_employees": number_of_employees, "organization_contact": organization_contact, @@ -576,8 +781,10 @@ async def retrieve( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> EnterpriseRetrieveResponse: - """ - Retrieve details of a specific enterprise by ID. + """Retrieve a single enterprise by id. + + Returns `404` if the id does not exist or + does not belong to your account. Args: extra_headers: Send extra headers @@ -604,20 +811,65 @@ async def update( *, billing_address: BillingAddressParam | Omit = omit, billing_contact: BillingContactParam | Omit = omit, - corporate_registration_number: str | Omit = omit, + corporate_registration_number: Optional[str] | Omit = omit, customer_reference: str | Omit = omit, doing_business_as: str | Omit = omit, - dun_bradstreet_number: str | Omit = omit, + dun_bradstreet_number: Optional[str] | Omit = omit, fein: str | Omit = omit, - industry: str | Omit = omit, - legal_name: str | Omit = omit, - number_of_employees: Literal["1-10", "11-50", "51-200", "201-500", "501-2000", "2001-10000", "10001+"] + industry: Literal[ + "accounting", + "finance", + "billing", + "collections", + "business", + "charity", + "nonprofit", + "communications", + "telecom", + "customer service", + "support", + "delivery", + "shipping", + "logistics", + "education", + "financial", + "banking", + "government", + "public", + "healthcare", + "health", + "pharmacy", + "medical", + "insurance", + "legal", + "law", + "notifications", + "scheduling", + "real estate", + "property", + "retail", + "ecommerce", + "sales", + "marketing", + "software", + "technology", + "tech", + "media", + "surveys", + "market research", + "travel", + "hospitality", + "hotel", + ] | Omit = omit, + jurisdiction_of_incorporation: str | Omit = omit, + legal_name: str | Omit = omit, + number_of_employees: str | Omit = omit, organization_contact: OrganizationContactParam | Omit = omit, - organization_legal_type: Literal["corporation", "llc", "partnership", "nonprofit", "other"] | Omit = omit, + organization_legal_type: str | Omit = omit, organization_physical_address: PhysicalAddressParam | Omit = omit, - primary_business_domain_sic_code: str | Omit = omit, - professional_license_number: str | Omit = omit, + primary_business_domain_sic_code: Optional[str] | Omit = omit, + professional_license_number: Optional[str] | Omit = omit, website: 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. @@ -626,38 +878,18 @@ async def update( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> EnterpriseUpdateResponse: - """Update enterprise information. + """Replace the enterprise's mutable fields. - All fields are optional — only the provided - fields will be updated. + Only mutable fields may be sent. + Server-assigned and immutable fields (`id`, `record_type`, `created_at`, + `updated_at`, status fields, `organization_type`, `country_code`, `role_type`) + cannot be changed: including any of them in the body is rejected with + `400 Bad Request` (`Field 'X' is not allowed in this request`). Args: - corporate_registration_number: Corporate registration number - - customer_reference: Customer reference identifier + jurisdiction_of_incorporation: Updated state/province/country of incorporation. Optional on update. - doing_business_as: DBA name - - dun_bradstreet_number: D-U-N-S Number - - fein: Federal Employer Identification Number. Format: XX-XXXXXXX or XXXXXXXXX - - industry: Industry classification - - legal_name: Legal name of the enterprise - - number_of_employees: Employee count range - - organization_contact: Organization contact information. Note: the response returns this object with - the phone field as 'phone' (not 'phone_number'). - - organization_legal_type: Legal structure type - - primary_business_domain_sic_code: SIC Code - - professional_license_number: Professional license number - - website: Company website URL + legal_name: Legal name of the enterprise. extra_headers: Send extra headers @@ -681,6 +913,7 @@ async def update( "dun_bradstreet_number": dun_bradstreet_number, "fein": fein, "industry": industry, + "jurisdiction_of_incorporation": jurisdiction_of_incorporation, "legal_name": legal_name, "number_of_employees": number_of_employees, "organization_contact": organization_contact, @@ -711,15 +944,17 @@ def list( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> AsyncPaginator[EnterprisePublic, AsyncDefaultFlatPagination[EnterprisePublic]]: - """ - Retrieve a paginated list of enterprises associated with your account. + """Return the enterprises you own, paginated. + + The default page size is 20; the + maximum is 250. Args: - legal_name: Filter by legal name (partial match) + legal_name: Filter by legal name (partial match). - page_number: Page number (1-indexed) + page_number: 1-based page number. Out-of-range values return an empty page with correct meta. - page_size: Number of items per page + page_size: Items per page. Default 10. Maximum 250; values above are clamped to 250. extra_headers: Send extra headers @@ -760,9 +995,12 @@ async def delete( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: - """Delete an enterprise and all associated resources. + """Delete an enterprise. - This action is irreversible. + Fails with `400` if the enterprise still has dependent + resources (e.g. active reputation settings or registered numbers); remove those + first. Returns `404` if the enterprise does not exist or does not belong to your + account. Args: extra_headers: Send extra headers @@ -784,6 +1022,58 @@ async def delete( cast_to=NoneType, ) + async def activate_branded_calling( + 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, + ) -> EnterpriseActivateBrandedCallingResponse: + """ + Branded Calling is a paid product that must be activated on each enterprise. + Activation is idempotent: + + - First call: marks the enterprise as activated and begins onboarding it with + the Branded Calling platform asynchronously. Returns `200` with + `branded_calling_enabled: true`. + - Re-call after success: no-op, returns the same enterprise body. + - Re-call after a prior failure: re-queues onboarding, returns `200`. + + Prerequisite: the calling user must have agreed to the Branded Calling Terms of + Service (`POST /terms_of_service/branded_calling/agree`). Without that, this + endpoint returns `403 terms_of_service_not_accepted`. + + Failure modes: + + - `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. + + 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}/branded_calling", enterprise_id=enterprise_id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=EnterpriseActivateBrandedCallingResponse, + ) + class EnterprisesResourceWithRawResponse: def __init__(self, enterprises: EnterprisesResource) -> None: @@ -804,13 +1094,21 @@ def __init__(self, enterprises: EnterprisesResource) -> None: self.delete = to_raw_response_wrapper( enterprises.delete, ) + self.activate_branded_calling = to_raw_response_wrapper( + enterprises.activate_branded_calling, + ) @cached_property def reputation(self) -> ReputationResourceWithRawResponse: + """Phone-number reputation monitoring (spam-score lookup and tracking).""" + return ReputationResourceWithRawResponse(self._enterprises.reputation) + + @cached_property + def dir(self) -> DirResourceWithRawResponse: """ - Manage Number Reputation enrollment and check frequency settings for an enterprise + A Display Identity Record (DIR) is the verified calling identity (display name, logo, call reasons) shown to recipients on outbound calls. """ - return ReputationResourceWithRawResponse(self._enterprises.reputation) + return DirResourceWithRawResponse(self._enterprises.dir) class AsyncEnterprisesResourceWithRawResponse: @@ -832,13 +1130,21 @@ def __init__(self, enterprises: AsyncEnterprisesResource) -> None: self.delete = async_to_raw_response_wrapper( enterprises.delete, ) + self.activate_branded_calling = async_to_raw_response_wrapper( + enterprises.activate_branded_calling, + ) @cached_property def reputation(self) -> AsyncReputationResourceWithRawResponse: + """Phone-number reputation monitoring (spam-score lookup and tracking).""" + return AsyncReputationResourceWithRawResponse(self._enterprises.reputation) + + @cached_property + def dir(self) -> AsyncDirResourceWithRawResponse: """ - Manage Number Reputation enrollment and check frequency settings for an enterprise + A Display Identity Record (DIR) is the verified calling identity (display name, logo, call reasons) shown to recipients on outbound calls. """ - return AsyncReputationResourceWithRawResponse(self._enterprises.reputation) + return AsyncDirResourceWithRawResponse(self._enterprises.dir) class EnterprisesResourceWithStreamingResponse: @@ -860,13 +1166,21 @@ def __init__(self, enterprises: EnterprisesResource) -> None: self.delete = to_streamed_response_wrapper( enterprises.delete, ) + self.activate_branded_calling = to_streamed_response_wrapper( + enterprises.activate_branded_calling, + ) @cached_property def reputation(self) -> ReputationResourceWithStreamingResponse: + """Phone-number reputation monitoring (spam-score lookup and tracking).""" + return ReputationResourceWithStreamingResponse(self._enterprises.reputation) + + @cached_property + def dir(self) -> DirResourceWithStreamingResponse: """ - Manage Number Reputation enrollment and check frequency settings for an enterprise + A Display Identity Record (DIR) is the verified calling identity (display name, logo, call reasons) shown to recipients on outbound calls. """ - return ReputationResourceWithStreamingResponse(self._enterprises.reputation) + return DirResourceWithStreamingResponse(self._enterprises.dir) class AsyncEnterprisesResourceWithStreamingResponse: @@ -888,10 +1202,18 @@ def __init__(self, enterprises: AsyncEnterprisesResource) -> None: self.delete = async_to_streamed_response_wrapper( enterprises.delete, ) + self.activate_branded_calling = async_to_streamed_response_wrapper( + enterprises.activate_branded_calling, + ) @cached_property def reputation(self) -> AsyncReputationResourceWithStreamingResponse: + """Phone-number reputation monitoring (spam-score lookup and tracking).""" + return AsyncReputationResourceWithStreamingResponse(self._enterprises.reputation) + + @cached_property + def dir(self) -> AsyncDirResourceWithStreamingResponse: """ - Manage Number Reputation enrollment and check frequency settings for an enterprise + A Display Identity Record (DIR) is the verified calling identity (display name, logo, call reasons) shown to recipients on outbound calls. """ - return AsyncReputationResourceWithStreamingResponse(self._enterprises.reputation) + return AsyncDirResourceWithStreamingResponse(self._enterprises.dir) diff --git a/src/telnyx/resources/enterprises/reputation/__init__.py b/src/telnyx/resources/enterprises/reputation/__init__.py index 147c4c1b..18229566 100644 --- a/src/telnyx/resources/enterprises/reputation/__init__.py +++ b/src/telnyx/resources/enterprises/reputation/__init__.py @@ -1,5 +1,13 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +from .loa import ( + LoaResource, + AsyncLoaResource, + LoaResourceWithRawResponse, + AsyncLoaResourceWithRawResponse, + LoaResourceWithStreamingResponse, + AsyncLoaResourceWithStreamingResponse, +) from .numbers import ( NumbersResource, AsyncNumbersResource, @@ -24,6 +32,12 @@ "AsyncNumbersResourceWithRawResponse", "NumbersResourceWithStreamingResponse", "AsyncNumbersResourceWithStreamingResponse", + "LoaResource", + "AsyncLoaResource", + "LoaResourceWithRawResponse", + "AsyncLoaResourceWithRawResponse", + "LoaResourceWithStreamingResponse", + "AsyncLoaResourceWithStreamingResponse", "ReputationResource", "AsyncReputationResource", "ReputationResourceWithRawResponse", diff --git a/src/telnyx/resources/enterprises/reputation/loa.py b/src/telnyx/resources/enterprises/reputation/loa.py new file mode 100644 index 00000000..f394d214 --- /dev/null +++ b/src/telnyx/resources/enterprises/reputation/loa.py @@ -0,0 +1,323 @@ +# 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, async_maybe_transform +from ...._compat import cached_property +from ...._resource import SyncAPIResource, AsyncAPIResource +from ...._response import ( + BinaryAPIResponse, + AsyncBinaryAPIResponse, + StreamedBinaryAPIResponse, + AsyncStreamedBinaryAPIResponse, + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + to_custom_raw_response_wrapper, + async_to_streamed_response_wrapper, + to_custom_streamed_response_wrapper, + async_to_custom_raw_response_wrapper, + async_to_custom_streamed_response_wrapper, +) +from ...._base_client import make_request_options +from ....types.enterprises.reputation import loa_render_params, loa_update_params +from ....types.enterprises.reputation.loa_update_response import LoaUpdateResponse + +__all__ = ["LoaResource", "AsyncLoaResource"] + + +class LoaResource(SyncAPIResource): + """Phone-number reputation monitoring (spam-score lookup and tracking).""" + + @cached_property + def with_raw_response(self) -> LoaResourceWithRawResponse: + """ + 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 LoaResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> LoaResourceWithStreamingResponse: + """ + 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 LoaResourceWithStreamingResponse(self) + + def update( + self, + enterprise_id: str, + *, + loa_document_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, + ) -> LoaUpdateResponse: + """Point the enterprise's reputation settings at a new signed LOA document. + + This + resets LOA approval to `pending`; the new document must be approved before + additional phone numbers can be added. + + Args: + loa_document_id: Id of the new signed LOA document (from the Telnyx Documents API). Changing it + resets LOA approval; the new document must be approved before more numbers can + be added. + + 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._patch( + path_template("/enterprises/{enterprise_id}/reputation/loa", enterprise_id=enterprise_id), + body=maybe_transform({"loa_document_id": loa_document_id}, loa_update_params.LoaUpdateParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=LoaUpdateResponse, + ) + + def render( + self, + enterprise_id: str, + *, + 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. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> BinaryAPIResponse: + """Render the LOA for this enterprise as a PDF. + + The enterprise identity, address, + and authorized-representative contact are taken from the enterprise record; the + optional `agent` block is supplied only when a third-party partner manages the + numbers. The response is the PDF itself (unsigned unless a `signature` is + provided). Sign it and upload it to the Telnyx Documents API + (`POST /v2/documents`, see https://developers.telnyx.com/api/documents) to + obtain the `loa_document_id` required by `POST .../reputation`. + + Args: + agent: Third-party reseller / partner managing the enterprise's phone numbers. Omit + when the enterprise works directly with Telnyx. + + signature: Optional signature embedded in the rendered PDF. When omitted the PDF is + returned unsigned for the customer to sign and upload. + + 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}") + extra_headers = {"Accept": "application/pdf", **(extra_headers or {})} + return self._post( + path_template("/enterprises/{enterprise_id}/reputation/loa", enterprise_id=enterprise_id), + body=maybe_transform( + { + "agent": agent, + "signature": signature, + }, + loa_render_params.LoaRenderParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=BinaryAPIResponse, + ) + + +class AsyncLoaResource(AsyncAPIResource): + """Phone-number reputation monitoring (spam-score lookup and tracking).""" + + @cached_property + def with_raw_response(self) -> AsyncLoaResourceWithRawResponse: + """ + 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 AsyncLoaResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncLoaResourceWithStreamingResponse: + """ + 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 AsyncLoaResourceWithStreamingResponse(self) + + async def update( + self, + enterprise_id: str, + *, + loa_document_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, + ) -> LoaUpdateResponse: + """Point the enterprise's reputation settings at a new signed LOA document. + + This + resets LOA approval to `pending`; the new document must be approved before + additional phone numbers can be added. + + Args: + loa_document_id: Id of the new signed LOA document (from the Telnyx Documents API). Changing it + resets LOA approval; the new document must be approved before more numbers can + be added. + + 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._patch( + path_template("/enterprises/{enterprise_id}/reputation/loa", enterprise_id=enterprise_id), + body=await async_maybe_transform({"loa_document_id": loa_document_id}, loa_update_params.LoaUpdateParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=LoaUpdateResponse, + ) + + async def render( + self, + enterprise_id: str, + *, + 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. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> AsyncBinaryAPIResponse: + """Render the LOA for this enterprise as a PDF. + + The enterprise identity, address, + and authorized-representative contact are taken from the enterprise record; the + optional `agent` block is supplied only when a third-party partner manages the + numbers. The response is the PDF itself (unsigned unless a `signature` is + provided). Sign it and upload it to the Telnyx Documents API + (`POST /v2/documents`, see https://developers.telnyx.com/api/documents) to + obtain the `loa_document_id` required by `POST .../reputation`. + + Args: + agent: Third-party reseller / partner managing the enterprise's phone numbers. Omit + when the enterprise works directly with Telnyx. + + signature: Optional signature embedded in the rendered PDF. When omitted the PDF is + returned unsigned for the customer to sign and upload. + + 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}") + extra_headers = {"Accept": "application/pdf", **(extra_headers or {})} + return await self._post( + path_template("/enterprises/{enterprise_id}/reputation/loa", enterprise_id=enterprise_id), + body=await async_maybe_transform( + { + "agent": agent, + "signature": signature, + }, + loa_render_params.LoaRenderParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=AsyncBinaryAPIResponse, + ) + + +class LoaResourceWithRawResponse: + def __init__(self, loa: LoaResource) -> None: + self._loa = loa + + self.update = to_raw_response_wrapper( + loa.update, + ) + self.render = to_custom_raw_response_wrapper( + loa.render, + BinaryAPIResponse, + ) + + +class AsyncLoaResourceWithRawResponse: + def __init__(self, loa: AsyncLoaResource) -> None: + self._loa = loa + + self.update = async_to_raw_response_wrapper( + loa.update, + ) + self.render = async_to_custom_raw_response_wrapper( + loa.render, + AsyncBinaryAPIResponse, + ) + + +class LoaResourceWithStreamingResponse: + def __init__(self, loa: LoaResource) -> None: + self._loa = loa + + self.update = to_streamed_response_wrapper( + loa.update, + ) + self.render = to_custom_streamed_response_wrapper( + loa.render, + StreamedBinaryAPIResponse, + ) + + +class AsyncLoaResourceWithStreamingResponse: + def __init__(self, loa: AsyncLoaResource) -> None: + self._loa = loa + + self.update = async_to_streamed_response_wrapper( + loa.update, + ) + self.render = async_to_custom_streamed_response_wrapper( + loa.render, + AsyncStreamedBinaryAPIResponse, + ) diff --git a/src/telnyx/resources/enterprises/reputation/numbers.py b/src/telnyx/resources/enterprises/reputation/numbers.py index 242cc668..472e0206 100644 --- a/src/telnyx/resources/enterprises/reputation/numbers.py +++ b/src/telnyx/resources/enterprises/reputation/numbers.py @@ -16,18 +16,22 @@ ) from ....pagination import SyncDefaultFlatPagination, AsyncDefaultFlatPagination from ...._base_client import AsyncPaginator, make_request_options -from ....types.enterprises.reputation import number_list_params, number_retrieve_params, number_associate_params +from ....types.enterprises.reputation import ( + number_list_params, + number_refresh_params, + number_retrieve_params, + number_associate_params, +) +from ....types.enterprises.reputation.number_list_response import NumberListResponse +from ....types.enterprises.reputation.number_refresh_response import NumberRefreshResponse from ....types.enterprises.reputation.number_retrieve_response import NumberRetrieveResponse from ....types.enterprises.reputation.number_associate_response import NumberAssociateResponse -from ....types.shared.reputation_phone_number_with_reputation_data import ReputationPhoneNumberWithReputationData __all__ = ["NumbersResource", "AsyncNumbersResource"] class NumbersResource(SyncAPIResource): - """ - Associate phone numbers with an enterprise for reputation monitoring and retrieve reputation scores - """ + """Phone-number reputation monitoring (spam-score lookup and tracking).""" @cached_property def with_raw_response(self) -> NumbersResourceWithRawResponse: @@ -61,29 +65,15 @@ def retrieve( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> NumberRetrieveResponse: - """ - Get detailed reputation data for a specific phone number associated with an - enterprise. - - **Query Parameters:** + """Retrieve one registered number with its latest reputation snapshot. - - `fresh` (default: `false`): When `true`, fetches fresh reputation data (incurs - API cost). When `false`, returns cached data. If no cached data exists, fresh - data is automatically fetched. - - **Returns:** - - - `spam_risk`: Overall spam risk level (`low`, `medium`, `high`) - - `spam_category`: Spam category classification - - `maturity_score`: Maturity metric (0–100) - - `connection_score`: Connection quality metric (0–100) - - `engagement_score`: Engagement metric (0–100) - - `sentiment_score`: Sentiment metric (0–100) - - `last_refreshed_at`: Timestamp of last data refresh + The + `phone_number` path parameter is in E.164 format and must be URL-encoded (e.g. + `%2B19493253498`). Args: - fresh: When true, fetches fresh reputation data (incurs API cost). When false, returns - cached data. + fresh: When true, fetches fresh reputation data (incurs API cost). When false + (default), returns cached data. extra_headers: Send extra headers @@ -126,20 +116,18 @@ def list( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> SyncDefaultFlatPagination[ReputationPhoneNumberWithReputationData]: + ) -> SyncDefaultFlatPagination[NumberListResponse]: """ - List all phone numbers associated with an enterprise for Number Reputation - monitoring. - - Returns phone numbers with their cached reputation data (if available). Supports - pagination and filtering by phone number. + Paginated list of phone numbers registered for reputation monitoring under this + enterprise. The response includes the latest reputation snapshot per number + where one has been collected. Args: - page_number: Page number (1-indexed) + page_number: 1-based page number. Out-of-range values return an empty page with correct meta. - page_size: Number of items per page + page_size: Items per page. Default 10. Maximum 250; values above are clamped to 250. - phone_number: Filter by specific phone number (E.164 format) + phone_number: Filter by specific phone number (E.164 format). extra_headers: Send extra headers @@ -153,7 +141,7 @@ def list( raise ValueError(f"Expected a non-empty value for `enterprise_id` but received {enterprise_id!r}") return self._get_api_list( path_template("/enterprises/{enterprise_id}/reputation/numbers", enterprise_id=enterprise_id), - page=SyncDefaultFlatPagination[ReputationPhoneNumberWithReputationData], + page=SyncDefaultFlatPagination[NumberListResponse], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -168,7 +156,7 @@ def list( number_list_params.NumberListParams, ), ), - model=ReputationPhoneNumberWithReputationData, + model=NumberListResponse, ) def associate( @@ -183,25 +171,20 @@ def associate( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> NumberAssociateResponse: - """ - Associate one or more phone numbers with an enterprise for Number Reputation - monitoring. - - **Validations:** + """Add up to 100 phone numbers to reputation monitoring on this enterprise. - - Phone numbers must be in E.164 format (e.g., `+16035551234`) - - Phone numbers must be in-service and belong to your account (verified via - Warehouse) - - Phone numbers must be US local numbers - - Phone numbers cannot already be associated with any enterprise + Each + must be in E.164 format (`+1NPANXXXXXX` for US/CA) and belong to your Telnyx + phone-number inventory. - **Note:** This operation is atomic — if any number fails validation, the entire - request fails. + **Prerequisite**: reputation must already be enabled on this enterprise (see + `POST .../reputation`). - **Maximum:** 100 phone numbers per request. + **Pricing:** This is a billable action. See https://telnyx.com/pricing/numbers + for current pricing. Args: - phone_numbers: List of phone numbers to associate for reputation monitoring (max 100) + phone_numbers: 1–100 phone numbers in E.164 format with a leading `+`. extra_headers: Send extra headers @@ -234,11 +217,10 @@ def disassociate( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: - """ - Remove a phone number from Number Reputation monitoring for an enterprise. + """Stop tracking the reputation of this phone number. - The number will no longer be tracked and reputation data will no longer be - refreshed. + The number itself remains in + your inventory; only the reputation registration is removed. Args: extra_headers: Send extra headers @@ -266,11 +248,54 @@ def disassociate( cast_to=NoneType, ) + def refresh( + self, + enterprise_id: str, + *, + phone_numbers: SequenceNotStr[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, + ) -> NumberRefreshResponse: + """Immediately refresh the stored reputation data for the listed numbers. + + This is + in addition to the periodic refresh determined by `check_frequency`. Up to 100 + numbers per call. The response carries the kicked-off jobs; the actual refresh + runs asynchronously. + + **Pricing:** Forcing a refresh performs live reputation lookups, which are + billable. See https://telnyx.com/pricing/numbers for current pricing. + + Args: + phone_numbers: Phone numbers to refresh reputation data for. 1–100 numbers per request, each in + E.164 format. Reputation refreshes are subject to per-enterprise rate limits. + + 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}/reputation/numbers/refresh", enterprise_id=enterprise_id), + body=maybe_transform({"phone_numbers": phone_numbers}, number_refresh_params.NumberRefreshParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NumberRefreshResponse, + ) + class AsyncNumbersResource(AsyncAPIResource): - """ - Associate phone numbers with an enterprise for reputation monitoring and retrieve reputation scores - """ + """Phone-number reputation monitoring (spam-score lookup and tracking).""" @cached_property def with_raw_response(self) -> AsyncNumbersResourceWithRawResponse: @@ -304,29 +329,15 @@ async def retrieve( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> NumberRetrieveResponse: - """ - Get detailed reputation data for a specific phone number associated with an - enterprise. - - **Query Parameters:** - - - `fresh` (default: `false`): When `true`, fetches fresh reputation data (incurs - API cost). When `false`, returns cached data. If no cached data exists, fresh - data is automatically fetched. + """Retrieve one registered number with its latest reputation snapshot. - **Returns:** - - - `spam_risk`: Overall spam risk level (`low`, `medium`, `high`) - - `spam_category`: Spam category classification - - `maturity_score`: Maturity metric (0–100) - - `connection_score`: Connection quality metric (0–100) - - `engagement_score`: Engagement metric (0–100) - - `sentiment_score`: Sentiment metric (0–100) - - `last_refreshed_at`: Timestamp of last data refresh + The + `phone_number` path parameter is in E.164 format and must be URL-encoded (e.g. + `%2B19493253498`). Args: - fresh: When true, fetches fresh reputation data (incurs API cost). When false, returns - cached data. + fresh: When true, fetches fresh reputation data (incurs API cost). When false + (default), returns cached data. extra_headers: Send extra headers @@ -369,22 +380,18 @@ def list( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> AsyncPaginator[ - ReputationPhoneNumberWithReputationData, AsyncDefaultFlatPagination[ReputationPhoneNumberWithReputationData] - ]: + ) -> AsyncPaginator[NumberListResponse, AsyncDefaultFlatPagination[NumberListResponse]]: """ - List all phone numbers associated with an enterprise for Number Reputation - monitoring. - - Returns phone numbers with their cached reputation data (if available). Supports - pagination and filtering by phone number. + Paginated list of phone numbers registered for reputation monitoring under this + enterprise. The response includes the latest reputation snapshot per number + where one has been collected. Args: - page_number: Page number (1-indexed) + page_number: 1-based page number. Out-of-range values return an empty page with correct meta. - page_size: Number of items per page + page_size: Items per page. Default 10. Maximum 250; values above are clamped to 250. - phone_number: Filter by specific phone number (E.164 format) + phone_number: Filter by specific phone number (E.164 format). extra_headers: Send extra headers @@ -398,7 +405,7 @@ def list( raise ValueError(f"Expected a non-empty value for `enterprise_id` but received {enterprise_id!r}") return self._get_api_list( path_template("/enterprises/{enterprise_id}/reputation/numbers", enterprise_id=enterprise_id), - page=AsyncDefaultFlatPagination[ReputationPhoneNumberWithReputationData], + page=AsyncDefaultFlatPagination[NumberListResponse], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -413,7 +420,7 @@ def list( number_list_params.NumberListParams, ), ), - model=ReputationPhoneNumberWithReputationData, + model=NumberListResponse, ) async def associate( @@ -428,25 +435,20 @@ async def associate( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> NumberAssociateResponse: - """ - Associate one or more phone numbers with an enterprise for Number Reputation - monitoring. + """Add up to 100 phone numbers to reputation monitoring on this enterprise. - **Validations:** + Each + must be in E.164 format (`+1NPANXXXXXX` for US/CA) and belong to your Telnyx + phone-number inventory. - - Phone numbers must be in E.164 format (e.g., `+16035551234`) - - Phone numbers must be in-service and belong to your account (verified via - Warehouse) - - Phone numbers must be US local numbers - - Phone numbers cannot already be associated with any enterprise + **Prerequisite**: reputation must already be enabled on this enterprise (see + `POST .../reputation`). - **Note:** This operation is atomic — if any number fails validation, the entire - request fails. - - **Maximum:** 100 phone numbers per request. + **Pricing:** This is a billable action. See https://telnyx.com/pricing/numbers + for current pricing. Args: - phone_numbers: List of phone numbers to associate for reputation monitoring (max 100) + phone_numbers: 1–100 phone numbers in E.164 format with a leading `+`. extra_headers: Send extra headers @@ -481,11 +483,10 @@ async def disassociate( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: - """ - Remove a phone number from Number Reputation monitoring for an enterprise. + """Stop tracking the reputation of this phone number. - The number will no longer be tracked and reputation data will no longer be - refreshed. + The number itself remains in + your inventory; only the reputation registration is removed. Args: extra_headers: Send extra headers @@ -513,6 +514,53 @@ async def disassociate( cast_to=NoneType, ) + async def refresh( + self, + enterprise_id: str, + *, + phone_numbers: SequenceNotStr[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, + ) -> NumberRefreshResponse: + """Immediately refresh the stored reputation data for the listed numbers. + + This is + in addition to the periodic refresh determined by `check_frequency`. Up to 100 + numbers per call. The response carries the kicked-off jobs; the actual refresh + runs asynchronously. + + **Pricing:** Forcing a refresh performs live reputation lookups, which are + billable. See https://telnyx.com/pricing/numbers for current pricing. + + Args: + phone_numbers: Phone numbers to refresh reputation data for. 1–100 numbers per request, each in + E.164 format. Reputation refreshes are subject to per-enterprise rate limits. + + 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}/reputation/numbers/refresh", enterprise_id=enterprise_id), + body=await async_maybe_transform( + {"phone_numbers": phone_numbers}, number_refresh_params.NumberRefreshParams + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NumberRefreshResponse, + ) + class NumbersResourceWithRawResponse: def __init__(self, numbers: NumbersResource) -> None: @@ -530,6 +578,9 @@ def __init__(self, numbers: NumbersResource) -> None: self.disassociate = to_raw_response_wrapper( numbers.disassociate, ) + self.refresh = to_raw_response_wrapper( + numbers.refresh, + ) class AsyncNumbersResourceWithRawResponse: @@ -548,6 +599,9 @@ def __init__(self, numbers: AsyncNumbersResource) -> None: self.disassociate = async_to_raw_response_wrapper( numbers.disassociate, ) + self.refresh = async_to_raw_response_wrapper( + numbers.refresh, + ) class NumbersResourceWithStreamingResponse: @@ -566,6 +620,9 @@ def __init__(self, numbers: NumbersResource) -> None: self.disassociate = to_streamed_response_wrapper( numbers.disassociate, ) + self.refresh = to_streamed_response_wrapper( + numbers.refresh, + ) class AsyncNumbersResourceWithStreamingResponse: @@ -584,3 +641,6 @@ def __init__(self, numbers: AsyncNumbersResource) -> None: self.disassociate = async_to_streamed_response_wrapper( numbers.disassociate, ) + self.refresh = async_to_streamed_response_wrapper( + numbers.refresh, + ) diff --git a/src/telnyx/resources/enterprises/reputation/reputation.py b/src/telnyx/resources/enterprises/reputation/reputation.py index 615635e4..de601c43 100644 --- a/src/telnyx/resources/enterprises/reputation/reputation.py +++ b/src/telnyx/resources/enterprises/reputation/reputation.py @@ -6,6 +6,14 @@ import httpx +from .loa import ( + LoaResource, + AsyncLoaResource, + LoaResourceWithRawResponse, + AsyncLoaResourceWithRawResponse, + LoaResourceWithStreamingResponse, + AsyncLoaResourceWithStreamingResponse, +) from .numbers import ( NumbersResource, AsyncNumbersResource, @@ -34,17 +42,18 @@ class ReputationResource(SyncAPIResource): - """ - Manage Number Reputation enrollment and check frequency settings for an enterprise - """ + """Phone-number reputation monitoring (spam-score lookup and tracking).""" @cached_property def numbers(self) -> NumbersResource: - """ - Associate phone numbers with an enterprise for reputation monitoring and retrieve reputation scores - """ + """Phone-number reputation monitoring (spam-score lookup and tracking).""" return NumbersResource(self._client) + @cached_property + def loa(self) -> LoaResource: + """Phone-number reputation monitoring (spam-score lookup and tracking).""" + return LoaResource(self._client) + @cached_property def with_raw_response(self) -> ReputationResourceWithRawResponse: """ @@ -76,12 +85,12 @@ def retrieve( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ReputationRetrieveResponse: """ - Retrieve the current Number Reputation settings for an enterprise. - - Returns the enrollment status (`pending`, `approved`, `rejected`, `deleted`), - check frequency, and any rejection reasons. + Phone Number Reputation tracks how your outbound caller-IDs are perceived (spam + risk, engagement, etc.) across the call-screening ecosystem. This endpoint reads + the enterprise-level settings: whether the product is enabled, the refresh + cadence, and the stored Letter of Authorization document id. - Returns `404` if reputation has not been enabled for this enterprise. + Returns `404` if reputation has never been enabled for this enterprise. Args: extra_headers: Send extra headers @@ -113,16 +122,11 @@ def disable( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: - """ - Disable Number Reputation for an enterprise. - - This will: - - - Delete the reputation settings record - - Log the deletion for audit purposes - - Stop all future automated reputation checks + """Disable Phone Number Reputation. - **Note:** Can only be performed on `approved` reputation settings. + All registered numbers are de-registered as a + cascade. The enterprise itself is unaffected. Returns `204` on success, `404` if + reputation is not enabled for this enterprise. Args: extra_headers: Send extra headers @@ -157,38 +161,33 @@ def enable( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ReputationEnableResponse: - """ - Enable Number Reputation service for an enterprise. - - **Requirements:** + """Activate Phone Number Reputation for the given enterprise. - - Signed LOA (Letter of Authorization) document ID - - Reputation check frequency (defaults to `business_daily`) - - Number Reputation Terms of Service must be accepted + Requires an uploaded + Letter of Authorization document (the `loa_document_id` references the Telnyx + Documents API) and a refresh-frequency selection. After activation, individual + phone numbers can be registered via `POST .../reputation/numbers`. - **Flow:** + **Prerequisite**: the calling user must have agreed to the Phone Number + Reputation Terms of Service (`POST /terms_of_service/number_reputation/agree`). - 1. Registers the enterprise for reputation monitoring - 2. Creates reputation settings with `pending` status - 3. Awaits admin approval before monitoring begins + Failure modes: - **Resubmission After Rejection:** If a previously rejected record exists, this - endpoint will delete it and create a new `pending` record. + - `403` — Phone Number Reputation Terms of Service not accepted. + - `404` — enterprise does not exist or does not belong to your account. + - `400` — reputation already enabled for this enterprise. + - `422` — `loa_document_id` missing or `check_frequency` invalid. - **Available Frequencies:** - - - `business_daily` — Monday–Friday - - `daily` — Every day - - `weekly` — Once per week - - `biweekly` — Once every two weeks - - `monthly` — Once per month - - `never` — Manual refresh only + **Pricing:** This is a billable action. See https://telnyx.com/pricing/numbers + for current pricing. Args: - loa_document_id: ID of the signed Letter of Authorization (LOA) document uploaded to the document - service + loa_document_id: Id of the signed Letter of Authorization document, returned by the Telnyx + Documents API after upload (upload via `POST /v2/documents`; see + https://developers.telnyx.com/api/documents). - check_frequency: Frequency for automatically refreshing reputation data + check_frequency: How often Telnyx refreshes the stored reputation data for this enterprise's + registered numbers. extra_headers: Send extra headers @@ -228,22 +227,16 @@ def update_frequency( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ReputationUpdateFrequencyResponse: """ - Update how often reputation data is automatically refreshed. - - **Note:** The enterprise must have `approved` reputation settings. Updating - frequency on `pending` or `rejected` settings will return an error. - - **Available Frequencies:** + Update how often Telnyx refreshes the reputation data for this enterprise's + registered numbers. The new frequency takes effect on the next scheduled + refresh. - - `business_daily` — Monday–Friday - - `daily` — Every day including weekends - - `weekly` — Once per week - - `biweekly` — Once every two weeks - - `monthly` — Once per month - - `never` — Manual refresh only (no automatic checks) + The enterprise's reputation must be in `approved` status. A request made while + the status is `pending` is rejected with `400 Bad Request`. Args: - check_frequency: New frequency for refreshing reputation data + check_frequency: How often Telnyx refreshes the stored reputation data for this enterprise's + registered numbers. extra_headers: Send extra headers @@ -268,17 +261,18 @@ def update_frequency( class AsyncReputationResource(AsyncAPIResource): - """ - Manage Number Reputation enrollment and check frequency settings for an enterprise - """ + """Phone-number reputation monitoring (spam-score lookup and tracking).""" @cached_property def numbers(self) -> AsyncNumbersResource: - """ - Associate phone numbers with an enterprise for reputation monitoring and retrieve reputation scores - """ + """Phone-number reputation monitoring (spam-score lookup and tracking).""" return AsyncNumbersResource(self._client) + @cached_property + def loa(self) -> AsyncLoaResource: + """Phone-number reputation monitoring (spam-score lookup and tracking).""" + return AsyncLoaResource(self._client) + @cached_property def with_raw_response(self) -> AsyncReputationResourceWithRawResponse: """ @@ -310,12 +304,12 @@ async def retrieve( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ReputationRetrieveResponse: """ - Retrieve the current Number Reputation settings for an enterprise. - - Returns the enrollment status (`pending`, `approved`, `rejected`, `deleted`), - check frequency, and any rejection reasons. + Phone Number Reputation tracks how your outbound caller-IDs are perceived (spam + risk, engagement, etc.) across the call-screening ecosystem. This endpoint reads + the enterprise-level settings: whether the product is enabled, the refresh + cadence, and the stored Letter of Authorization document id. - Returns `404` if reputation has not been enabled for this enterprise. + Returns `404` if reputation has never been enabled for this enterprise. Args: extra_headers: Send extra headers @@ -347,16 +341,11 @@ async def disable( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: - """ - Disable Number Reputation for an enterprise. - - This will: - - - Delete the reputation settings record - - Log the deletion for audit purposes - - Stop all future automated reputation checks + """Disable Phone Number Reputation. - **Note:** Can only be performed on `approved` reputation settings. + All registered numbers are de-registered as a + cascade. The enterprise itself is unaffected. Returns `204` on success, `404` if + reputation is not enabled for this enterprise. Args: extra_headers: Send extra headers @@ -391,38 +380,33 @@ async def enable( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ReputationEnableResponse: - """ - Enable Number Reputation service for an enterprise. - - **Requirements:** - - - Signed LOA (Letter of Authorization) document ID - - Reputation check frequency (defaults to `business_daily`) - - Number Reputation Terms of Service must be accepted + """Activate Phone Number Reputation for the given enterprise. - **Flow:** + Requires an uploaded + Letter of Authorization document (the `loa_document_id` references the Telnyx + Documents API) and a refresh-frequency selection. After activation, individual + phone numbers can be registered via `POST .../reputation/numbers`. - 1. Registers the enterprise for reputation monitoring - 2. Creates reputation settings with `pending` status - 3. Awaits admin approval before monitoring begins + **Prerequisite**: the calling user must have agreed to the Phone Number + Reputation Terms of Service (`POST /terms_of_service/number_reputation/agree`). - **Resubmission After Rejection:** If a previously rejected record exists, this - endpoint will delete it and create a new `pending` record. + Failure modes: - **Available Frequencies:** + - `403` — Phone Number Reputation Terms of Service not accepted. + - `404` — enterprise does not exist or does not belong to your account. + - `400` — reputation already enabled for this enterprise. + - `422` — `loa_document_id` missing or `check_frequency` invalid. - - `business_daily` — Monday–Friday - - `daily` — Every day - - `weekly` — Once per week - - `biweekly` — Once every two weeks - - `monthly` — Once per month - - `never` — Manual refresh only + **Pricing:** This is a billable action. See https://telnyx.com/pricing/numbers + for current pricing. Args: - loa_document_id: ID of the signed Letter of Authorization (LOA) document uploaded to the document - service + loa_document_id: Id of the signed Letter of Authorization document, returned by the Telnyx + Documents API after upload (upload via `POST /v2/documents`; see + https://developers.telnyx.com/api/documents). - check_frequency: Frequency for automatically refreshing reputation data + check_frequency: How often Telnyx refreshes the stored reputation data for this enterprise's + registered numbers. extra_headers: Send extra headers @@ -462,22 +446,16 @@ async def update_frequency( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ReputationUpdateFrequencyResponse: """ - Update how often reputation data is automatically refreshed. + Update how often Telnyx refreshes the reputation data for this enterprise's + registered numbers. The new frequency takes effect on the next scheduled + refresh. - **Note:** The enterprise must have `approved` reputation settings. Updating - frequency on `pending` or `rejected` settings will return an error. - - **Available Frequencies:** - - - `business_daily` — Monday–Friday - - `daily` — Every day including weekends - - `weekly` — Once per week - - `biweekly` — Once every two weeks - - `monthly` — Once per month - - `never` — Manual refresh only (no automatic checks) + The enterprise's reputation must be in `approved` status. A request made while + the status is `pending` is rejected with `400 Bad Request`. Args: - check_frequency: New frequency for refreshing reputation data + check_frequency: How often Telnyx refreshes the stored reputation data for this enterprise's + registered numbers. extra_headers: Send extra headers @@ -520,11 +498,14 @@ def __init__(self, reputation: ReputationResource) -> None: @cached_property def numbers(self) -> NumbersResourceWithRawResponse: - """ - Associate phone numbers with an enterprise for reputation monitoring and retrieve reputation scores - """ + """Phone-number reputation monitoring (spam-score lookup and tracking).""" return NumbersResourceWithRawResponse(self._reputation.numbers) + @cached_property + def loa(self) -> LoaResourceWithRawResponse: + """Phone-number reputation monitoring (spam-score lookup and tracking).""" + return LoaResourceWithRawResponse(self._reputation.loa) + class AsyncReputationResourceWithRawResponse: def __init__(self, reputation: AsyncReputationResource) -> None: @@ -545,11 +526,14 @@ def __init__(self, reputation: AsyncReputationResource) -> None: @cached_property def numbers(self) -> AsyncNumbersResourceWithRawResponse: - """ - Associate phone numbers with an enterprise for reputation monitoring and retrieve reputation scores - """ + """Phone-number reputation monitoring (spam-score lookup and tracking).""" return AsyncNumbersResourceWithRawResponse(self._reputation.numbers) + @cached_property + def loa(self) -> AsyncLoaResourceWithRawResponse: + """Phone-number reputation monitoring (spam-score lookup and tracking).""" + return AsyncLoaResourceWithRawResponse(self._reputation.loa) + class ReputationResourceWithStreamingResponse: def __init__(self, reputation: ReputationResource) -> None: @@ -570,11 +554,14 @@ def __init__(self, reputation: ReputationResource) -> None: @cached_property def numbers(self) -> NumbersResourceWithStreamingResponse: - """ - Associate phone numbers with an enterprise for reputation monitoring and retrieve reputation scores - """ + """Phone-number reputation monitoring (spam-score lookup and tracking).""" return NumbersResourceWithStreamingResponse(self._reputation.numbers) + @cached_property + def loa(self) -> LoaResourceWithStreamingResponse: + """Phone-number reputation monitoring (spam-score lookup and tracking).""" + return LoaResourceWithStreamingResponse(self._reputation.loa) + class AsyncReputationResourceWithStreamingResponse: def __init__(self, reputation: AsyncReputationResource) -> None: @@ -595,7 +582,10 @@ def __init__(self, reputation: AsyncReputationResource) -> None: @cached_property def numbers(self) -> AsyncNumbersResourceWithStreamingResponse: - """ - Associate phone numbers with an enterprise for reputation monitoring and retrieve reputation scores - """ + """Phone-number reputation monitoring (spam-score lookup and tracking).""" return AsyncNumbersResourceWithStreamingResponse(self._reputation.numbers) + + @cached_property + def loa(self) -> AsyncLoaResourceWithStreamingResponse: + """Phone-number reputation monitoring (spam-score lookup and tracking).""" + return AsyncLoaResourceWithStreamingResponse(self._reputation.loa) diff --git a/src/telnyx/resources/infringement_claims.py b/src/telnyx/resources/infringement_claims.py new file mode 100644 index 00000000..3d4a93cd --- /dev/null +++ b/src/telnyx/resources/infringement_claims.py @@ -0,0 +1,320 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Iterable + +import httpx + +from ..types import infringement_claim_contest_params +from .._types import Body, Omit, Query, Headers, NotGiven, omit, 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.infringement_claim_contest_response import InfringementClaimContestResponse +from ..types.infringement_claim_retrieve_response import InfringementClaimRetrieveResponse + +__all__ = ["InfringementClaimsResource", "AsyncInfringementClaimsResource"] + + +class InfringementClaimsResource(SyncAPIResource): + """Trademark or impersonation claims filed against your DIR. + + Customers may contest a claim with supporting evidence. + """ + + @cached_property + def with_raw_response(self) -> InfringementClaimsResourceWithRawResponse: + """ + 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 InfringementClaimsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> InfringementClaimsResourceWithStreamingResponse: + """ + 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 InfringementClaimsResourceWithStreamingResponse(self) + + def retrieve( + self, + claim_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, + ) -> InfringementClaimRetrieveResponse: + """Retrieve a single claim by id. + + Returns `404` if the claim does not exist or is + not against a DIR you own. + + 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 claim_id: + raise ValueError(f"Expected a non-empty value for `claim_id` but received {claim_id!r}") + return self._get( + path_template("/infringement_claims/{claim_id}", claim_id=claim_id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=InfringementClaimRetrieveResponse, + ) + + def contest( + self, + claim_id: str, + *, + contest_notes: str, + documents: Iterable[infringement_claim_contest_params.Document] | 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, + ) -> InfringementClaimContestResponse: + """Submit a written response and supporting documents disputing the claim. + + The + first call moves the claim from `pending` to `contested`; subsequent calls + append supplementary evidence without changing status. The `documents[]` you + attach are aggregated across rounds in the claim's `contest_documents` field. + + Only `pending` and `contested` claims accept new evidence. A `resolved` claim + returns `400`. + + Failure modes: + + - `400` — the claim is `resolved` (terminal); cannot be contested further. + - `404` — the claim does not exist or is not against a DIR you own. + - `422` — `contest_notes` is too short (< 10 chars), too long (> 2000 chars), + `documents` is > 20 entries, or a `document_id` is duplicated within the same + submission. + + Args: + contest_notes: Customer's response to the claim. 10–2000 characters. + + documents: 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. + + 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 claim_id: + raise ValueError(f"Expected a non-empty value for `claim_id` but received {claim_id!r}") + return self._post( + path_template("/infringement_claims/{claim_id}/contest", claim_id=claim_id), + body=maybe_transform( + { + "contest_notes": contest_notes, + "documents": documents, + }, + infringement_claim_contest_params.InfringementClaimContestParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=InfringementClaimContestResponse, + ) + + +class AsyncInfringementClaimsResource(AsyncAPIResource): + """Trademark or impersonation claims filed against your DIR. + + Customers may contest a claim with supporting evidence. + """ + + @cached_property + def with_raw_response(self) -> AsyncInfringementClaimsResourceWithRawResponse: + """ + 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 AsyncInfringementClaimsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncInfringementClaimsResourceWithStreamingResponse: + """ + 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 AsyncInfringementClaimsResourceWithStreamingResponse(self) + + async def retrieve( + self, + claim_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, + ) -> InfringementClaimRetrieveResponse: + """Retrieve a single claim by id. + + Returns `404` if the claim does not exist or is + not against a DIR you own. + + 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 claim_id: + raise ValueError(f"Expected a non-empty value for `claim_id` but received {claim_id!r}") + return await self._get( + path_template("/infringement_claims/{claim_id}", claim_id=claim_id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=InfringementClaimRetrieveResponse, + ) + + async def contest( + self, + claim_id: str, + *, + contest_notes: str, + documents: Iterable[infringement_claim_contest_params.Document] | 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, + ) -> InfringementClaimContestResponse: + """Submit a written response and supporting documents disputing the claim. + + The + first call moves the claim from `pending` to `contested`; subsequent calls + append supplementary evidence without changing status. The `documents[]` you + attach are aggregated across rounds in the claim's `contest_documents` field. + + Only `pending` and `contested` claims accept new evidence. A `resolved` claim + returns `400`. + + Failure modes: + + - `400` — the claim is `resolved` (terminal); cannot be contested further. + - `404` — the claim does not exist or is not against a DIR you own. + - `422` — `contest_notes` is too short (< 10 chars), too long (> 2000 chars), + `documents` is > 20 entries, or a `document_id` is duplicated within the same + submission. + + Args: + contest_notes: Customer's response to the claim. 10–2000 characters. + + documents: 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. + + 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 claim_id: + raise ValueError(f"Expected a non-empty value for `claim_id` but received {claim_id!r}") + return await self._post( + path_template("/infringement_claims/{claim_id}/contest", claim_id=claim_id), + body=await async_maybe_transform( + { + "contest_notes": contest_notes, + "documents": documents, + }, + infringement_claim_contest_params.InfringementClaimContestParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=InfringementClaimContestResponse, + ) + + +class InfringementClaimsResourceWithRawResponse: + def __init__(self, infringement_claims: InfringementClaimsResource) -> None: + self._infringement_claims = infringement_claims + + self.retrieve = to_raw_response_wrapper( + infringement_claims.retrieve, + ) + self.contest = to_raw_response_wrapper( + infringement_claims.contest, + ) + + +class AsyncInfringementClaimsResourceWithRawResponse: + def __init__(self, infringement_claims: AsyncInfringementClaimsResource) -> None: + self._infringement_claims = infringement_claims + + self.retrieve = async_to_raw_response_wrapper( + infringement_claims.retrieve, + ) + self.contest = async_to_raw_response_wrapper( + infringement_claims.contest, + ) + + +class InfringementClaimsResourceWithStreamingResponse: + def __init__(self, infringement_claims: InfringementClaimsResource) -> None: + self._infringement_claims = infringement_claims + + self.retrieve = to_streamed_response_wrapper( + infringement_claims.retrieve, + ) + self.contest = to_streamed_response_wrapper( + infringement_claims.contest, + ) + + +class AsyncInfringementClaimsResourceWithStreamingResponse: + def __init__(self, infringement_claims: AsyncInfringementClaimsResource) -> None: + self._infringement_claims = infringement_claims + + self.retrieve = async_to_streamed_response_wrapper( + infringement_claims.retrieve, + ) + self.contest = async_to_streamed_response_wrapper( + infringement_claims.contest, + ) diff --git a/src/telnyx/resources/public_internet_gateways.py b/src/telnyx/resources/public_internet_gateways.py index 7e7919b1..8e8f9c52 100644 --- a/src/telnyx/resources/public_internet_gateways.py +++ b/src/telnyx/resources/public_internet_gateways.py @@ -17,7 +17,7 @@ ) from ..pagination import SyncDefaultFlatPagination, AsyncDefaultFlatPagination from .._base_client import AsyncPaginator, make_request_options -from ..types.public_internet_gateway_read import PublicInternetGatewayRead +from ..types.public_internet_gateway_list_response import PublicInternetGatewayListResponse from ..types.public_internet_gateway_create_response import PublicInternetGatewayCreateResponse from ..types.public_internet_gateway_delete_response import PublicInternetGatewayDeleteResponse from ..types.public_internet_gateway_retrieve_response import PublicInternetGatewayRetrieveResponse @@ -139,7 +139,7 @@ def list( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> SyncDefaultFlatPagination[PublicInternetGatewayRead]: + ) -> SyncDefaultFlatPagination[PublicInternetGatewayListResponse]: """ List all Public Internet Gateways. @@ -156,7 +156,7 @@ def list( """ return self._get_api_list( "/public_internet_gateways", - page=SyncDefaultFlatPagination[PublicInternetGatewayRead], + page=SyncDefaultFlatPagination[PublicInternetGatewayListResponse], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -171,7 +171,7 @@ def list( public_internet_gateway_list_params.PublicInternetGatewayListParams, ), ), - model=PublicInternetGatewayRead, + model=PublicInternetGatewayListResponse, ) def delete( @@ -322,7 +322,9 @@ def list( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> AsyncPaginator[PublicInternetGatewayRead, AsyncDefaultFlatPagination[PublicInternetGatewayRead]]: + ) -> AsyncPaginator[ + PublicInternetGatewayListResponse, AsyncDefaultFlatPagination[PublicInternetGatewayListResponse] + ]: """ List all Public Internet Gateways. @@ -339,7 +341,7 @@ def list( """ return self._get_api_list( "/public_internet_gateways", - page=AsyncDefaultFlatPagination[PublicInternetGatewayRead], + page=AsyncDefaultFlatPagination[PublicInternetGatewayListResponse], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -354,7 +356,7 @@ def list( public_internet_gateway_list_params.PublicInternetGatewayListParams, ), ), - model=PublicInternetGatewayRead, + model=PublicInternetGatewayListResponse, ) async def delete( diff --git a/src/telnyx/resources/reputation/numbers.py b/src/telnyx/resources/reputation/numbers.py index 6920ac29..e58ec23d 100644 --- a/src/telnyx/resources/reputation/numbers.py +++ b/src/telnyx/resources/reputation/numbers.py @@ -17,16 +17,14 @@ from ...pagination import SyncDefaultFlatPagination, AsyncDefaultFlatPagination from ..._base_client import AsyncPaginator, make_request_options from ...types.reputation import number_list_params, number_retrieve_params +from ...types.reputation.number_list_response import NumberListResponse from ...types.reputation.number_retrieve_response import NumberRetrieveResponse -from ...types.shared.reputation_phone_number_with_reputation_data import ReputationPhoneNumberWithReputationData __all__ = ["NumbersResource", "AsyncNumbersResource"] class NumbersResource(SyncAPIResource): - """ - Associate phone numbers with an enterprise for reputation monitoring and retrieve reputation scores - """ + """Phone-number reputation monitoring (spam-score lookup and tracking).""" @cached_property def with_raw_response(self) -> NumbersResourceWithRawResponse: @@ -60,14 +58,12 @@ def retrieve( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> NumberRetrieveResponse: """ - Get reputation data for a specific phone number without requiring an - `enterprise_id`. - - Same response as the enterprise-scoped endpoint. Uses cached data by default. + Convenience alias for + `GET /v2/enterprises/{enterprise_id}/reputation/numbers/{phone_number}`. Args: - fresh: When true, fetches fresh reputation data (incurs API cost). When false, returns - cached data. + fresh: When true, fetches fresh reputation data (incurs API cost). When false + (default), returns cached data. extra_headers: Send extra headers @@ -103,21 +99,18 @@ def list( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> SyncDefaultFlatPagination[ReputationPhoneNumberWithReputationData]: - """List all phone numbers enrolled in Number Reputation monitoring for your - account. - - This is a simplified endpoint that does not require an `enterprise_id` - — it returns numbers across all your enterprises. - - Supports pagination and filtering by phone number. + ) -> SyncDefaultFlatPagination[NumberListResponse]: + """ + Convenience alias for `GET /v2/enterprises/{enterprise_id}/reputation/numbers` + that returns numbers across every enterprise you own. Useful when you don't want + to look up the enterprise id first. Args: - page_number: Page number (1-indexed) + page_number: 1-based page number. Out-of-range values return an empty page with correct meta. - page_size: Number of items per page + page_size: Items per page. Maximum 250; values above are clamped to 250. - phone_number: Filter by specific phone number (E.164 format) + phone_number: Filter by specific phone number (E.164 format). extra_headers: Send extra headers @@ -129,7 +122,7 @@ def list( """ return self._get_api_list( "/reputation/numbers", - page=SyncDefaultFlatPagination[ReputationPhoneNumberWithReputationData], + page=SyncDefaultFlatPagination[NumberListResponse], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -144,7 +137,7 @@ def list( number_list_params.NumberListParams, ), ), - model=ReputationPhoneNumberWithReputationData, + model=NumberListResponse, ) def delete( @@ -159,8 +152,8 @@ def delete( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ - Remove a phone number from Number Reputation monitoring without requiring an - `enterprise_id`. + Convenience alias for + `DELETE /v2/enterprises/{enterprise_id}/reputation/numbers/{phone_number}`. Args: extra_headers: Send extra headers @@ -184,9 +177,7 @@ def delete( class AsyncNumbersResource(AsyncAPIResource): - """ - Associate phone numbers with an enterprise for reputation monitoring and retrieve reputation scores - """ + """Phone-number reputation monitoring (spam-score lookup and tracking).""" @cached_property def with_raw_response(self) -> AsyncNumbersResourceWithRawResponse: @@ -220,14 +211,12 @@ async def retrieve( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> NumberRetrieveResponse: """ - Get reputation data for a specific phone number without requiring an - `enterprise_id`. - - Same response as the enterprise-scoped endpoint. Uses cached data by default. + Convenience alias for + `GET /v2/enterprises/{enterprise_id}/reputation/numbers/{phone_number}`. Args: - fresh: When true, fetches fresh reputation data (incurs API cost). When false, returns - cached data. + fresh: When true, fetches fresh reputation data (incurs API cost). When false + (default), returns cached data. extra_headers: Send extra headers @@ -263,23 +252,18 @@ def list( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> AsyncPaginator[ - ReputationPhoneNumberWithReputationData, AsyncDefaultFlatPagination[ReputationPhoneNumberWithReputationData] - ]: - """List all phone numbers enrolled in Number Reputation monitoring for your - account. - - This is a simplified endpoint that does not require an `enterprise_id` - — it returns numbers across all your enterprises. - - Supports pagination and filtering by phone number. + ) -> AsyncPaginator[NumberListResponse, AsyncDefaultFlatPagination[NumberListResponse]]: + """ + Convenience alias for `GET /v2/enterprises/{enterprise_id}/reputation/numbers` + that returns numbers across every enterprise you own. Useful when you don't want + to look up the enterprise id first. Args: - page_number: Page number (1-indexed) + page_number: 1-based page number. Out-of-range values return an empty page with correct meta. - page_size: Number of items per page + page_size: Items per page. Maximum 250; values above are clamped to 250. - phone_number: Filter by specific phone number (E.164 format) + phone_number: Filter by specific phone number (E.164 format). extra_headers: Send extra headers @@ -291,7 +275,7 @@ def list( """ return self._get_api_list( "/reputation/numbers", - page=AsyncDefaultFlatPagination[ReputationPhoneNumberWithReputationData], + page=AsyncDefaultFlatPagination[NumberListResponse], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -306,7 +290,7 @@ def list( number_list_params.NumberListParams, ), ), - model=ReputationPhoneNumberWithReputationData, + model=NumberListResponse, ) async def delete( @@ -321,8 +305,8 @@ async def delete( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> None: """ - Remove a phone number from Number Reputation monitoring without requiring an - `enterprise_id`. + Convenience alias for + `DELETE /v2/enterprises/{enterprise_id}/reputation/numbers/{phone_number}`. Args: extra_headers: Send extra headers diff --git a/src/telnyx/resources/reputation/reputation.py b/src/telnyx/resources/reputation/reputation.py index 5cf57070..5c7bfd84 100644 --- a/src/telnyx/resources/reputation/reputation.py +++ b/src/telnyx/resources/reputation/reputation.py @@ -19,9 +19,7 @@ class ReputationResource(SyncAPIResource): @cached_property def numbers(self) -> NumbersResource: - """ - Associate phone numbers with an enterprise for reputation monitoring and retrieve reputation scores - """ + """Phone-number reputation monitoring (spam-score lookup and tracking).""" return NumbersResource(self._client) @cached_property @@ -47,9 +45,7 @@ def with_streaming_response(self) -> ReputationResourceWithStreamingResponse: class AsyncReputationResource(AsyncAPIResource): @cached_property def numbers(self) -> AsyncNumbersResource: - """ - Associate phone numbers with an enterprise for reputation monitoring and retrieve reputation scores - """ + """Phone-number reputation monitoring (spam-score lookup and tracking).""" return AsyncNumbersResource(self._client) @cached_property @@ -78,9 +74,7 @@ def __init__(self, reputation: ReputationResource) -> None: @cached_property def numbers(self) -> NumbersResourceWithRawResponse: - """ - Associate phone numbers with an enterprise for reputation monitoring and retrieve reputation scores - """ + """Phone-number reputation monitoring (spam-score lookup and tracking).""" return NumbersResourceWithRawResponse(self._reputation.numbers) @@ -90,9 +84,7 @@ def __init__(self, reputation: AsyncReputationResource) -> None: @cached_property def numbers(self) -> AsyncNumbersResourceWithRawResponse: - """ - Associate phone numbers with an enterprise for reputation monitoring and retrieve reputation scores - """ + """Phone-number reputation monitoring (spam-score lookup and tracking).""" return AsyncNumbersResourceWithRawResponse(self._reputation.numbers) @@ -102,9 +94,7 @@ def __init__(self, reputation: ReputationResource) -> None: @cached_property def numbers(self) -> NumbersResourceWithStreamingResponse: - """ - Associate phone numbers with an enterprise for reputation monitoring and retrieve reputation scores - """ + """Phone-number reputation monitoring (spam-score lookup and tracking).""" return NumbersResourceWithStreamingResponse(self._reputation.numbers) @@ -114,7 +104,5 @@ def __init__(self, reputation: AsyncReputationResource) -> None: @cached_property def numbers(self) -> AsyncNumbersResourceWithStreamingResponse: - """ - Associate phone numbers with an enterprise for reputation monitoring and retrieve reputation scores - """ + """Phone-number reputation monitoring (spam-score lookup and tracking).""" return AsyncNumbersResourceWithStreamingResponse(self._reputation.numbers) diff --git a/src/telnyx/resources/terms_of_service/__init__.py b/src/telnyx/resources/terms_of_service/__init__.py index 3782003e..d1e8cd99 100644 --- a/src/telnyx/resources/terms_of_service/__init__.py +++ b/src/telnyx/resources/terms_of_service/__init__.py @@ -1,5 +1,21 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +from .agreements import ( + AgreementsResource, + AsyncAgreementsResource, + AgreementsResourceWithRawResponse, + AsyncAgreementsResourceWithRawResponse, + AgreementsResourceWithStreamingResponse, + AsyncAgreementsResourceWithStreamingResponse, +) +from .branded_calling import ( + BrandedCallingResource, + AsyncBrandedCallingResource, + BrandedCallingResourceWithRawResponse, + AsyncBrandedCallingResourceWithRawResponse, + BrandedCallingResourceWithStreamingResponse, + AsyncBrandedCallingResourceWithStreamingResponse, +) from .terms_of_service import ( TermsOfServiceResource, AsyncTermsOfServiceResource, @@ -24,6 +40,18 @@ "AsyncNumberReputationResourceWithRawResponse", "NumberReputationResourceWithStreamingResponse", "AsyncNumberReputationResourceWithStreamingResponse", + "AgreementsResource", + "AsyncAgreementsResource", + "AgreementsResourceWithRawResponse", + "AsyncAgreementsResourceWithRawResponse", + "AgreementsResourceWithStreamingResponse", + "AsyncAgreementsResourceWithStreamingResponse", + "BrandedCallingResource", + "AsyncBrandedCallingResource", + "BrandedCallingResourceWithRawResponse", + "AsyncBrandedCallingResourceWithRawResponse", + "BrandedCallingResourceWithStreamingResponse", + "AsyncBrandedCallingResourceWithStreamingResponse", "TermsOfServiceResource", "AsyncTermsOfServiceResource", "TermsOfServiceResourceWithRawResponse", diff --git a/src/telnyx/resources/terms_of_service/agreements.py b/src/telnyx/resources/terms_of_service/agreements.py new file mode 100644 index 00000000..160f7065 --- /dev/null +++ b/src/telnyx/resources/terms_of_service/agreements.py @@ -0,0 +1,321 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal + +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.terms_of_service import agreement_list_params +from ...types.terms_of_service.agreement_list_response import AgreementListResponse +from ...types.terms_of_service.agreement_retrieve_response import AgreementRetrieveResponse + +__all__ = ["AgreementsResource", "AsyncAgreementsResource"] + + +class AgreementsResource(SyncAPIResource): + """ + Accept and review the Branded Calling and Phone Number Reputation terms of service. + """ + + @cached_property + def with_raw_response(self) -> AgreementsResourceWithRawResponse: + """ + 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 AgreementsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AgreementsResourceWithStreamingResponse: + """ + 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 AgreementsResourceWithStreamingResponse(self) + + def retrieve( + self, + agreement_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, + ) -> AgreementRetrieveResponse: + """Retrieve a single ToS agreement record. + + Returns `404` if the agreement does not + exist or does not belong to the authenticated user. + + 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 agreement_id: + raise ValueError(f"Expected a non-empty value for `agreement_id` but received {agreement_id!r}") + return self._get( + path_template("/terms_of_service/agreements/{agreement_id}", agreement_id=agreement_id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=AgreementRetrieveResponse, + ) + + def list( + self, + *, + page_number: int | Omit = omit, + page_size: int | Omit = omit, + product_type: Literal["branded_calling", "number_reputation"] | 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[AgreementListResponse]: + """Returns the Terms of Service agreements the authenticated user has on file. + + Each + entry records the version agreed to and when. Most users only have one agreement + per product, but if the ToS is updated and the user re-agrees a new entry is + added. + + Results are paginated with the standard `page[number]` / `page[size]` + parameters; the response uses the standard `{data, meta}` JSON:API envelope. + + By default this returns agreements for **all** products the user has agreed to + (including Branded Calling). Pass the `product_type` query parameter to scope + the result to a single product. + + 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. + + product_type: 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. + + 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( + "/terms_of_service/agreements", + page=SyncDefaultFlatPagination[AgreementListResponse], + 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, + "product_type": product_type, + }, + agreement_list_params.AgreementListParams, + ), + ), + model=AgreementListResponse, + ) + + +class AsyncAgreementsResource(AsyncAPIResource): + """ + Accept and review the Branded Calling and Phone Number Reputation terms of service. + """ + + @cached_property + def with_raw_response(self) -> AsyncAgreementsResourceWithRawResponse: + """ + 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 AsyncAgreementsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncAgreementsResourceWithStreamingResponse: + """ + 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 AsyncAgreementsResourceWithStreamingResponse(self) + + async def retrieve( + self, + agreement_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, + ) -> AgreementRetrieveResponse: + """Retrieve a single ToS agreement record. + + Returns `404` if the agreement does not + exist or does not belong to the authenticated user. + + 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 agreement_id: + raise ValueError(f"Expected a non-empty value for `agreement_id` but received {agreement_id!r}") + return await self._get( + path_template("/terms_of_service/agreements/{agreement_id}", agreement_id=agreement_id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=AgreementRetrieveResponse, + ) + + def list( + self, + *, + page_number: int | Omit = omit, + page_size: int | Omit = omit, + product_type: Literal["branded_calling", "number_reputation"] | 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[AgreementListResponse, AsyncDefaultFlatPagination[AgreementListResponse]]: + """Returns the Terms of Service agreements the authenticated user has on file. + + Each + entry records the version agreed to and when. Most users only have one agreement + per product, but if the ToS is updated and the user re-agrees a new entry is + added. + + Results are paginated with the standard `page[number]` / `page[size]` + parameters; the response uses the standard `{data, meta}` JSON:API envelope. + + By default this returns agreements for **all** products the user has agreed to + (including Branded Calling). Pass the `product_type` query parameter to scope + the result to a single product. + + 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. + + product_type: 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. + + 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( + "/terms_of_service/agreements", + page=AsyncDefaultFlatPagination[AgreementListResponse], + 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, + "product_type": product_type, + }, + agreement_list_params.AgreementListParams, + ), + ), + model=AgreementListResponse, + ) + + +class AgreementsResourceWithRawResponse: + def __init__(self, agreements: AgreementsResource) -> None: + self._agreements = agreements + + self.retrieve = to_raw_response_wrapper( + agreements.retrieve, + ) + self.list = to_raw_response_wrapper( + agreements.list, + ) + + +class AsyncAgreementsResourceWithRawResponse: + def __init__(self, agreements: AsyncAgreementsResource) -> None: + self._agreements = agreements + + self.retrieve = async_to_raw_response_wrapper( + agreements.retrieve, + ) + self.list = async_to_raw_response_wrapper( + agreements.list, + ) + + +class AgreementsResourceWithStreamingResponse: + def __init__(self, agreements: AgreementsResource) -> None: + self._agreements = agreements + + self.retrieve = to_streamed_response_wrapper( + agreements.retrieve, + ) + self.list = to_streamed_response_wrapper( + agreements.list, + ) + + +class AsyncAgreementsResourceWithStreamingResponse: + def __init__(self, agreements: AsyncAgreementsResource) -> None: + self._agreements = agreements + + self.retrieve = async_to_streamed_response_wrapper( + agreements.retrieve, + ) + self.list = async_to_streamed_response_wrapper( + agreements.list, + ) diff --git a/src/telnyx/resources/terms_of_service/branded_calling.py b/src/telnyx/resources/terms_of_service/branded_calling.py new file mode 100644 index 00000000..a4693e3f --- /dev/null +++ b/src/telnyx/resources/terms_of_service/branded_calling.py @@ -0,0 +1,159 @@ +# 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 ..._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.terms_of_service.branded_calling_agree_response import BrandedCallingAgreeResponse + +__all__ = ["BrandedCallingResource", "AsyncBrandedCallingResource"] + + +class BrandedCallingResource(SyncAPIResource): + """ + Accept and review the Branded Calling and Phone Number Reputation terms of service. + """ + + @cached_property + def with_raw_response(self) -> BrandedCallingResourceWithRawResponse: + """ + 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 BrandedCallingResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> BrandedCallingResourceWithStreamingResponse: + """ + 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 BrandedCallingResourceWithStreamingResponse(self) + + def agree( + 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, + ) -> BrandedCallingAgreeResponse: + """ + Records the authenticated user's agreement to the current Branded Calling ToS. + No body required. Idempotent — re-calling after agreement is a no-op and returns + the existing agreement. + + This is a prerequisite for activating Branded Calling on any enterprise + (`POST /enterprises/{id}/branded_calling`); without an agreement, activation + returns `403`. + """ + return self._post( + "/terms_of_service/branded_calling/agree", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=BrandedCallingAgreeResponse, + ) + + +class AsyncBrandedCallingResource(AsyncAPIResource): + """ + Accept and review the Branded Calling and Phone Number Reputation terms of service. + """ + + @cached_property + def with_raw_response(self) -> AsyncBrandedCallingResourceWithRawResponse: + """ + 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 AsyncBrandedCallingResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncBrandedCallingResourceWithStreamingResponse: + """ + 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 AsyncBrandedCallingResourceWithStreamingResponse(self) + + async def agree( + 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, + ) -> BrandedCallingAgreeResponse: + """ + Records the authenticated user's agreement to the current Branded Calling ToS. + No body required. Idempotent — re-calling after agreement is a no-op and returns + the existing agreement. + + This is a prerequisite for activating Branded Calling on any enterprise + (`POST /enterprises/{id}/branded_calling`); without an agreement, activation + returns `403`. + """ + return await self._post( + "/terms_of_service/branded_calling/agree", + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=BrandedCallingAgreeResponse, + ) + + +class BrandedCallingResourceWithRawResponse: + def __init__(self, branded_calling: BrandedCallingResource) -> None: + self._branded_calling = branded_calling + + self.agree = to_raw_response_wrapper( + branded_calling.agree, + ) + + +class AsyncBrandedCallingResourceWithRawResponse: + def __init__(self, branded_calling: AsyncBrandedCallingResource) -> None: + self._branded_calling = branded_calling + + self.agree = async_to_raw_response_wrapper( + branded_calling.agree, + ) + + +class BrandedCallingResourceWithStreamingResponse: + def __init__(self, branded_calling: BrandedCallingResource) -> None: + self._branded_calling = branded_calling + + self.agree = to_streamed_response_wrapper( + branded_calling.agree, + ) + + +class AsyncBrandedCallingResourceWithStreamingResponse: + def __init__(self, branded_calling: AsyncBrandedCallingResource) -> None: + self._branded_calling = branded_calling + + self.agree = async_to_streamed_response_wrapper( + branded_calling.agree, + ) diff --git a/src/telnyx/resources/terms_of_service/number_reputation.py b/src/telnyx/resources/terms_of_service/number_reputation.py index d047e0b0..50c63a56 100644 --- a/src/telnyx/resources/terms_of_service/number_reputation.py +++ b/src/telnyx/resources/terms_of_service/number_reputation.py @@ -4,7 +4,7 @@ import httpx -from ..._types import Body, Query, Headers, NoneType, NotGiven, not_given +from ..._types import Body, Query, Headers, NotGiven, not_given from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import ( @@ -14,12 +14,15 @@ async_to_streamed_response_wrapper, ) from ..._base_client import make_request_options +from ...types.terms_of_service.number_reputation_agree_response import NumberReputationAgreeResponse __all__ = ["NumberReputationResource", "AsyncNumberReputationResource"] class NumberReputationResource(SyncAPIResource): - """Terms of Service agreement endpoints""" + """ + Accept and review the Branded Calling and Phone Number Reputation terms of service. + """ @cached_property def with_raw_response(self) -> NumberReputationResourceWithRawResponse: @@ -49,27 +52,26 @@ def agree( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> None: - """Accept the Terms of Service for the Number Reputation product. - - Must be called - before using Number Reputation endpoints. + ) -> NumberReputationAgreeResponse: + """ + Records the authenticated user's agreement to the current Phone Number + Reputation ToS. No body required. Idempotent. - Returns `400` with error code `10015` if the user has already agreed to the - current ToS version. + Prerequisite for using any of the `/v2/.../reputation/*` endpoints. """ - extra_headers = {"Accept": "*/*", **(extra_headers or {})} return self._post( "/terms_of_service/number_reputation/agree", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=NoneType, + cast_to=NumberReputationAgreeResponse, ) class AsyncNumberReputationResource(AsyncAPIResource): - """Terms of Service agreement endpoints""" + """ + Accept and review the Branded Calling and Phone Number Reputation terms of service. + """ @cached_property def with_raw_response(self) -> AsyncNumberReputationResourceWithRawResponse: @@ -99,22 +101,19 @@ async def agree( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> None: - """Accept the Terms of Service for the Number Reputation product. - - Must be called - before using Number Reputation endpoints. + ) -> NumberReputationAgreeResponse: + """ + Records the authenticated user's agreement to the current Phone Number + Reputation ToS. No body required. Idempotent. - Returns `400` with error code `10015` if the user has already agreed to the - current ToS version. + Prerequisite for using any of the `/v2/.../reputation/*` endpoints. """ - extra_headers = {"Accept": "*/*", **(extra_headers or {})} return await self._post( "/terms_of_service/number_reputation/agree", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=NoneType, + cast_to=NumberReputationAgreeResponse, ) diff --git a/src/telnyx/resources/terms_of_service/terms_of_service.py b/src/telnyx/resources/terms_of_service/terms_of_service.py index b94ff0c8..fdc3d060 100644 --- a/src/telnyx/resources/terms_of_service/terms_of_service.py +++ b/src/telnyx/resources/terms_of_service/terms_of_service.py @@ -2,8 +2,38 @@ from __future__ import annotations +from typing_extensions import Literal + +import httpx + +from ...types import terms_of_service_status_params +from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given +from ..._utils import maybe_transform, async_maybe_transform from ..._compat import cached_property +from .agreements import ( + AgreementsResource, + AsyncAgreementsResource, + AgreementsResourceWithRawResponse, + AsyncAgreementsResourceWithRawResponse, + AgreementsResourceWithStreamingResponse, + AsyncAgreementsResourceWithStreamingResponse, +) 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 .branded_calling import ( + BrandedCallingResource, + AsyncBrandedCallingResource, + BrandedCallingResourceWithRawResponse, + AsyncBrandedCallingResourceWithRawResponse, + BrandedCallingResourceWithStreamingResponse, + AsyncBrandedCallingResourceWithStreamingResponse, +) from .number_reputation import ( NumberReputationResource, AsyncNumberReputationResource, @@ -12,16 +42,37 @@ NumberReputationResourceWithStreamingResponse, AsyncNumberReputationResourceWithStreamingResponse, ) +from ...types.terms_of_service_status_response import TermsOfServiceStatusResponse __all__ = ["TermsOfServiceResource", "AsyncTermsOfServiceResource"] class TermsOfServiceResource(SyncAPIResource): + """ + Accept and review the Branded Calling and Phone Number Reputation terms of service. + """ + @cached_property def number_reputation(self) -> NumberReputationResource: - """Terms of Service agreement endpoints""" + """ + Accept and review the Branded Calling and Phone Number Reputation terms of service. + """ return NumberReputationResource(self._client) + @cached_property + def agreements(self) -> AgreementsResource: + """ + Accept and review the Branded Calling and Phone Number Reputation terms of service. + """ + return AgreementsResource(self._client) + + @cached_property + def branded_calling(self) -> BrandedCallingResource: + """ + Accept and review the Branded Calling and Phone Number Reputation terms of service. + """ + return BrandedCallingResource(self._client) + @cached_property def with_raw_response(self) -> TermsOfServiceResourceWithRawResponse: """ @@ -41,13 +92,80 @@ def with_streaming_response(self) -> TermsOfServiceResourceWithStreamingResponse """ return TermsOfServiceResourceWithStreamingResponse(self) + def status( + self, + *, + product_type: Literal["branded_calling", "number_reputation"] | 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, + ) -> TermsOfServiceStatusResponse: + """ + Returns whether the authenticated user has agreed to the current Number + Reputation Terms of Service. Used during onboarding to decide whether to prompt + the user with the ToS dialog before continuing. + + The `agreement_required: true` value means the user has not yet agreed (or has + agreed to an outdated version) and must call + `POST /terms_of_service/number_reputation/agree` before they can use the Number + Reputation endpoints on an enterprise. + + Args: + product_type: Which product's ToS to check. Defaults to `branded_calling`; pass + `number_reputation` to check the Number Reputation Terms of Service. + + 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( + "/terms_of_service/status", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + {"product_type": product_type}, terms_of_service_status_params.TermsOfServiceStatusParams + ), + ), + cast_to=TermsOfServiceStatusResponse, + ) + class AsyncTermsOfServiceResource(AsyncAPIResource): + """ + Accept and review the Branded Calling and Phone Number Reputation terms of service. + """ + @cached_property def number_reputation(self) -> AsyncNumberReputationResource: - """Terms of Service agreement endpoints""" + """ + Accept and review the Branded Calling and Phone Number Reputation terms of service. + """ return AsyncNumberReputationResource(self._client) + @cached_property + def agreements(self) -> AsyncAgreementsResource: + """ + Accept and review the Branded Calling and Phone Number Reputation terms of service. + """ + return AsyncAgreementsResource(self._client) + + @cached_property + def branded_calling(self) -> AsyncBrandedCallingResource: + """ + Accept and review the Branded Calling and Phone Number Reputation terms of service. + """ + return AsyncBrandedCallingResource(self._client) + @cached_property def with_raw_response(self) -> AsyncTermsOfServiceResourceWithRawResponse: """ @@ -67,42 +185,169 @@ def with_streaming_response(self) -> AsyncTermsOfServiceResourceWithStreamingRes """ return AsyncTermsOfServiceResourceWithStreamingResponse(self) + async def status( + self, + *, + product_type: Literal["branded_calling", "number_reputation"] | 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, + ) -> TermsOfServiceStatusResponse: + """ + Returns whether the authenticated user has agreed to the current Number + Reputation Terms of Service. Used during onboarding to decide whether to prompt + the user with the ToS dialog before continuing. + + The `agreement_required: true` value means the user has not yet agreed (or has + agreed to an outdated version) and must call + `POST /terms_of_service/number_reputation/agree` before they can use the Number + Reputation endpoints on an enterprise. + + Args: + product_type: Which product's ToS to check. Defaults to `branded_calling`; pass + `number_reputation` to check the Number Reputation Terms of Service. + + 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( + "/terms_of_service/status", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform( + {"product_type": product_type}, terms_of_service_status_params.TermsOfServiceStatusParams + ), + ), + cast_to=TermsOfServiceStatusResponse, + ) + class TermsOfServiceResourceWithRawResponse: def __init__(self, terms_of_service: TermsOfServiceResource) -> None: self._terms_of_service = terms_of_service + self.status = to_raw_response_wrapper( + terms_of_service.status, + ) + @cached_property def number_reputation(self) -> NumberReputationResourceWithRawResponse: - """Terms of Service agreement endpoints""" + """ + Accept and review the Branded Calling and Phone Number Reputation terms of service. + """ return NumberReputationResourceWithRawResponse(self._terms_of_service.number_reputation) + @cached_property + def agreements(self) -> AgreementsResourceWithRawResponse: + """ + Accept and review the Branded Calling and Phone Number Reputation terms of service. + """ + return AgreementsResourceWithRawResponse(self._terms_of_service.agreements) + + @cached_property + def branded_calling(self) -> BrandedCallingResourceWithRawResponse: + """ + Accept and review the Branded Calling and Phone Number Reputation terms of service. + """ + return BrandedCallingResourceWithRawResponse(self._terms_of_service.branded_calling) + class AsyncTermsOfServiceResourceWithRawResponse: def __init__(self, terms_of_service: AsyncTermsOfServiceResource) -> None: self._terms_of_service = terms_of_service + self.status = async_to_raw_response_wrapper( + terms_of_service.status, + ) + @cached_property def number_reputation(self) -> AsyncNumberReputationResourceWithRawResponse: - """Terms of Service agreement endpoints""" + """ + Accept and review the Branded Calling and Phone Number Reputation terms of service. + """ return AsyncNumberReputationResourceWithRawResponse(self._terms_of_service.number_reputation) + @cached_property + def agreements(self) -> AsyncAgreementsResourceWithRawResponse: + """ + Accept and review the Branded Calling and Phone Number Reputation terms of service. + """ + return AsyncAgreementsResourceWithRawResponse(self._terms_of_service.agreements) + + @cached_property + def branded_calling(self) -> AsyncBrandedCallingResourceWithRawResponse: + """ + Accept and review the Branded Calling and Phone Number Reputation terms of service. + """ + return AsyncBrandedCallingResourceWithRawResponse(self._terms_of_service.branded_calling) + class TermsOfServiceResourceWithStreamingResponse: def __init__(self, terms_of_service: TermsOfServiceResource) -> None: self._terms_of_service = terms_of_service + self.status = to_streamed_response_wrapper( + terms_of_service.status, + ) + @cached_property def number_reputation(self) -> NumberReputationResourceWithStreamingResponse: - """Terms of Service agreement endpoints""" + """ + Accept and review the Branded Calling and Phone Number Reputation terms of service. + """ return NumberReputationResourceWithStreamingResponse(self._terms_of_service.number_reputation) + @cached_property + def agreements(self) -> AgreementsResourceWithStreamingResponse: + """ + Accept and review the Branded Calling and Phone Number Reputation terms of service. + """ + return AgreementsResourceWithStreamingResponse(self._terms_of_service.agreements) + + @cached_property + def branded_calling(self) -> BrandedCallingResourceWithStreamingResponse: + """ + Accept and review the Branded Calling and Phone Number Reputation terms of service. + """ + return BrandedCallingResourceWithStreamingResponse(self._terms_of_service.branded_calling) + class AsyncTermsOfServiceResourceWithStreamingResponse: def __init__(self, terms_of_service: AsyncTermsOfServiceResource) -> None: self._terms_of_service = terms_of_service + self.status = async_to_streamed_response_wrapper( + terms_of_service.status, + ) + @cached_property def number_reputation(self) -> AsyncNumberReputationResourceWithStreamingResponse: - """Terms of Service agreement endpoints""" + """ + Accept and review the Branded Calling and Phone Number Reputation terms of service. + """ return AsyncNumberReputationResourceWithStreamingResponse(self._terms_of_service.number_reputation) + + @cached_property + def agreements(self) -> AsyncAgreementsResourceWithStreamingResponse: + """ + Accept and review the Branded Calling and Phone Number Reputation terms of service. + """ + return AsyncAgreementsResourceWithStreamingResponse(self._terms_of_service.agreements) + + @cached_property + def branded_calling(self) -> AsyncBrandedCallingResourceWithStreamingResponse: + """ + Accept and review the Branded Calling and Phone Number Reputation terms of service. + """ + return AsyncBrandedCallingResourceWithStreamingResponse(self._terms_of_service.branded_calling) diff --git a/src/telnyx/resources/uac_connections/uac_connections.py b/src/telnyx/resources/uac_connections/uac_connections.py index 87dcdaab..53a7d738 100644 --- a/src/telnyx/resources/uac_connections/uac_connections.py +++ b/src/telnyx/resources/uac_connections/uac_connections.py @@ -36,12 +36,9 @@ from ...pagination import SyncDefaultFlatPagination, AsyncDefaultFlatPagination from ..._base_client import AsyncPaginator, make_request_options from ...types.dtmf_type import DtmfType -from ...types.uac_connection import UacConnection from ...types.encrypted_media import EncryptedMedia -from ...types.uac_outbound_param import UacOutboundParam from ...types.anchorsite_override import AnchorsiteOverride -from ...types.uac_external_settings_param import UacExternalSettingsParam -from ...types.uac_internal_settings_param import UacInternalSettingsParam +from ...types.uac_connection_list_response import UacConnectionListResponse from ...types.connection_rtcp_settings_param import ConnectionRtcpSettingsParam from ...types.uac_connection_create_response import UacConnectionCreateResponse from ...types.uac_connection_delete_response import UacConnectionDeleteResponse @@ -92,15 +89,15 @@ def create( dtmf_type: DtmfType | Omit = omit, encode_contact_header_enabled: bool | Omit = omit, encrypted_media: Optional[EncryptedMedia] | Omit = omit, - external_uac_settings: UacExternalSettingsParam | Omit = omit, + external_uac_settings: uac_connection_create_params.ExternalUacSettings | Omit = omit, inbound: uac_connection_create_params.Inbound | Omit = omit, - internal_uac_settings: UacInternalSettingsParam | Omit = omit, + internal_uac_settings: uac_connection_create_params.InternalUacSettings | Omit = omit, ios_push_credential_id: Optional[str] | Omit = omit, jitter_buffer: ConnectionJitterBuffer | Omit = omit, noise_suppression: Literal["inbound", "outbound", "both", "disabled"] | Omit = omit, noise_suppression_details: ConnectionNoiseSuppressionDetails | Omit = omit, onnet_t38_passthrough_enabled: bool | Omit = omit, - outbound: UacOutboundParam | Omit = omit, + outbound: uac_connection_create_params.Outbound | Omit = omit, password: str | Omit = omit, rtcp_settings: ConnectionRtcpSettingsParam | Omit = omit, sip_uri_calling_preference: Literal["disabled", "unrestricted", "internal"] | Omit = omit, @@ -301,15 +298,15 @@ def update( dtmf_type: DtmfType | Omit = omit, encode_contact_header_enabled: bool | Omit = omit, encrypted_media: Optional[EncryptedMedia] | Omit = omit, - external_uac_settings: UacExternalSettingsParam | Omit = omit, + external_uac_settings: uac_connection_update_params.ExternalUacSettings | Omit = omit, inbound: uac_connection_update_params.Inbound | Omit = omit, - internal_uac_settings: UacInternalSettingsParam | Omit = omit, + internal_uac_settings: uac_connection_update_params.InternalUacSettings | Omit = omit, ios_push_credential_id: Optional[str] | Omit = omit, jitter_buffer: ConnectionJitterBuffer | Omit = omit, noise_suppression: Literal["inbound", "outbound", "both", "disabled"] | Omit = omit, noise_suppression_details: ConnectionNoiseSuppressionDetails | Omit = omit, onnet_t38_passthrough_enabled: bool | Omit = omit, - outbound: UacOutboundParam | Omit = omit, + outbound: uac_connection_update_params.Outbound | Omit = omit, password: str | Omit = omit, rtcp_settings: ConnectionRtcpSettingsParam | Omit = omit, sip_uri_calling_preference: Literal["disabled", "unrestricted", "internal"] | Omit = omit, @@ -473,7 +470,7 @@ def list( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> SyncDefaultFlatPagination[UacConnection]: + ) -> SyncDefaultFlatPagination[UacConnectionListResponse]: """Returns a list of your UAC connections. A UAC (User Agent Client) Connection @@ -512,7 +509,7 @@ def list( """ return self._get_api_list( "/uac_connections", - page=SyncDefaultFlatPagination[UacConnection], + page=SyncDefaultFlatPagination[UacConnectionListResponse], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -528,7 +525,7 @@ def list( uac_connection_list_params.UacConnectionListParams, ), ), - model=UacConnection, + model=UacConnectionListResponse, ) def delete( @@ -604,15 +601,15 @@ async def create( dtmf_type: DtmfType | Omit = omit, encode_contact_header_enabled: bool | Omit = omit, encrypted_media: Optional[EncryptedMedia] | Omit = omit, - external_uac_settings: UacExternalSettingsParam | Omit = omit, + external_uac_settings: uac_connection_create_params.ExternalUacSettings | Omit = omit, inbound: uac_connection_create_params.Inbound | Omit = omit, - internal_uac_settings: UacInternalSettingsParam | Omit = omit, + internal_uac_settings: uac_connection_create_params.InternalUacSettings | Omit = omit, ios_push_credential_id: Optional[str] | Omit = omit, jitter_buffer: ConnectionJitterBuffer | Omit = omit, noise_suppression: Literal["inbound", "outbound", "both", "disabled"] | Omit = omit, noise_suppression_details: ConnectionNoiseSuppressionDetails | Omit = omit, onnet_t38_passthrough_enabled: bool | Omit = omit, - outbound: UacOutboundParam | Omit = omit, + outbound: uac_connection_create_params.Outbound | Omit = omit, password: str | Omit = omit, rtcp_settings: ConnectionRtcpSettingsParam | Omit = omit, sip_uri_calling_preference: Literal["disabled", "unrestricted", "internal"] | Omit = omit, @@ -813,15 +810,15 @@ async def update( dtmf_type: DtmfType | Omit = omit, encode_contact_header_enabled: bool | Omit = omit, encrypted_media: Optional[EncryptedMedia] | Omit = omit, - external_uac_settings: UacExternalSettingsParam | Omit = omit, + external_uac_settings: uac_connection_update_params.ExternalUacSettings | Omit = omit, inbound: uac_connection_update_params.Inbound | Omit = omit, - internal_uac_settings: UacInternalSettingsParam | Omit = omit, + internal_uac_settings: uac_connection_update_params.InternalUacSettings | Omit = omit, ios_push_credential_id: Optional[str] | Omit = omit, jitter_buffer: ConnectionJitterBuffer | Omit = omit, noise_suppression: Literal["inbound", "outbound", "both", "disabled"] | Omit = omit, noise_suppression_details: ConnectionNoiseSuppressionDetails | Omit = omit, onnet_t38_passthrough_enabled: bool | Omit = omit, - outbound: UacOutboundParam | Omit = omit, + outbound: uac_connection_update_params.Outbound | Omit = omit, password: str | Omit = omit, rtcp_settings: ConnectionRtcpSettingsParam | Omit = omit, sip_uri_calling_preference: Literal["disabled", "unrestricted", "internal"] | Omit = omit, @@ -985,7 +982,7 @@ def list( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> AsyncPaginator[UacConnection, AsyncDefaultFlatPagination[UacConnection]]: + ) -> AsyncPaginator[UacConnectionListResponse, AsyncDefaultFlatPagination[UacConnectionListResponse]]: """Returns a list of your UAC connections. A UAC (User Agent Client) Connection @@ -1024,7 +1021,7 @@ def list( """ return self._get_api_list( "/uac_connections", - page=AsyncDefaultFlatPagination[UacConnection], + page=AsyncDefaultFlatPagination[UacConnectionListResponse], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -1040,7 +1037,7 @@ def list( uac_connection_list_params.UacConnectionListParams, ), ), - model=UacConnection, + model=UacConnectionListResponse, ) async def delete( diff --git a/src/telnyx/resources/virtual_cross_connects.py b/src/telnyx/resources/virtual_cross_connects.py index a7b37fbc..042383c0 100644 --- a/src/telnyx/resources/virtual_cross_connects.py +++ b/src/telnyx/resources/virtual_cross_connects.py @@ -23,7 +23,7 @@ ) from ..pagination import SyncDefaultFlatPagination, AsyncDefaultFlatPagination from .._base_client import AsyncPaginator, make_request_options -from ..types.virtual_cross_connect_combined import VirtualCrossConnectCombined +from ..types.virtual_cross_connect_list_response import VirtualCrossConnectListResponse from ..types.virtual_cross_connect_create_response import VirtualCrossConnectCreateResponse from ..types.virtual_cross_connect_delete_response import VirtualCrossConnectDeleteResponse from ..types.virtual_cross_connect_update_response import VirtualCrossConnectUpdateResponse @@ -294,7 +294,7 @@ def list( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> SyncDefaultFlatPagination[VirtualCrossConnectCombined]: + ) -> SyncDefaultFlatPagination[VirtualCrossConnectListResponse]: """ List all Virtual Cross Connects. @@ -311,7 +311,7 @@ def list( """ return self._get_api_list( "/virtual_cross_connects", - page=SyncDefaultFlatPagination[VirtualCrossConnectCombined], + page=SyncDefaultFlatPagination[VirtualCrossConnectListResponse], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -326,7 +326,7 @@ def list( virtual_cross_connect_list_params.VirtualCrossConnectListParams, ), ), - model=VirtualCrossConnectCombined, + model=VirtualCrossConnectListResponse, ) def delete( @@ -625,7 +625,7 @@ def list( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> AsyncPaginator[VirtualCrossConnectCombined, AsyncDefaultFlatPagination[VirtualCrossConnectCombined]]: + ) -> AsyncPaginator[VirtualCrossConnectListResponse, AsyncDefaultFlatPagination[VirtualCrossConnectListResponse]]: """ List all Virtual Cross Connects. @@ -642,7 +642,7 @@ def list( """ return self._get_api_list( "/virtual_cross_connects", - page=AsyncDefaultFlatPagination[VirtualCrossConnectCombined], + page=AsyncDefaultFlatPagination[VirtualCrossConnectListResponse], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -657,7 +657,7 @@ def list( virtual_cross_connect_list_params.VirtualCrossConnectListParams, ), ), - model=VirtualCrossConnectCombined, + model=VirtualCrossConnectListResponse, ) async def delete( diff --git a/src/telnyx/resources/wireguard_interfaces.py b/src/telnyx/resources/wireguard_interfaces.py index d2f6bad1..3266d472 100644 --- a/src/telnyx/resources/wireguard_interfaces.py +++ b/src/telnyx/resources/wireguard_interfaces.py @@ -17,7 +17,7 @@ ) from ..pagination import SyncDefaultFlatPagination, AsyncDefaultFlatPagination from .._base_client import AsyncPaginator, make_request_options -from ..types.wireguard_interface_read import WireguardInterfaceRead +from ..types.wireguard_interface_list_response import WireguardInterfaceListResponse from ..types.wireguard_interface_create_response import WireguardInterfaceCreateResponse from ..types.wireguard_interface_delete_response import WireguardInterfaceDeleteResponse from ..types.wireguard_interface_retrieve_response import WireguardInterfaceRetrieveResponse @@ -145,7 +145,7 @@ def list( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> SyncDefaultFlatPagination[WireguardInterfaceRead]: + ) -> SyncDefaultFlatPagination[WireguardInterfaceListResponse]: """ List all WireGuard Interfaces. @@ -162,7 +162,7 @@ def list( """ return self._get_api_list( "/wireguard_interfaces", - page=SyncDefaultFlatPagination[WireguardInterfaceRead], + page=SyncDefaultFlatPagination[WireguardInterfaceListResponse], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -177,7 +177,7 @@ def list( wireguard_interface_list_params.WireguardInterfaceListParams, ), ), - model=WireguardInterfaceRead, + model=WireguardInterfaceListResponse, ) def delete( @@ -334,7 +334,7 @@ def list( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> AsyncPaginator[WireguardInterfaceRead, AsyncDefaultFlatPagination[WireguardInterfaceRead]]: + ) -> AsyncPaginator[WireguardInterfaceListResponse, AsyncDefaultFlatPagination[WireguardInterfaceListResponse]]: """ List all WireGuard Interfaces. @@ -351,7 +351,7 @@ def list( """ return self._get_api_list( "/wireguard_interfaces", - page=AsyncDefaultFlatPagination[WireguardInterfaceRead], + page=AsyncDefaultFlatPagination[WireguardInterfaceListResponse], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -366,7 +366,7 @@ def list( wireguard_interface_list_params.WireguardInterfaceListParams, ), ), - model=WireguardInterfaceRead, + model=WireguardInterfaceListResponse, ) async def delete( diff --git a/src/telnyx/types/__init__.py b/src/telnyx/types/__init__.py index b5541f55..f42c8a25 100644 --- a/src/telnyx/types/__init__.py +++ b/src/telnyx/types/__init__.py @@ -16,7 +16,6 @@ Feature as Feature, APIError as APIError, Metadata as Metadata, - MetaInfo as MetaInfo, ShortCode as ShortCode, HostedNumber as HostedNumber, SimCardStatus as SimCardStatus, @@ -25,7 +24,6 @@ CostInformation as CostInformation, NetappsLocation as NetappsLocation, RoomParticipant as RoomParticipant, - XaiVoiceSettings as XaiVoiceSettings, RegionInformation as RegionInformation, RimeVoiceSettings as RimeVoiceSettings, AzureVoiceSettings as AzureVoiceSettings, @@ -52,7 +50,6 @@ AvailablePhoneNumbersMetadata as AvailablePhoneNumbersMetadata, PhoneNumberWithMessagingSettings as PhoneNumberWithMessagingSettings, ConnectionNoiseSuppressionDetails as ConnectionNoiseSuppressionDetails, - ReputationPhoneNumberWithReputationData as ReputationPhoneNumberWithReputationData, SubNumberOrderRegulatoryRequirementWithValue as SubNumberOrderRegulatoryRequirementWithValue, ) from .address import Address as Address @@ -71,7 +68,6 @@ from .oauth_grant import OAuthGrant as OAuthGrant from .outbound_ip import OutboundIP as OutboundIP from .rcs_to_item import RcsToItem as RcsToItem -from .uac_inbound import UacInbound as UacInbound from .call_bridged import CallBridged as CallBridged from .inbound_fqdn import InboundFqdn as InboundFqdn from .month_detail import MonthDetail as MonthDetail @@ -81,7 +77,6 @@ from .service_plan import ServicePlan as ServicePlan from .stream_codec import StreamCodec as StreamCodec from .traffic_type import TrafficType as TrafficType -from .uac_outbound import UacOutbound as UacOutbound from .user_address import UserAddress as UserAddress from .verification import Verification as Verification from .video_region import VideoRegion as VideoRegion @@ -97,12 +92,10 @@ from .call_initiated import CallInitiated as CallInitiated from .ip_list_params import IPListParams as IPListParams from .media_resource import MediaResource as MediaResource -from .model_metadata import ModelMetadata as ModelMetadata from .rcs_suggestion import RcsSuggestion as RcsSuggestion from .settings_param import SettingsParam as SettingsParam from .sim_card_group import SimCardGroup as SimCardGroup from .sim_card_order import SimCardOrder as SimCardOrder -from .uac_connection import UacConnection as UacConnection from .verify_profile import VerifyProfile as VerifyProfile from .whatsapp_media import WhatsappMedia as WhatsappMedia from .wireless_error import WirelessError as WirelessError @@ -110,6 +103,7 @@ from .billing_address import BillingAddress as BillingAddress from .billing_contact import BillingContact as BillingContact from .call_left_queue import CallLeftQueue as CallLeftQueue +from .dir_list_params import DirListParams as DirListParams from .encrypted_media import EncryptedMedia as EncryptedMedia from .fax_application import FaxApplication as FaxApplication from .fax_list_params import FaxListParams as FaxListParams @@ -148,10 +142,13 @@ from .call_gather_ended import CallGatherEnded as CallGatherEnded from .call_refer_failed import CallReferFailed as CallReferFailed from .custom_sip_header import CustomSipHeader as CustomSipHeader +from .dir_list_response import DirListResponse as DirListResponse +from .dir_update_params import DirUpdateParams as DirUpdateParams from .enterprise_public import EnterprisePublic as EnterprisePublic from .fax_create_params import FaxCreateParams as FaxCreateParams from .media_list_params import MediaListParams as MediaListParams from .messaging_profile import MessagingProfile as MessagingProfile +from .network_interface import NetworkInterface as NetworkInterface from .outbound_ip_param import OutboundIPParam as OutboundIPParam from .queue_list_params import QueueListParams as QueueListParams from .rcs_agent_message import RcsAgentMessage as RcsAgentMessage @@ -183,7 +180,6 @@ from .room_create_params import RoomCreateParams as RoomCreateParams from .room_update_params import RoomUpdateParams as RoomUpdateParams from .transport_protocol import TransportProtocol as TransportProtocol -from .uac_outbound_param import UacOutboundParam as UacOutboundParam from .video_region_param import VideoRegionParam as VideoRegionParam from .wireless_blocklist import WirelessBlocklist as WirelessBlocklist from .address_list_params import AddressListParams as AddressListParams @@ -194,6 +190,8 @@ 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_submit_response import DirSubmitResponse as DirSubmitResponse +from .dir_update_response import DirUpdateResponse as DirUpdateResponse from .external_connection import ExternalConnection as ExternalConnection from .fax_create_response import FaxCreateResponse as FaxCreateResponse from .fax_media_processed import FaxMediaProcessed as FaxMediaProcessed @@ -254,6 +252,7 @@ from .comment_create_params import CommentCreateParams as CommentCreateParams from .comment_list_response import CommentListResponse as CommentListResponse from .credential_connection import CredentialConnection as CredentialConnection +from .dir_retrieve_response import DirRetrieveResponse as DirRetrieveResponse from .fax_retrieve_response import FaxRetrieveResponse as FaxRetrieveResponse from .global_ip_list_params import GlobalIPListParams as GlobalIPListParams from .invoice_list_response import InvoiceListResponse as InvoiceListResponse @@ -272,8 +271,6 @@ from .recording_list_params import RecordingListParams as RecordingListParams from .reserved_phone_number import ReservedPhoneNumber as ReservedPhoneNumber from .s3_configuration_data import S3ConfigurationData as S3ConfigurationData -from .uac_external_settings import UacExternalSettings as UacExternalSettings -from .uac_internal_settings import UacInternalSettings as UacInternalSettings from .alphanumeric_sender_id import AlphanumericSenderID as AlphanumericSenderID from .call_event_list_params import CallEventListParams as CallEventListParams from .call_streaming_started import CallStreamingStarted as CallStreamingStarted @@ -315,6 +312,7 @@ from .call_conversation_ended import CallConversationEnded as CallConversationEnded from .call_cost_webhook_event import CallCostWebhookEvent as CallCostWebhookEvent from .call_hold_webhook_event import CallHoldWebhookEvent as CallHoldWebhookEvent +from .call_reason_list_params import CallReasonListParams as CallReasonListParams from .comment_create_response import CommentCreateResponse as CommentCreateResponse from .custom_sip_header_param import CustomSipHeaderParam as CustomSipHeaderParam from .customer_service_record import CustomerServiceRecord as CustomerServiceRecord @@ -380,12 +378,12 @@ from .user_address_list_params import UserAddressListParams as UserAddressListParams from .voice_design_list_params import VoiceDesignListParams as VoiceDesignListParams from .whatsapp_message_content import WhatsappMessageContent as WhatsappMessageContent -from .wireguard_interface_read import WireguardInterfaceRead as WireguardInterfaceRead from .address_retrieve_response import AddressRetrieveResponse as AddressRetrieveResponse from .audit_event_list_response import AuditEventListResponse as AuditEventListResponse from .balance_retrieve_response import BalanceRetrieveResponse as BalanceRetrieveResponse from .billing_group_list_params import BillingGroupListParams as BillingGroupListParams from .call_hangup_webhook_event import CallHangupWebhookEvent as CallHangupWebhookEvent +from .call_reason_list_response import CallReasonListResponse as CallReasonListResponse from .call_unhold_webhook_event import CallUnholdWebhookEvent as CallUnholdWebhookEvent from .comment_retrieve_response import CommentRetrieveResponse as CommentRetrieveResponse from .conference_playback_ended import ConferencePlaybackEnded as ConferencePlaybackEnded @@ -458,6 +456,7 @@ from .call_answered_webhook_event import CallAnsweredWebhookEvent as CallAnsweredWebhookEvent from .call_enqueued_webhook_event import CallEnqueuedWebhookEvent as CallEnqueuedWebhookEvent from .call_machine_greeting_ended import CallMachineGreetingEnded as CallMachineGreetingEnded +from .call_reason_validate_params import CallReasonValidateParams as CallReasonValidateParams from .conference_participant_left import ConferenceParticipantLeft as ConferenceParticipantLeft from .conference_playback_started import ConferencePlaybackStarted as ConferencePlaybackStarted from .detail_record_list_response import DetailRecordListResponse as DetailRecordListResponse @@ -478,8 +477,6 @@ from .reserved_phone_number_param import ReservedPhoneNumberParam as ReservedPhoneNumberParam from .s3_configuration_data_param import S3ConfigurationDataParam as S3ConfigurationDataParam from .transcription_webhook_event import TranscriptionWebhookEvent as TranscriptionWebhookEvent -from .uac_external_settings_param import UacExternalSettingsParam as UacExternalSettingsParam -from .uac_internal_settings_param import UacInternalSettingsParam as UacInternalSettingsParam from .unsafe_unwrap_webhook_event import UnsafeUnwrapWebhookEvent as UnsafeUnwrapWebhookEvent from .verified_number_list_params import VerifiedNumberListParams as VerifiedNumberListParams from .voice_clone_create_response import VoiceCloneCreateResponse as VoiceCloneCreateResponse @@ -511,7 +508,6 @@ from .porting_order_end_user_admin import PortingOrderEndUserAdmin as PortingOrderEndUserAdmin from .porting_order_end_user_param import PortingOrderEndUserParam as PortingOrderEndUserParam from .portout_update_status_params import PortoutUpdateStatusParams as PortoutUpdateStatusParams -from .public_internet_gateway_read import PublicInternetGatewayRead as PublicInternetGatewayRead from .requirement_type_list_params import RequirementTypeListParams as RequirementTypeListParams from .room_composition_list_params import RoomCompositionListParams as RoomCompositionListParams from .room_participant_list_params import RoomParticipantListParams as RoomParticipantListParams @@ -523,6 +519,7 @@ from .sim_card_order_create_params import SimCardOrderCreateParams as SimCardOrderCreateParams from .sub_number_order_list_params import SubNumberOrderListParams as SubNumberOrderListParams from .uac_connection_create_params import UacConnectionCreateParams as UacConnectionCreateParams +from .uac_connection_list_response import UacConnectionListResponse as UacConnectionListResponse from .uac_connection_update_params import UacConnectionUpdateParams as UacConnectionUpdateParams from .url_shortener_settings_param import URLShortenerSettingsParam as URLShortenerSettingsParam from .user_address_create_response import UserAddressCreateResponse as UserAddressCreateResponse @@ -543,6 +540,7 @@ from .billing_group_delete_response import BillingGroupDeleteResponse as BillingGroupDeleteResponse from .billing_group_update_response import BillingGroupUpdateResponse as BillingGroupUpdateResponse from .call_left_queue_webhook_event import CallLeftQueueWebhookEvent as CallLeftQueueWebhookEvent +from .call_reason_validate_response import CallReasonValidateResponse as CallReasonValidateResponse from .call_retrieve_status_response import CallRetrieveStatusResponse as CallRetrieveStatusResponse from .comment_mark_as_read_response import CommentMarkAsReadResponse as CommentMarkAsReadResponse from .conference_participant_joined import ConferenceParticipantJoined as ConferenceParticipantJoined @@ -586,6 +584,7 @@ from .call_speak_ended_webhook_event import CallSpeakEndedWebhookEvent as CallSpeakEndedWebhookEvent from .conference_ended_webhook_event import ConferenceEndedWebhookEvent as ConferenceEndedWebhookEvent from .connection_rtcp_settings_param import ConnectionRtcpSettingsParam as ConnectionRtcpSettingsParam +from .dir_update_infringement_params import DirUpdateInfringementParams as DirUpdateInfringementParams from .integration_secret_list_params import IntegrationSecretListParams as IntegrationSecretListParams from .inventory_coverage_list_params import InventoryCoverageListParams as InventoryCoverageListParams from .list_retrieve_by_zone_response import ListRetrieveByZoneResponse as ListRetrieveByZoneResponse @@ -615,13 +614,13 @@ from .siprec_connector_update_params import SiprecConnectorUpdateParams as SiprecConnectorUpdateParams from .sub_number_order_list_response import SubNumberOrderListResponse as SubNumberOrderListResponse from .sub_number_order_update_params import SubNumberOrderUpdateParams as SubNumberOrderUpdateParams +from .terms_of_service_status_params import TermsOfServiceStatusParams as TermsOfServiceStatusParams from .text_to_speech_generate_params import TextToSpeechGenerateParams as TextToSpeechGenerateParams from .uac_connection_create_response import UacConnectionCreateResponse as UacConnectionCreateResponse from .uac_connection_delete_response import UacConnectionDeleteResponse as UacConnectionDeleteResponse from .uac_connection_update_response import UacConnectionUpdateResponse as UacConnectionUpdateResponse from .user_address_retrieve_response import UserAddressRetrieveResponse as UserAddressRetrieveResponse from .verification_retrieve_response import VerificationRetrieveResponse as VerificationRetrieveResponse -from .virtual_cross_connect_combined import VirtualCrossConnectCombined as VirtualCrossConnectCombined from .voice_design_retrieve_response import VoiceDesignRetrieveResponse as VoiceDesignRetrieveResponse from .webhook_delivery_list_response import WebhookDeliveryListResponse as WebhookDeliveryListResponse from .whatsapp_message_content_param import WhatsappMessageContentParam as WhatsappMessageContentParam @@ -682,6 +681,8 @@ from .call_siprec_failed_webhook_event import CallSiprecFailedWebhookEvent as CallSiprecFailedWebhookEvent from .call_speak_started_webhook_event import CallSpeakStartedWebhookEvent as CallSpeakStartedWebhookEvent from .conference_created_webhook_event import ConferenceCreatedWebhookEvent as ConferenceCreatedWebhookEvent +from .dir_list_document_types_response import DirListDocumentTypesResponse as DirListDocumentTypesResponse +from .dir_update_infringement_response import DirUpdateInfringementResponse as DirUpdateInfringementResponse from .global_ip_assignment_list_params import GlobalIPAssignmentListParams as GlobalIPAssignmentListParams from .global_ip_protocol_list_response import GlobalIPProtocolListResponse as GlobalIPProtocolListResponse from .inexplicit_number_order_response import InexplicitNumberOrderResponse as InexplicitNumberOrderResponse @@ -712,6 +713,7 @@ from .sub_number_order_retrieve_params import SubNumberOrderRetrieveParams as SubNumberOrderRetrieveParams from .sub_number_order_update_response import SubNumberOrderUpdateResponse as SubNumberOrderUpdateResponse from .telephony_credential_list_params import TelephonyCredentialListParams as TelephonyCredentialListParams +from .terms_of_service_status_response import TermsOfServiceStatusResponse as TermsOfServiceStatusResponse from .text_to_speech_generate_response import TextToSpeechGenerateResponse as TextToSpeechGenerateResponse from .uac_connection_retrieve_response import UacConnectionRetrieveResponse as UacConnectionRetrieveResponse from .verification_trigger_call_params import VerificationTriggerCallParams as VerificationTriggerCallParams @@ -732,6 +734,7 @@ from .fqdn_connection_retrieve_response import FqdnConnectionRetrieveResponse as FqdnConnectionRetrieveResponse from .global_ip_latency_retrieve_params import GlobalIPLatencyRetrieveParams as GlobalIPLatencyRetrieveParams from .global_ip_usage_retrieve_response import GlobalIPUsageRetrieveResponse as GlobalIPUsageRetrieveResponse +from .infringement_claim_contest_params import InfringementClaimContestParams as InfringementClaimContestParams from .managed_account_retrieve_response import ManagedAccountRetrieveResponse as ManagedAccountRetrieveResponse from .message_cancel_scheduled_response import MessageCancelScheduledResponse as MessageCancelScheduledResponse from .message_send_number_pool_response import MessageSendNumberPoolResponse as MessageSendNumberPoolResponse @@ -753,6 +756,7 @@ from .virtual_cross_connect_list_params import VirtualCrossConnectListParams as VirtualCrossConnectListParams from .voice_sdk_call_report_list_params import VoiceSDKCallReportListParams as VoiceSDKCallReportListParams from .wireguard_interface_create_params import WireguardInterfaceCreateParams as WireguardInterfaceCreateParams +from .wireguard_interface_list_response import WireguardInterfaceListResponse as WireguardInterfaceListResponse from .alphanumeric_sender_id_list_params import AlphanumericSenderIDListParams as AlphanumericSenderIDListParams from .available_phone_number_list_params import AvailablePhoneNumberListParams as AvailablePhoneNumberListParams from .bulk_sim_card_action_list_response import BulkSimCardActionListResponse as BulkSimCardActionListResponse @@ -807,11 +811,13 @@ from .customer_service_record_list_params import CustomerServiceRecordListParams as CustomerServiceRecordListParams from .dialogflow_connection_create_params import DialogflowConnectionCreateParams as DialogflowConnectionCreateParams from .dialogflow_connection_update_params import DialogflowConnectionUpdateParams as DialogflowConnectionUpdateParams +from .dir_list_infringement_claims_params import DirListInfringementClaimsParams as DirListInfringementClaimsParams from .external_connection_create_response import ExternalConnectionCreateResponse as ExternalConnectionCreateResponse from .external_connection_delete_response import ExternalConnectionDeleteResponse as ExternalConnectionDeleteResponse from .external_connection_update_response import ExternalConnectionUpdateResponse as ExternalConnectionUpdateResponse from .global_ip_latency_retrieve_response import GlobalIPLatencyRetrieveResponse as GlobalIPLatencyRetrieveResponse from .inexplicit_number_order_list_params import InexplicitNumberOrderListParams as InexplicitNumberOrderListParams +from .infringement_claim_contest_response import InfringementClaimContestResponse as InfringementClaimContestResponse from .messaging_hosted_number_list_params import MessagingHostedNumberListParams as MessagingHostedNumberListParams from .messaging_profile_retrieve_response import MessagingProfileRetrieveResponse as MessagingProfileRetrieveResponse from .mobile_network_operator_list_params import MobileNetworkOperatorListParams as MobileNetworkOperatorListParams @@ -826,6 +832,7 @@ from .text_to_speech_list_voices_response import TextToSpeechListVoicesResponse as TextToSpeechListVoicesResponse from .update_regulatory_requirement_param import UpdateRegulatoryRequirementParam as UpdateRegulatoryRequirementParam from .virtual_cross_connect_create_params import VirtualCrossConnectCreateParams as VirtualCrossConnectCreateParams +from .virtual_cross_connect_list_response import VirtualCrossConnectListResponse as VirtualCrossConnectListResponse from .virtual_cross_connect_update_params import VirtualCrossConnectUpdateParams as VirtualCrossConnectUpdateParams from .voice_design_download_sample_params import VoiceDesignDownloadSampleParams as VoiceDesignDownloadSampleParams from .voice_sdk_call_report_list_response import VoiceSDKCallReportListResponse as VoiceSDKCallReportListResponse @@ -848,6 +855,7 @@ from .global_ip_assignment_update_response import GlobalIPAssignmentUpdateResponse as GlobalIPAssignmentUpdateResponse from .global_ip_health_check_create_params import GlobalIPHealthCheckCreateParams as GlobalIPHealthCheckCreateParams from .global_ip_health_check_list_response import GlobalIPHealthCheckListResponse as GlobalIPHealthCheckListResponse +from .infringement_claim_retrieve_response import InfringementClaimRetrieveResponse as InfringementClaimRetrieveResponse from .messaging_profile_metric_list_params import MessagingProfileMetricListParams as MessagingProfileMetricListParams from .mobile_push_credential_create_params import MobilePushCredentialCreateParams as MobilePushCredentialCreateParams from .notification_channel_create_response import NotificationChannelCreateResponse as NotificationChannelCreateResponse @@ -909,6 +917,9 @@ from .dialogflow_connection_update_response import ( DialogflowConnectionUpdateResponse as DialogflowConnectionUpdateResponse, ) +from .dir_list_infringement_claims_response import ( + DirListInfringementClaimsResponse as DirListInfringementClaimsResponse, +) from .dynamic_emergency_address_list_params import ( DynamicEmergencyAddressListParams as DynamicEmergencyAddressListParams, ) @@ -944,6 +955,9 @@ from .public_internet_gateway_create_params import ( PublicInternetGatewayCreateParams as PublicInternetGatewayCreateParams, ) +from .public_internet_gateway_list_response import ( + PublicInternetGatewayListResponse as PublicInternetGatewayListResponse, +) from .sim_card_get_activation_code_response import SimCardGetActivationCodeResponse as SimCardGetActivationCodeResponse from .sim_card_order_preview_preview_params import SimCardOrderPreviewPreviewParams as SimCardOrderPreviewPreviewParams from .verification_trigger_flashcall_params import ( @@ -1388,6 +1402,9 @@ from .dynamic_emergency_endpoint_retrieve_response import ( DynamicEmergencyEndpointRetrieveResponse as DynamicEmergencyEndpointRetrieveResponse, ) +from .enterprise_activate_branded_calling_response import ( + EnterpriseActivateBrandedCallingResponse as EnterpriseActivateBrandedCallingResponse, +) from .external_connection_update_location_response import ( ExternalConnectionUpdateLocationResponse as ExternalConnectionUpdateLocationResponse, ) diff --git a/src/telnyx/types/ai/__init__.py b/src/telnyx/types/ai/__init__.py index 6f72480c..9b9fb7e8 100644 --- a/src/telnyx/types/ai/__init__.py +++ b/src/telnyx/types/ai/__init__.py @@ -5,7 +5,6 @@ from .bucket_ids import BucketIDs as BucketIDs from .hangup_tool import HangupTool as HangupTool from .conversation import Conversation as Conversation -from .external_llm import ExternalLlm as ExternalLlm from .mission_data import MissionData as MissionData from .observability import Observability as Observability from .assistant_tool import AssistantTool as AssistantTool @@ -13,7 +12,6 @@ from .voice_settings import VoiceSettings as VoiceSettings from .assistant_param import AssistantParam as AssistantParam from .assistants_list import AssistantsList as AssistantsList -from .fallback_config import FallbackConfig as FallbackConfig from .import_metadata import ImportMetadata as ImportMetadata from .widget_settings import WidgetSettings as WidgetSettings from .bucket_ids_param import BucketIDsParam as BucketIDsParam @@ -34,9 +32,7 @@ from .cluster_list_params import ClusterListParams as ClusterListParams from .inference_embedding import InferenceEmbedding as InferenceEmbedding from .mission_list_params import MissionListParams as MissionListParams -from .start_speaking_plan import StartSpeakingPlan as StartSpeakingPlan from .transfer_tool_param import TransferToolParam as TransferToolParam -from .assistant_mcp_server import AssistantMcpServer as AssistantMcpServer from .assistant_tool_param import AssistantToolParam as AssistantToolParam from .embedding_url_params import EmbeddingURLParams as EmbeddingURLParams from .retrieval_tool_param import RetrievalToolParam as RetrievalToolParam @@ -44,14 +40,12 @@ from .tool_update_response import ToolUpdateResponse as ToolUpdateResponse from .voice_settings_param import VoiceSettingsParam as VoiceSettingsParam from .assistant_chat_params import AssistantChatParams as AssistantChatParams -from .assistant_integration import AssistantIntegration as AssistantIntegration from .cluster_list_response import ClusterListResponse as ClusterListResponse from .embedding_list_params import EmbeddingListParams as EmbeddingListParams from .mission_create_params import MissionCreateParams as MissionCreateParams from .widget_settings_param import WidgetSettingsParam as WidgetSettingsParam from .background_task_status import BackgroundTaskStatus as BackgroundTaskStatus from .cluster_compute_params import ClusterComputeParams as ClusterComputeParams -from .external_llm_req_param import ExternalLlmReqParam as ExternalLlmReqParam from .insight_settings_param import InsightSettingsParam as InsightSettingsParam from .mcp_server_list_params import McpServerListParams as McpServerListParams from .privacy_settings_param import PrivacySettingsParam as PrivacySettingsParam @@ -81,11 +75,8 @@ from .assistant_send_sms_params import AssistantSendSMSParams as AssistantSendSMSParams from .audio_transcribe_response import AudioTranscribeResponse as AudioTranscribeResponse from .cluster_retrieve_response import ClusterRetrieveResponse as ClusterRetrieveResponse -from .fallback_config_req_param import FallbackConfigReqParam as FallbackConfigReqParam from .integration_list_response import IntegrationListResponse as IntegrationListResponse from .mission_retrieve_response import MissionRetrieveResponse as MissionRetrieveResponse -from .start_speaking_plan_param import StartSpeakingPlanParam as StartSpeakingPlanParam -from .assistant_mcp_server_param import AssistantMcpServerParam as AssistantMcpServerParam from .cluster_fetch_graph_params import ClusterFetchGraphParams as ClusterFetchGraphParams from .conversation_create_params import ConversationCreateParams as ConversationCreateParams from .conversation_list_response import ConversationListResponse as ConversationListResponse @@ -93,8 +84,6 @@ from .mcp_server_create_response import McpServerCreateResponse as McpServerCreateResponse from .mcp_server_update_response import McpServerUpdateResponse as McpServerUpdateResponse from .mission_list_events_params import MissionListEventsParams as MissionListEventsParams -from .post_conversation_settings import PostConversationSettings as PostConversationSettings -from .assistant_integration_param import AssistantIntegrationParam as AssistantIntegrationParam from .assistant_send_sms_response import AssistantSendSMSResponse as AssistantSendSMSResponse from .embedding_retrieve_response import EmbeddingRetrieveResponse as EmbeddingRetrieveResponse from .openai_list_models_response import OpenAIListModelsResponse as OpenAIListModelsResponse @@ -109,7 +98,6 @@ from .openai_create_response_params import OpenAICreateResponseParams as OpenAICreateResponseParams from .transcription_settings_config import TranscriptionSettingsConfig as TranscriptionSettingsConfig from .conversation_retrieve_response import ConversationRetrieveResponse as ConversationRetrieveResponse -from .transcription_endpointing_plan import TranscriptionEndpointingPlan as TranscriptionEndpointingPlan from .chat_create_completion_response import ChatCreateCompletionResponse as ChatCreateCompletionResponse from .conversation_add_message_params import ConversationAddMessageParams as ConversationAddMessageParams from .mission_update_mission_response import MissionUpdateMissionResponse as MissionUpdateMissionResponse @@ -117,20 +105,12 @@ from .embedding_similarity_search_params import EmbeddingSimilaritySearchParams as EmbeddingSimilaritySearchParams from .transcription_settings_config_param import TranscriptionSettingsConfigParam as TranscriptionSettingsConfigParam from .embedding_similarity_search_response import EmbeddingSimilaritySearchResponse as EmbeddingSimilaritySearchResponse -from .post_conversation_settings_req_param import PostConversationSettingsReqParam as PostConversationSettingsReqParam -from .transcription_endpointing_plan_param import TranscriptionEndpointingPlanParam as TranscriptionEndpointingPlanParam from .inference_embedding_webhook_tool_params import ( InferenceEmbeddingWebhookToolParams as InferenceEmbeddingWebhookToolParams, ) -from .inference_embedding_interruption_settings import ( - InferenceEmbeddingInterruptionSettings as InferenceEmbeddingInterruptionSettings, -) from .inference_embedding_webhook_tool_params_param import ( InferenceEmbeddingWebhookToolParamsParam as InferenceEmbeddingWebhookToolParamsParam, ) -from .inference_embedding_interruption_settings_param import ( - InferenceEmbeddingInterruptionSettingsParam as InferenceEmbeddingInterruptionSettingsParam, -) from .conversation_retrieve_conversations_insights_response import ( ConversationRetrieveConversationsInsightsResponse as ConversationRetrieveConversationsInsightsResponse, ) diff --git a/src/telnyx/types/ai/assistant_create_params.py b/src/telnyx/types/ai/assistant_create_params.py index 656a379e..bebde025 100644 --- a/src/telnyx/types/ai/assistant_create_params.py +++ b/src/telnyx/types/ai/assistant_create_params.py @@ -10,24 +10,19 @@ from .assistant_tool_param import AssistantToolParam from .voice_settings_param import VoiceSettingsParam 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_mcp_server_param import AssistantMcpServerParam -from .assistant_integration_param import AssistantIntegrationParam from .transcription_settings_param import TranscriptionSettingsParam -from .post_conversation_settings_req_param import PostConversationSettingsReqParam -from .inference_embedding_interruption_settings_param import InferenceEmbeddingInterruptionSettingsParam __all__ = [ "AssistantCreateParams", "ConversationFlow", "ConversationFlowNode", "ConversationFlowNodeFlowNodeReq", + "ConversationFlowNodeFlowNodeReqExternalLlm", "ConversationFlowNodeFlowNodeReqPosition", "ConversationFlowNodeToolNodeReq", "ConversationFlowNodeToolNodeReqPosition", @@ -47,6 +42,15 @@ "ConversationFlowEdgeTargetNodeTarget", "ConversationFlowEdgeTargetAssistantTarget", "ConversationFlowEdgeTargetAssistantTargetPosition", + "ExternalLlm", + "FallbackConfig", + "FallbackConfigExternalLlm", + "Integration", + "InterruptionSettings", + "InterruptionSettingsStartSpeakingPlan", + "InterruptionSettingsStartSpeakingPlanTranscriptionEndpointingPlan", + "McpServer", + "PostConversationSettings", ] @@ -95,9 +99,9 @@ class AssistantCreateParams(TypedDict, total=False): enabled_features: List[EnabledFeatures] - external_llm: ExternalLlmReqParam + external_llm: ExternalLlm - fallback_config: FallbackConfigReqParam + fallback_config: FallbackConfig greeting: str """Text that the assistant will use to start the conversation. @@ -111,7 +115,7 @@ class AssistantCreateParams(TypedDict, total=False): insight_settings: InsightSettingsParam - integrations: Iterable[AssistantIntegrationParam] + integrations: Iterable[Integration] """Connected integrations attached to the assistant. The catalog of available integrations is at `/ai/integrations`; the user's @@ -119,7 +123,7 @@ class AssistantCreateParams(TypedDict, total=False): references a catalog integration by `integration_id`. """ - interruption_settings: InferenceEmbeddingInterruptionSettingsParam + interruption_settings: InterruptionSettings """ Settings for interruptions and how the assistant decides the user has finished speaking. These timings are most relevant when using non turn-taking @@ -139,7 +143,7 @@ class AssistantCreateParams(TypedDict, total=False): are unlikely to work with this integration. """ - mcp_servers: Iterable[AssistantMcpServerParam] + mcp_servers: Iterable[McpServer] """MCP servers attached to the assistant. Create MCP servers with `/ai/mcp_servers`, then reference them by `id` here. @@ -159,7 +163,7 @@ class AssistantCreateParams(TypedDict, total=False): observability_settings: ObservabilityReqParam - post_conversation_settings: PostConversationSettingsReqParam + post_conversation_settings: PostConversationSettings """Configuration for post-conversation processing. When enabled, the assistant receives one additional LLM turn after the @@ -200,6 +204,47 @@ class AssistantCreateParams(TypedDict, total=False): """Configuration settings for the assistant's web widget.""" +class ConversationFlowNodeFlowNodeReqExternalLlm(TypedDict, total=False): + """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`, `base_url`, credentials). Part of the LLM bundle — see `model` for cascade semantics. Mutually exclusive with `model` on the node (a single LLM identity per node). + """ + + 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: Literal["token", "certificate"] + """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. + """ + + class ConversationFlowNodeFlowNodeReqPosition(TypedDict, total=False): """Optional canvas coordinates used by authoring UIs to lay out the graph. @@ -226,7 +271,7 @@ class ConversationFlowNodeFlowNodeReq(TypedDict, total=False): instructions: Required[str] """Prompt that drives the LLM while this node is active. Required.""" - external_llm: ExternalLlmReqParam + external_llm: ConversationFlowNodeFlowNodeReqExternalLlm """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`, @@ -627,3 +672,199 @@ class ConversationFlow(TypedDict, total=False): edges: Iterable[ConversationFlowEdge] """Directed transitions between nodes. May be empty for a single-node flow.""" + + +class ExternalLlm(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: Literal["token", "certificate"] + """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. + """ + + +class FallbackConfigExternalLlm(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: Literal["token", "certificate"] + """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. + """ + + +class FallbackConfig(TypedDict, total=False): + external_llm: FallbackConfigExternalLlm + + llm_api_key_ref: str + """Integration secret identifier for the fallback model API key.""" + + model: str + """ + Fallback Telnyx-hosted model to use when the primary LLM provider is + unavailable. + """ + + +class Integration(TypedDict, total=False): + """Reference to a connected integration attached to an assistant. + + Discover available integrations with `/ai/integrations` and connected integrations with `/ai/integrations/connections`. + """ + + integration_id: Required[str] + """Catalog integration ID to attach. + + This is the `id` from the integrations catalog at `/ai/integrations` (the same + value also appears as `integration_id` on entries returned by + `/ai/integrations/connections`). It is **not** the connection-level `id` from + `/ai/integrations/connections`. + """ + + allowed_list: SequenceNotStr[str] + """Optional per-assistant allowlist of integration tool names. + + When omitted or empty, all tools allowed by the connected integration are + available to the assistant. + """ + + +class InterruptionSettingsStartSpeakingPlanTranscriptionEndpointingPlan(TypedDict, total=False): + """Endpointing thresholds used to decide when the user has finished speaking. + + Applies to non turn-taking transcription models. For `deepgram/flux`, use `transcription.settings.eot_threshold` / `eot_timeout_ms` / `eager_eot_threshold`. + """ + + on_no_punctuation_seconds: float + """Seconds to wait after the transcript ends without punctuation.""" + + on_number_seconds: float + """Seconds to wait after the transcript ends with a number.""" + + on_punctuation_seconds: float + """Seconds to wait after the transcript ends with punctuation.""" + + +class InterruptionSettingsStartSpeakingPlan(TypedDict, total=False): + """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. + """ + + transcription_endpointing_plan: InterruptionSettingsStartSpeakingPlanTranscriptionEndpointingPlan + """Endpointing thresholds used to decide when the user has finished speaking. + + Applies to non turn-taking transcription models. For `deepgram/flux`, use + `transcription.settings.eot_threshold` / `eot_timeout_ms` / + `eager_eot_threshold`. + """ + + wait_seconds: float + """Minimum seconds to wait before the assistant starts speaking.""" + + +class InterruptionSettings(TypedDict, total=False): + """ + Settings for interruptions and how the assistant decides the user has finished speaking. These timings are most relevant when using non turn-taking transcription models. For turn-taking models like `deepgram/flux`, end-of-turn behavior is controlled by the transcription end-of-turn settings under `transcription.settings` (`eot_threshold`, `eot_timeout_ms`, `eager_eot_threshold`). + """ + + disable_greeting_interruption: bool + """When true, disables user interruptions while the assistant greeting is playing.""" + + enable: bool + """Whether users can interrupt the assistant while it is speaking.""" + + start_speaking_plan: InterruptionSettingsStartSpeakingPlan + """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. + """ + + +class McpServer(TypedDict, total=False): + """Reference to an MCP server attached to an assistant. + + Create and manage MCP servers with the `/ai/mcp_servers` endpoints, then attach them to assistants by ID. + """ + + id: Required[str] + """ID of the MCP server to attach. + + This must be the `id` of an MCP server returned by the `/ai/mcp_servers` + endpoints. + """ + + allowed_tools: SequenceNotStr[str] + """Optional per-assistant allowlist of MCP tool names. + + When omitted, the assistant uses the MCP server's configured `allowed_tools`. + """ + + +class PostConversationSettings(TypedDict, total=False): + """Configuration for post-conversation processing. + + When enabled, the assistant receives one additional LLM turn after the conversation ends, allowing it to execute tool calls such as logging to a CRM or sending a summary. The assistant can execute multiple parallel or sequential tools during this phase. Telephony-control tools (e.g. hangup, transfer) are unavailable post-conversation. Beta feature. + """ + + enabled: bool + """Whether post-conversation processing is enabled. + + When true, the assistant will be invoked after the conversation ends to perform + any final tool calls. Defaults to false. + """ diff --git a/src/telnyx/types/ai/assistant_integration.py b/src/telnyx/types/ai/assistant_integration.py deleted file mode 100644 index f686769d..00000000 --- a/src/telnyx/types/ai/assistant_integration.py +++ /dev/null @@ -1,30 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import List, Optional - -from ..._models import BaseModel - -__all__ = ["AssistantIntegration"] - - -class AssistantIntegration(BaseModel): - """Reference to a connected integration attached to an assistant. - - Discover available integrations with `/ai/integrations` and connected integrations with `/ai/integrations/connections`. - """ - - integration_id: str - """Catalog integration ID to attach. - - This is the `id` from the integrations catalog at `/ai/integrations` (the same - value also appears as `integration_id` on entries returned by - `/ai/integrations/connections`). It is **not** the connection-level `id` from - `/ai/integrations/connections`. - """ - - allowed_list: Optional[List[str]] = None - """Optional per-assistant allowlist of integration tool names. - - When omitted or empty, all tools allowed by the connected integration are - available to the assistant. - """ diff --git a/src/telnyx/types/ai/assistant_integration_param.py b/src/telnyx/types/ai/assistant_integration_param.py deleted file mode 100644 index 9f8e9a70..00000000 --- a/src/telnyx/types/ai/assistant_integration_param.py +++ /dev/null @@ -1,32 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing_extensions import Required, TypedDict - -from ..._types import SequenceNotStr - -__all__ = ["AssistantIntegrationParam"] - - -class AssistantIntegrationParam(TypedDict, total=False): - """Reference to a connected integration attached to an assistant. - - Discover available integrations with `/ai/integrations` and connected integrations with `/ai/integrations/connections`. - """ - - integration_id: Required[str] - """Catalog integration ID to attach. - - This is the `id` from the integrations catalog at `/ai/integrations` (the same - value also appears as `integration_id` on entries returned by - `/ai/integrations/connections`). It is **not** the connection-level `id` from - `/ai/integrations/connections`. - """ - - allowed_list: SequenceNotStr[str] - """Optional per-assistant allowlist of integration tool names. - - When omitted or empty, all tools allowed by the connected integration are - available to the assistant. - """ diff --git a/src/telnyx/types/ai/assistant_mcp_server.py b/src/telnyx/types/ai/assistant_mcp_server.py deleted file mode 100644 index c12e8217..00000000 --- a/src/telnyx/types/ai/assistant_mcp_server.py +++ /dev/null @@ -1,27 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import List, Optional - -from ..._models import BaseModel - -__all__ = ["AssistantMcpServer"] - - -class AssistantMcpServer(BaseModel): - """Reference to an MCP server attached to an assistant. - - Create and manage MCP servers with the `/ai/mcp_servers` endpoints, then attach them to assistants by ID. - """ - - id: str - """ID of the MCP server to attach. - - This must be the `id` of an MCP server returned by the `/ai/mcp_servers` - endpoints. - """ - - allowed_tools: Optional[List[str]] = None - """Optional per-assistant allowlist of MCP tool names. - - When omitted, the assistant uses the MCP server's configured `allowed_tools`. - """ diff --git a/src/telnyx/types/ai/assistant_mcp_server_param.py b/src/telnyx/types/ai/assistant_mcp_server_param.py deleted file mode 100644 index 520d4696..00000000 --- a/src/telnyx/types/ai/assistant_mcp_server_param.py +++ /dev/null @@ -1,29 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing_extensions import Required, TypedDict - -from ..._types import SequenceNotStr - -__all__ = ["AssistantMcpServerParam"] - - -class AssistantMcpServerParam(TypedDict, total=False): - """Reference to an MCP server attached to an assistant. - - Create and manage MCP servers with the `/ai/mcp_servers` endpoints, then attach them to assistants by ID. - """ - - id: Required[str] - """ID of the MCP server to attach. - - This must be the `id` of an MCP server returned by the `/ai/mcp_servers` - endpoints. - """ - - allowed_tools: SequenceNotStr[str] - """Optional per-assistant allowlist of MCP tool names. - - When omitted, the assistant uses the MCP server's configured `allowed_tools`. - """ diff --git a/src/telnyx/types/ai/assistant_tool.py b/src/telnyx/types/ai/assistant_tool.py index ca0927c8..b9092f3f 100644 --- a/src/telnyx/types/ai/assistant_tool.py +++ b/src/telnyx/types/ai/assistant_tool.py @@ -18,7 +18,7 @@ "HandoffHandoffAIAssistant", "Transfer", "TransferTransfer", - "TransferTransferTargetsTargetsList", + "TransferTransferTargetsUnionMember0", "TransferTransferCustomHeader", "TransferTransferVoicemailDetection", "TransferTransferVoicemailDetectionDetectionConfig", @@ -27,7 +27,7 @@ "Invite", "InviteInvite", "InviteInviteCustomHeader", - "InviteInviteTargetsTargetsList", + "InviteInviteTargetsUnionMember0", "InviteInviteVoicemailDetection", "InviteInviteVoicemailDetectionOnVoicemailDetected", "Refer", @@ -74,7 +74,7 @@ class Handoff(BaseModel): type: Literal["handoff"] -class TransferTransferTargetsTargetsList(BaseModel): +class TransferTransferTargetsUnionMember0(BaseModel): to: str """The destination number or SIP URI of the call.""" @@ -200,7 +200,7 @@ class TransferTransfer(BaseModel): from_: str = FieldInfo(alias="from") """Number or SIP URI placing the call.""" - targets: Union[List[TransferTransferTargetsTargetsList], str] + targets: Union[List[TransferTransferTargetsUnionMember0], str] """The different possible targets of the transfer. The assistant will be able to choose one of the targets to transfer the call to. @@ -261,7 +261,7 @@ class InviteInviteCustomHeader(BaseModel): """ -class InviteInviteTargetsTargetsList(BaseModel): +class InviteInviteTargetsUnionMember0(BaseModel): to: str """The destination number or SIP URI of the call.""" @@ -299,7 +299,7 @@ class InviteInvite(BaseModel): custom_headers: Optional[List[InviteInviteCustomHeader]] = None """Custom headers to be added to the SIP INVITE for the invite command.""" - targets: Union[List[InviteInviteTargetsTargetsList], str, None] = None + targets: Union[List[InviteInviteTargetsUnionMember0], str, None] = None """The different possible targets of the invite. The assistant will be able to choose one of the targets to invite to the call. diff --git a/src/telnyx/types/ai/assistant_tool_param.py b/src/telnyx/types/ai/assistant_tool_param.py index f2ad8bc6..0cbd6605 100644 --- a/src/telnyx/types/ai/assistant_tool_param.py +++ b/src/telnyx/types/ai/assistant_tool_param.py @@ -16,7 +16,7 @@ "HandoffHandoffAIAssistant", "Transfer", "TransferTransfer", - "TransferTransferTargetsTargetsList", + "TransferTransferTargetsUnionMember0", "TransferTransferCustomHeader", "TransferTransferVoicemailDetection", "TransferTransferVoicemailDetectionDetectionConfig", @@ -25,7 +25,7 @@ "Invite", "InviteInvite", "InviteInviteCustomHeader", - "InviteInviteTargetsTargetsList", + "InviteInviteTargetsUnionMember0", "InviteInviteVoicemailDetection", "InviteInviteVoicemailDetectionOnVoicemailDetected", "Refer", @@ -72,7 +72,7 @@ class Handoff(TypedDict, total=False): type: Required[Literal["handoff"]] -class TransferTransferTargetsTargetsList(TypedDict, total=False): +class TransferTransferTargetsUnionMember0(TypedDict, total=False): to: Required[str] """The destination number or SIP URI of the call.""" @@ -204,7 +204,7 @@ class TransferTransferVoicemailDetection(TypedDict, total=False): class TransferTransfer(_TransferTransferReservedKeywords, total=False): - targets: Required[Union[Iterable[TransferTransferTargetsTargetsList], str]] + targets: Required[Union[Iterable[TransferTransferTargetsUnionMember0], str]] """The different possible targets of the transfer. The assistant will be able to choose one of the targets to transfer the call to. @@ -265,7 +265,7 @@ class InviteInviteCustomHeader(TypedDict, total=False): """ -class InviteInviteTargetsTargetsList(TypedDict, total=False): +class InviteInviteTargetsUnionMember0(TypedDict, total=False): to: Required[str] """The destination number or SIP URI of the call.""" @@ -309,7 +309,7 @@ class InviteInvite(_InviteInviteReservedKeywords, total=False): custom_headers: Iterable[InviteInviteCustomHeader] """Custom headers to be added to the SIP INVITE for the invite command.""" - targets: Union[Iterable[InviteInviteTargetsTargetsList], str, None] + targets: Union[Iterable[InviteInviteTargetsUnionMember0], str, None] """The different possible targets of the invite. The assistant will be able to choose one of the targets to invite to the call. diff --git a/src/telnyx/types/ai/assistant_update_params.py b/src/telnyx/types/ai/assistant_update_params.py index 221e0e62..a8ffd1de 100644 --- a/src/telnyx/types/ai/assistant_update_params.py +++ b/src/telnyx/types/ai/assistant_update_params.py @@ -10,24 +10,19 @@ from .assistant_tool_param import AssistantToolParam from .voice_settings_param import VoiceSettingsParam 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_mcp_server_param import AssistantMcpServerParam -from .assistant_integration_param import AssistantIntegrationParam from .transcription_settings_param import TranscriptionSettingsParam -from .post_conversation_settings_req_param import PostConversationSettingsReqParam -from .inference_embedding_interruption_settings_param import InferenceEmbeddingInterruptionSettingsParam __all__ = [ "AssistantUpdateParams", "ConversationFlow", "ConversationFlowNode", "ConversationFlowNodeFlowNodeReq", + "ConversationFlowNodeFlowNodeReqExternalLlm", "ConversationFlowNodeFlowNodeReqPosition", "ConversationFlowNodeToolNodeReq", "ConversationFlowNodeToolNodeReqPosition", @@ -47,6 +42,15 @@ "ConversationFlowEdgeTargetNodeTarget", "ConversationFlowEdgeTargetAssistantTarget", "ConversationFlowEdgeTargetAssistantTargetPosition", + "ExternalLlm", + "FallbackConfig", + "FallbackConfigExternalLlm", + "Integration", + "InterruptionSettings", + "InterruptionSettingsStartSpeakingPlan", + "InterruptionSettingsStartSpeakingPlanTranscriptionEndpointingPlan", + "McpServer", + "PostConversationSettings", ] @@ -86,9 +90,9 @@ class AssistantUpdateParams(TypedDict, total=False): enabled_features: List[EnabledFeatures] - external_llm: ExternalLlmReqParam + external_llm: ExternalLlm - fallback_config: FallbackConfigReqParam + fallback_config: FallbackConfig greeting: str """Text that the assistant will use to start the conversation. @@ -109,7 +113,7 @@ class AssistantUpdateParams(TypedDict, total=False): [dynamic variables](https://developers.telnyx.com/docs/inference/ai-assistants/dynamic-variables) """ - integrations: Iterable[AssistantIntegrationParam] + integrations: Iterable[Integration] """Connected integrations attached to the assistant. The catalog of available integrations is at `/ai/integrations`; the user's @@ -117,7 +121,7 @@ class AssistantUpdateParams(TypedDict, total=False): references a catalog integration by `integration_id`. """ - interruption_settings: InferenceEmbeddingInterruptionSettingsParam + interruption_settings: InterruptionSettings """ Settings for interruptions and how the assistant decides the user has finished speaking. These timings are most relevant when using non turn-taking @@ -137,7 +141,7 @@ class AssistantUpdateParams(TypedDict, total=False): are unlikely to work with this integration. """ - mcp_servers: Iterable[AssistantMcpServerParam] + mcp_servers: Iterable[McpServer] """MCP servers attached to the assistant. Create MCP servers with `/ai/mcp_servers`, then reference them by `id` here. @@ -159,7 +163,7 @@ class AssistantUpdateParams(TypedDict, total=False): observability_settings: ObservabilityReqParam - post_conversation_settings: PostConversationSettingsReqParam + post_conversation_settings: PostConversationSettings """Configuration for post-conversation processing. When enabled, the assistant receives one additional LLM turn after the @@ -209,6 +213,47 @@ class AssistantUpdateParams(TypedDict, total=False): """Configuration settings for the assistant's web widget.""" +class ConversationFlowNodeFlowNodeReqExternalLlm(TypedDict, total=False): + """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`, `base_url`, credentials). Part of the LLM bundle — see `model` for cascade semantics. Mutually exclusive with `model` on the node (a single LLM identity per node). + """ + + 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: Literal["token", "certificate"] + """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. + """ + + class ConversationFlowNodeFlowNodeReqPosition(TypedDict, total=False): """Optional canvas coordinates used by authoring UIs to lay out the graph. @@ -235,7 +280,7 @@ class ConversationFlowNodeFlowNodeReq(TypedDict, total=False): instructions: Required[str] """Prompt that drives the LLM while this node is active. Required.""" - external_llm: ExternalLlmReqParam + external_llm: ConversationFlowNodeFlowNodeReqExternalLlm """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`, @@ -636,3 +681,199 @@ class ConversationFlow(TypedDict, total=False): edges: Iterable[ConversationFlowEdge] """Directed transitions between nodes. May be empty for a single-node flow.""" + + +class ExternalLlm(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: Literal["token", "certificate"] + """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. + """ + + +class FallbackConfigExternalLlm(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: Literal["token", "certificate"] + """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. + """ + + +class FallbackConfig(TypedDict, total=False): + external_llm: FallbackConfigExternalLlm + + llm_api_key_ref: str + """Integration secret identifier for the fallback model API key.""" + + model: str + """ + Fallback Telnyx-hosted model to use when the primary LLM provider is + unavailable. + """ + + +class Integration(TypedDict, total=False): + """Reference to a connected integration attached to an assistant. + + Discover available integrations with `/ai/integrations` and connected integrations with `/ai/integrations/connections`. + """ + + integration_id: Required[str] + """Catalog integration ID to attach. + + This is the `id` from the integrations catalog at `/ai/integrations` (the same + value also appears as `integration_id` on entries returned by + `/ai/integrations/connections`). It is **not** the connection-level `id` from + `/ai/integrations/connections`. + """ + + allowed_list: SequenceNotStr[str] + """Optional per-assistant allowlist of integration tool names. + + When omitted or empty, all tools allowed by the connected integration are + available to the assistant. + """ + + +class InterruptionSettingsStartSpeakingPlanTranscriptionEndpointingPlan(TypedDict, total=False): + """Endpointing thresholds used to decide when the user has finished speaking. + + Applies to non turn-taking transcription models. For `deepgram/flux`, use `transcription.settings.eot_threshold` / `eot_timeout_ms` / `eager_eot_threshold`. + """ + + on_no_punctuation_seconds: float + """Seconds to wait after the transcript ends without punctuation.""" + + on_number_seconds: float + """Seconds to wait after the transcript ends with a number.""" + + on_punctuation_seconds: float + """Seconds to wait after the transcript ends with punctuation.""" + + +class InterruptionSettingsStartSpeakingPlan(TypedDict, total=False): + """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. + """ + + transcription_endpointing_plan: InterruptionSettingsStartSpeakingPlanTranscriptionEndpointingPlan + """Endpointing thresholds used to decide when the user has finished speaking. + + Applies to non turn-taking transcription models. For `deepgram/flux`, use + `transcription.settings.eot_threshold` / `eot_timeout_ms` / + `eager_eot_threshold`. + """ + + wait_seconds: float + """Minimum seconds to wait before the assistant starts speaking.""" + + +class InterruptionSettings(TypedDict, total=False): + """ + Settings for interruptions and how the assistant decides the user has finished speaking. These timings are most relevant when using non turn-taking transcription models. For turn-taking models like `deepgram/flux`, end-of-turn behavior is controlled by the transcription end-of-turn settings under `transcription.settings` (`eot_threshold`, `eot_timeout_ms`, `eager_eot_threshold`). + """ + + disable_greeting_interruption: bool + """When true, disables user interruptions while the assistant greeting is playing.""" + + enable: bool + """Whether users can interrupt the assistant while it is speaking.""" + + start_speaking_plan: InterruptionSettingsStartSpeakingPlan + """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. + """ + + +class McpServer(TypedDict, total=False): + """Reference to an MCP server attached to an assistant. + + Create and manage MCP servers with the `/ai/mcp_servers` endpoints, then attach them to assistants by ID. + """ + + id: Required[str] + """ID of the MCP server to attach. + + This must be the `id` of an MCP server returned by the `/ai/mcp_servers` + endpoints. + """ + + allowed_tools: SequenceNotStr[str] + """Optional per-assistant allowlist of MCP tool names. + + When omitted, the assistant uses the MCP server's configured `allowed_tools`. + """ + + +class PostConversationSettings(TypedDict, total=False): + """Configuration for post-conversation processing. + + When enabled, the assistant receives one additional LLM turn after the conversation ends, allowing it to execute tool calls such as logging to a CRM or sending a summary. The assistant can execute multiple parallel or sequential tools during this phase. Telephony-control tools (e.g. hangup, transfer) are unavailable post-conversation. Beta feature. + """ + + enabled: bool + """Whether post-conversation processing is enabled. + + When true, the assistant will be invoked after the conversation ends to perform + any final tool calls. Defaults to false. + """ diff --git a/src/telnyx/types/ai/assistants/__init__.py b/src/telnyx/types/ai/assistants/__init__.py index 3e584a53..406ed42f 100644 --- a/src/telnyx/types/ai/assistants/__init__.py +++ b/src/telnyx/types/ai/assistants/__init__.py @@ -2,21 +2,13 @@ from __future__ import annotations -from .serve import Serve as Serve -from .clause import Clause as Clause -from .rule_output import RuleOutput as RuleOutput -from .serve_param import ServeParam as ServeParam -from .clause_param import ClauseParam as ClauseParam from .event_status import EventStatus as EventStatus -from .rollout_slot import RolloutSlot as RolloutSlot from .assistant_test import AssistantTest as AssistantTest from .tag_add_params import TagAddParams as TagAddParams -from .rule_input_param import RuleInputParam as RuleInputParam from .tag_add_response import TagAddResponse as TagAddResponse from .test_list_params import TestListParams as TestListParams from .tool_test_params import ToolTestParams as ToolTestParams from .tag_list_response import TagListResponse as TagListResponse -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 .tool_test_response import ToolTestResponse as ToolTestResponse 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 98f22d12..df481a3f 100644 --- a/src/telnyx/types/ai/assistants/canary_deploy_create_params.py +++ b/src/telnyx/types/ai/assistants/canary_deploy_create_params.py @@ -3,12 +3,69 @@ from __future__ import annotations from typing import Iterable -from typing_extensions import TypedDict +from typing_extensions import Literal, Required, TypedDict -from .rule_input_param import RuleInputParam +from ...._types import SequenceNotStr -__all__ = ["CanaryDeployCreateParams"] +__all__ = ["CanaryDeployCreateParams", "Rule", "RuleServe", "RuleServeRollout", "RuleMatch"] class CanaryDeployCreateParams(TypedDict, total=False): - rules: Iterable[RuleInputParam] + rules: Iterable[Rule] + + +class RuleServeRollout(TypedDict, total=False): + """One slot in a percentage rollout.""" + + version_id: Required[str] + + weight: Required[float] + + +class RuleServe(TypedDict, total=False): + """What a rule serves when matched. + + Exactly one of: + - ``version_id`` — serve a specific version + - ``rollout`` — weighted random across versions; weights must sum to + less than 100, with the leftover routing to the main version + """ + + rollout: Iterable[RuleServeRollout] + + version_id: str + + +class RuleMatch(TypedDict, total=False): + """A single attribute/operator/values check. + + A clause matches when the routing context's value for ``attribute`` + satisfies ``operator`` against any of ``values``. + """ + + attribute: Required[str] + """Attribute name from the routing context""" + + operator: Required[Literal["in", "not_in", "starts_with"]] + """Match operator""" + + values: Required[SequenceNotStr[str]] + + +class Rule(TypedDict, total=False): + """A targeting rule: ``match`` clauses (AND) gate ``serve``. + + An empty ``match`` is a catch-all (always fires). + """ + + serve: Required[RuleServe] + """What a rule serves when matched. + + Exactly one of: + + - `version_id` — serve a specific version + - `rollout` — weighted random across versions; weights must sum to less than + 100, with the leftover routing to the main version + """ + + match: Iterable[RuleMatch] diff --git a/src/telnyx/types/ai/assistants/canary_deploy_response.py b/src/telnyx/types/ai/assistants/canary_deploy_response.py index 86975189..7c649bbf 100644 --- a/src/telnyx/types/ai/assistants/canary_deploy_response.py +++ b/src/telnyx/types/ai/assistants/canary_deploy_response.py @@ -1,12 +1,69 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import List +from typing import List, Optional from datetime import datetime +from typing_extensions import Literal from ...._models import BaseModel -from .rule_output import RuleOutput -__all__ = ["CanaryDeployResponse"] +__all__ = ["CanaryDeployResponse", "Rule", "RuleServe", "RuleServeRollout", "RuleMatch"] + + +class RuleServeRollout(BaseModel): + """One slot in a percentage rollout.""" + + version_id: str + + weight: float + + +class RuleServe(BaseModel): + """What a rule serves when matched. + + Exactly one of: + - ``version_id`` — serve a specific version + - ``rollout`` — weighted random across versions; weights must sum to + less than 100, with the leftover routing to the main version + """ + + rollout: Optional[List[RuleServeRollout]] = None + + version_id: Optional[str] = None + + +class RuleMatch(BaseModel): + """A single attribute/operator/values check. + + A clause matches when the routing context's value for ``attribute`` + satisfies ``operator`` against any of ``values``. + """ + + attribute: str + """Attribute name from the routing context""" + + operator: Literal["in", "not_in", "starts_with"] + """Match operator""" + + values: List[str] + + +class Rule(BaseModel): + """A targeting rule: ``match`` clauses (AND) gate ``serve``. + + An empty ``match`` is a catch-all (always fires). + """ + + serve: RuleServe + """What a rule serves when matched. + + Exactly one of: + + - `version_id` — serve a specific version + - `rollout` — weighted random across versions; weights must sum to less than + 100, with the leftover routing to the main version + """ + + match: Optional[List[RuleMatch]] = None class CanaryDeployResponse(BaseModel): @@ -19,6 +76,6 @@ class CanaryDeployResponse(BaseModel): created_at: datetime - rules: List[RuleOutput] + rules: List[Rule] updated_at: datetime 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 28148415..c2c4a85f 100644 --- a/src/telnyx/types/ai/assistants/canary_deploy_update_params.py +++ b/src/telnyx/types/ai/assistants/canary_deploy_update_params.py @@ -3,12 +3,69 @@ from __future__ import annotations from typing import Iterable -from typing_extensions import TypedDict +from typing_extensions import Literal, Required, TypedDict -from .rule_input_param import RuleInputParam +from ...._types import SequenceNotStr -__all__ = ["CanaryDeployUpdateParams"] +__all__ = ["CanaryDeployUpdateParams", "Rule", "RuleServe", "RuleServeRollout", "RuleMatch"] class CanaryDeployUpdateParams(TypedDict, total=False): - rules: Iterable[RuleInputParam] + rules: Iterable[Rule] + + +class RuleServeRollout(TypedDict, total=False): + """One slot in a percentage rollout.""" + + version_id: Required[str] + + weight: Required[float] + + +class RuleServe(TypedDict, total=False): + """What a rule serves when matched. + + Exactly one of: + - ``version_id`` — serve a specific version + - ``rollout`` — weighted random across versions; weights must sum to + less than 100, with the leftover routing to the main version + """ + + rollout: Iterable[RuleServeRollout] + + version_id: str + + +class RuleMatch(TypedDict, total=False): + """A single attribute/operator/values check. + + A clause matches when the routing context's value for ``attribute`` + satisfies ``operator`` against any of ``values``. + """ + + attribute: Required[str] + """Attribute name from the routing context""" + + operator: Required[Literal["in", "not_in", "starts_with"]] + """Match operator""" + + values: Required[SequenceNotStr[str]] + + +class Rule(TypedDict, total=False): + """A targeting rule: ``match`` clauses (AND) gate ``serve``. + + An empty ``match`` is a catch-all (always fires). + """ + + serve: Required[RuleServe] + """What a rule serves when matched. + + Exactly one of: + + - `version_id` — serve a specific version + - `rollout` — weighted random across versions; weights must sum to less than + 100, with the leftover routing to the main version + """ + + match: Iterable[RuleMatch] diff --git a/src/telnyx/types/ai/assistants/clause.py b/src/telnyx/types/ai/assistants/clause.py deleted file mode 100644 index 45adbc16..00000000 --- a/src/telnyx/types/ai/assistants/clause.py +++ /dev/null @@ -1,24 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import List -from typing_extensions import Literal - -from ...._models import BaseModel - -__all__ = ["Clause"] - - -class Clause(BaseModel): - """A single attribute/operator/values check. - - A clause matches when the routing context's value for ``attribute`` - satisfies ``operator`` against any of ``values``. - """ - - attribute: str - """Attribute name from the routing context""" - - operator: Literal["in", "not_in", "starts_with"] - """Match operator""" - - values: List[str] diff --git a/src/telnyx/types/ai/assistants/clause_param.py b/src/telnyx/types/ai/assistants/clause_param.py deleted file mode 100644 index 9686b62d..00000000 --- a/src/telnyx/types/ai/assistants/clause_param.py +++ /dev/null @@ -1,25 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing_extensions import Literal, Required, TypedDict - -from ...._types import SequenceNotStr - -__all__ = ["ClauseParam"] - - -class ClauseParam(TypedDict, total=False): - """A single attribute/operator/values check. - - A clause matches when the routing context's value for ``attribute`` - satisfies ``operator`` against any of ``values``. - """ - - attribute: Required[str] - """Attribute name from the routing context""" - - operator: Required[Literal["in", "not_in", "starts_with"]] - """Match operator""" - - values: Required[SequenceNotStr[str]] diff --git a/src/telnyx/types/ai/assistants/rollout_slot.py b/src/telnyx/types/ai/assistants/rollout_slot.py deleted file mode 100644 index 7e79586b..00000000 --- a/src/telnyx/types/ai/assistants/rollout_slot.py +++ /dev/null @@ -1,13 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from ...._models import BaseModel - -__all__ = ["RolloutSlot"] - - -class RolloutSlot(BaseModel): - """One slot in a percentage rollout.""" - - version_id: str - - weight: float diff --git a/src/telnyx/types/ai/assistants/rollout_slot_param.py b/src/telnyx/types/ai/assistants/rollout_slot_param.py deleted file mode 100644 index b793001a..00000000 --- a/src/telnyx/types/ai/assistants/rollout_slot_param.py +++ /dev/null @@ -1,15 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing_extensions import Required, TypedDict - -__all__ = ["RolloutSlotParam"] - - -class RolloutSlotParam(TypedDict, total=False): - """One slot in a percentage rollout.""" - - version_id: Required[str] - - weight: Required[float] diff --git a/src/telnyx/types/ai/assistants/rule_input_param.py b/src/telnyx/types/ai/assistants/rule_input_param.py deleted file mode 100644 index 05f3d15d..00000000 --- a/src/telnyx/types/ai/assistants/rule_input_param.py +++ /dev/null @@ -1,30 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing import Iterable -from typing_extensions import Required, TypedDict - -from .serve_param import ServeParam -from .clause_param import ClauseParam - -__all__ = ["RuleInputParam"] - - -class RuleInputParam(TypedDict, total=False): - """A targeting rule: ``match`` clauses (AND) gate ``serve``. - - An empty ``match`` is a catch-all (always fires). - """ - - serve: Required[ServeParam] - """What a rule serves when matched. - - Exactly one of: - - - `version_id` — serve a specific version - - `rollout` — weighted random across versions; weights must sum to less than - 100, with the leftover routing to the main version - """ - - match: Iterable[ClauseParam] diff --git a/src/telnyx/types/ai/assistants/rule_output.py b/src/telnyx/types/ai/assistants/rule_output.py deleted file mode 100644 index d445b592..00000000 --- a/src/telnyx/types/ai/assistants/rule_output.py +++ /dev/null @@ -1,28 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import List, Optional - -from .serve import Serve -from .clause import Clause -from ...._models import BaseModel - -__all__ = ["RuleOutput"] - - -class RuleOutput(BaseModel): - """A targeting rule: ``match`` clauses (AND) gate ``serve``. - - An empty ``match`` is a catch-all (always fires). - """ - - serve: Serve - """What a rule serves when matched. - - Exactly one of: - - - `version_id` — serve a specific version - - `rollout` — weighted random across versions; weights must sum to less than - 100, with the leftover routing to the main version - """ - - match: Optional[List[Clause]] = None diff --git a/src/telnyx/types/ai/assistants/serve.py b/src/telnyx/types/ai/assistants/serve.py deleted file mode 100644 index be641a46..00000000 --- a/src/telnyx/types/ai/assistants/serve.py +++ /dev/null @@ -1,22 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import List, Optional - -from ...._models import BaseModel -from .rollout_slot import RolloutSlot - -__all__ = ["Serve"] - - -class Serve(BaseModel): - """What a rule serves when matched. - - Exactly one of: - - ``version_id`` — serve a specific version - - ``rollout`` — weighted random across versions; weights must sum to - less than 100, with the leftover routing to the main version - """ - - rollout: Optional[List[RolloutSlot]] = None - - version_id: Optional[str] = None diff --git a/src/telnyx/types/ai/assistants/serve_param.py b/src/telnyx/types/ai/assistants/serve_param.py deleted file mode 100644 index 167c02a7..00000000 --- a/src/telnyx/types/ai/assistants/serve_param.py +++ /dev/null @@ -1,24 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing import Iterable -from typing_extensions import TypedDict - -from .rollout_slot_param import RolloutSlotParam - -__all__ = ["ServeParam"] - - -class ServeParam(TypedDict, total=False): - """What a rule serves when matched. - - Exactly one of: - - ``version_id`` — serve a specific version - - ``rollout`` — weighted random across versions; weights must sum to - less than 100, with the leftover routing to the main version - """ - - rollout: Iterable[RolloutSlotParam] - - version_id: str diff --git a/src/telnyx/types/ai/assistants/version_update_params.py b/src/telnyx/types/ai/assistants/version_update_params.py index 13f9cde0..fc19ddfc 100644 --- a/src/telnyx/types/ai/assistants/version_update_params.py +++ b/src/telnyx/types/ai/assistants/version_update_params.py @@ -10,24 +10,19 @@ from ..assistant_tool_param import AssistantToolParam from ..voice_settings_param import VoiceSettingsParam 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_mcp_server_param import AssistantMcpServerParam -from ..assistant_integration_param import AssistantIntegrationParam from ..transcription_settings_param import TranscriptionSettingsParam -from ..post_conversation_settings_req_param import PostConversationSettingsReqParam -from ..inference_embedding_interruption_settings_param import InferenceEmbeddingInterruptionSettingsParam __all__ = [ "VersionUpdateParams", "ConversationFlow", "ConversationFlowNode", "ConversationFlowNodeFlowNodeReq", + "ConversationFlowNodeFlowNodeReqExternalLlm", "ConversationFlowNodeFlowNodeReqPosition", "ConversationFlowNodeToolNodeReq", "ConversationFlowNodeToolNodeReqPosition", @@ -47,6 +42,15 @@ "ConversationFlowEdgeTargetNodeTarget", "ConversationFlowEdgeTargetAssistantTarget", "ConversationFlowEdgeTargetAssistantTargetPosition", + "ExternalLlm", + "FallbackConfig", + "FallbackConfigExternalLlm", + "Integration", + "InterruptionSettings", + "InterruptionSettingsStartSpeakingPlan", + "InterruptionSettingsStartSpeakingPlanTranscriptionEndpointingPlan", + "McpServer", + "PostConversationSettings", ] @@ -88,9 +92,9 @@ class VersionUpdateParams(TypedDict, total=False): enabled_features: List[EnabledFeatures] - external_llm: ExternalLlmReqParam + external_llm: ExternalLlm - fallback_config: FallbackConfigReqParam + fallback_config: FallbackConfig greeting: str """Text that the assistant will use to start the conversation. @@ -111,7 +115,7 @@ class VersionUpdateParams(TypedDict, total=False): [dynamic variables](https://developers.telnyx.com/docs/inference/ai-assistants/dynamic-variables) """ - integrations: Iterable[AssistantIntegrationParam] + integrations: Iterable[Integration] """Connected integrations attached to the assistant. The catalog of available integrations is at `/ai/integrations`; the user's @@ -119,7 +123,7 @@ class VersionUpdateParams(TypedDict, total=False): references a catalog integration by `integration_id`. """ - interruption_settings: InferenceEmbeddingInterruptionSettingsParam + interruption_settings: InterruptionSettings """ Settings for interruptions and how the assistant decides the user has finished speaking. These timings are most relevant when using non turn-taking @@ -139,7 +143,7 @@ class VersionUpdateParams(TypedDict, total=False): are unlikely to work with this integration. """ - mcp_servers: Iterable[AssistantMcpServerParam] + mcp_servers: Iterable[McpServer] """MCP servers attached to the assistant. Create MCP servers with `/ai/mcp_servers`, then reference them by `id` here. @@ -161,7 +165,7 @@ class VersionUpdateParams(TypedDict, total=False): observability_settings: ObservabilityReqParam - post_conversation_settings: PostConversationSettingsReqParam + post_conversation_settings: PostConversationSettings """Configuration for post-conversation processing. When enabled, the assistant receives one additional LLM turn after the @@ -205,6 +209,47 @@ class VersionUpdateParams(TypedDict, total=False): """Configuration settings for the assistant's web widget.""" +class ConversationFlowNodeFlowNodeReqExternalLlm(TypedDict, total=False): + """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`, `base_url`, credentials). Part of the LLM bundle — see `model` for cascade semantics. Mutually exclusive with `model` on the node (a single LLM identity per node). + """ + + 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: Literal["token", "certificate"] + """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. + """ + + class ConversationFlowNodeFlowNodeReqPosition(TypedDict, total=False): """Optional canvas coordinates used by authoring UIs to lay out the graph. @@ -231,7 +276,7 @@ class ConversationFlowNodeFlowNodeReq(TypedDict, total=False): instructions: Required[str] """Prompt that drives the LLM while this node is active. Required.""" - external_llm: ExternalLlmReqParam + external_llm: ConversationFlowNodeFlowNodeReqExternalLlm """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`, @@ -632,3 +677,199 @@ class ConversationFlow(TypedDict, total=False): edges: Iterable[ConversationFlowEdge] """Directed transitions between nodes. May be empty for a single-node flow.""" + + +class ExternalLlm(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: Literal["token", "certificate"] + """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. + """ + + +class FallbackConfigExternalLlm(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: Literal["token", "certificate"] + """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. + """ + + +class FallbackConfig(TypedDict, total=False): + external_llm: FallbackConfigExternalLlm + + llm_api_key_ref: str + """Integration secret identifier for the fallback model API key.""" + + model: str + """ + Fallback Telnyx-hosted model to use when the primary LLM provider is + unavailable. + """ + + +class Integration(TypedDict, total=False): + """Reference to a connected integration attached to an assistant. + + Discover available integrations with `/ai/integrations` and connected integrations with `/ai/integrations/connections`. + """ + + integration_id: Required[str] + """Catalog integration ID to attach. + + This is the `id` from the integrations catalog at `/ai/integrations` (the same + value also appears as `integration_id` on entries returned by + `/ai/integrations/connections`). It is **not** the connection-level `id` from + `/ai/integrations/connections`. + """ + + allowed_list: SequenceNotStr[str] + """Optional per-assistant allowlist of integration tool names. + + When omitted or empty, all tools allowed by the connected integration are + available to the assistant. + """ + + +class InterruptionSettingsStartSpeakingPlanTranscriptionEndpointingPlan(TypedDict, total=False): + """Endpointing thresholds used to decide when the user has finished speaking. + + Applies to non turn-taking transcription models. For `deepgram/flux`, use `transcription.settings.eot_threshold` / `eot_timeout_ms` / `eager_eot_threshold`. + """ + + on_no_punctuation_seconds: float + """Seconds to wait after the transcript ends without punctuation.""" + + on_number_seconds: float + """Seconds to wait after the transcript ends with a number.""" + + on_punctuation_seconds: float + """Seconds to wait after the transcript ends with punctuation.""" + + +class InterruptionSettingsStartSpeakingPlan(TypedDict, total=False): + """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. + """ + + transcription_endpointing_plan: InterruptionSettingsStartSpeakingPlanTranscriptionEndpointingPlan + """Endpointing thresholds used to decide when the user has finished speaking. + + Applies to non turn-taking transcription models. For `deepgram/flux`, use + `transcription.settings.eot_threshold` / `eot_timeout_ms` / + `eager_eot_threshold`. + """ + + wait_seconds: float + """Minimum seconds to wait before the assistant starts speaking.""" + + +class InterruptionSettings(TypedDict, total=False): + """ + Settings for interruptions and how the assistant decides the user has finished speaking. These timings are most relevant when using non turn-taking transcription models. For turn-taking models like `deepgram/flux`, end-of-turn behavior is controlled by the transcription end-of-turn settings under `transcription.settings` (`eot_threshold`, `eot_timeout_ms`, `eager_eot_threshold`). + """ + + disable_greeting_interruption: bool + """When true, disables user interruptions while the assistant greeting is playing.""" + + enable: bool + """Whether users can interrupt the assistant while it is speaking.""" + + start_speaking_plan: InterruptionSettingsStartSpeakingPlan + """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. + """ + + +class McpServer(TypedDict, total=False): + """Reference to an MCP server attached to an assistant. + + Create and manage MCP servers with the `/ai/mcp_servers` endpoints, then attach them to assistants by ID. + """ + + id: Required[str] + """ID of the MCP server to attach. + + This must be the `id` of an MCP server returned by the `/ai/mcp_servers` + endpoints. + """ + + allowed_tools: SequenceNotStr[str] + """Optional per-assistant allowlist of MCP tool names. + + When omitted, the assistant uses the MCP server's configured `allowed_tools`. + """ + + +class PostConversationSettings(TypedDict, total=False): + """Configuration for post-conversation processing. + + When enabled, the assistant receives one additional LLM turn after the conversation ends, allowing it to execute tool calls such as logging to a CRM or sending a summary. The assistant can execute multiple parallel or sequential tools during this phase. Telephony-control tools (e.g. hangup, transfer) are unavailable post-conversation. Beta feature. + """ + + enabled: bool + """Whether post-conversation processing is enabled. + + When true, the assistant will be invoked after the conversation ends to perform + any final tool calls. Defaults to false. + """ diff --git a/src/telnyx/types/ai/external_llm.py b/src/telnyx/types/ai/external_llm.py deleted file mode 100644 index 36332eb5..00000000 --- a/src/telnyx/types/ai/external_llm.py +++ /dev/null @@ -1,44 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Optional -from typing_extensions import Literal - -from ..._models import BaseModel - -__all__ = ["ExternalLlm"] - - -class ExternalLlm(BaseModel): - base_url: str - """Base URL for the external LLM endpoint.""" - - model: str - """Model identifier to use with the external LLM endpoint.""" - - authentication_method: Optional[Literal["token", "certificate"]] = None - """Authentication method used when connecting to the external LLM endpoint.""" - - certificate_ref: Optional[str] = None - """ - Integration secret identifier for the client certificate used with certificate - authentication. - """ - - forward_metadata: Optional[bool] = None - """ - 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: Optional[str] = None - """Integration secret identifier for the external LLM API key.""" - - token_retrieval_url: Optional[str] = None - """ - URL used to retrieve an access token when certificate authentication is enabled. - """ diff --git a/src/telnyx/types/ai/external_llm_req_param.py b/src/telnyx/types/ai/external_llm_req_param.py deleted file mode 100644 index ea863952..00000000 --- a/src/telnyx/types/ai/external_llm_req_param.py +++ /dev/null @@ -1,43 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing_extensions import Literal, Required, TypedDict - -__all__ = ["ExternalLlmReqParam"] - - -class ExternalLlmReqParam(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: Literal["token", "certificate"] - """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. - """ diff --git a/src/telnyx/types/ai/fallback_config.py b/src/telnyx/types/ai/fallback_config.py deleted file mode 100644 index d929cec8..00000000 --- a/src/telnyx/types/ai/fallback_config.py +++ /dev/null @@ -1,21 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Optional - -from ..._models import BaseModel -from .external_llm import ExternalLlm - -__all__ = ["FallbackConfig"] - - -class FallbackConfig(BaseModel): - external_llm: Optional[ExternalLlm] = None - - llm_api_key_ref: Optional[str] = None - """Integration secret identifier for the fallback model API key.""" - - model: Optional[str] = None - """ - Fallback Telnyx-hosted model to use when the primary LLM provider is - unavailable. - """ diff --git a/src/telnyx/types/ai/fallback_config_req_param.py b/src/telnyx/types/ai/fallback_config_req_param.py deleted file mode 100644 index 69b14470..00000000 --- a/src/telnyx/types/ai/fallback_config_req_param.py +++ /dev/null @@ -1,22 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing_extensions import TypedDict - -from .external_llm_req_param import ExternalLlmReqParam - -__all__ = ["FallbackConfigReqParam"] - - -class FallbackConfigReqParam(TypedDict, total=False): - external_llm: ExternalLlmReqParam - - llm_api_key_ref: str - """Integration secret identifier for the fallback model API key.""" - - model: str - """ - Fallback Telnyx-hosted model to use when the primary LLM provider is - unavailable. - """ diff --git a/src/telnyx/types/ai/inference_embedding.py b/src/telnyx/types/ai/inference_embedding.py index a9fa32e1..8ef6cc2b 100644 --- a/src/telnyx/types/ai/inference_embedding.py +++ b/src/telnyx/types/ai/inference_embedding.py @@ -6,11 +6,9 @@ from ..._utils import PropertyInfo from ..._models import BaseModel -from .external_llm import ExternalLlm from .observability import Observability from .assistant_tool import AssistantTool from .voice_settings import VoiceSettings -from .fallback_config import FallbackConfig from .import_metadata import ImportMetadata from .widget_settings import WidgetSettings from .enabled_features import EnabledFeatures @@ -18,17 +16,14 @@ from .privacy_settings import PrivacySettings from .messaging_settings import MessagingSettings from .telephony_settings import TelephonySettings -from .assistant_mcp_server import AssistantMcpServer -from .assistant_integration import AssistantIntegration from .transcription_settings import TranscriptionSettings -from .post_conversation_settings import PostConversationSettings -from .inference_embedding_interruption_settings import InferenceEmbeddingInterruptionSettings __all__ = [ "InferenceEmbedding", "ConversationFlow", "ConversationFlowNode", "ConversationFlowNodeFlowNode", + "ConversationFlowNodeFlowNodeExternalLlm", "ConversationFlowNodeFlowNodePosition", "ConversationFlowNodeToolNode", "ConversationFlowNodeToolNodePosition", @@ -48,9 +43,59 @@ "ConversationFlowEdgeTargetNodeTarget", "ConversationFlowEdgeTargetAssistantTarget", "ConversationFlowEdgeTargetAssistantTargetPosition", + "ExternalLlm", + "FallbackConfig", + "FallbackConfigExternalLlm", + "Integration", + "InterruptionSettings", + "InterruptionSettingsStartSpeakingPlan", + "InterruptionSettingsStartSpeakingPlanTranscriptionEndpointingPlan", + "McpServer", + "PostConversationSettings", ] +class ConversationFlowNodeFlowNodeExternalLlm(BaseModel): + """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`, `base_url`, credentials). Part of the LLM bundle — see `model` for cascade semantics. Mutually exclusive with `model` on the node (a single LLM identity per node). + """ + + base_url: str + """Base URL for the external LLM endpoint.""" + + model: str + """Model identifier to use with the external LLM endpoint.""" + + authentication_method: Optional[Literal["token", "certificate"]] = None + """Authentication method used when connecting to the external LLM endpoint.""" + + certificate_ref: Optional[str] = None + """ + Integration secret identifier for the client certificate used with certificate + authentication. + """ + + forward_metadata: Optional[bool] = None + """ + 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: Optional[str] = None + """Integration secret identifier for the external LLM API key.""" + + token_retrieval_url: Optional[str] = None + """ + URL used to retrieve an access token when certificate authentication is enabled. + """ + + class ConversationFlowNodeFlowNodePosition(BaseModel): """Optional canvas coordinates used by authoring UIs to lay out the graph. @@ -73,7 +118,7 @@ class ConversationFlowNodeFlowNode(BaseModel): instructions: str """Prompt that drives the LLM while this node is active. Required.""" - external_llm: Optional[ExternalLlm] = None + external_llm: Optional[ConversationFlowNodeFlowNodeExternalLlm] = None """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`, @@ -465,6 +510,202 @@ class ConversationFlow(BaseModel): """Directed transitions between nodes.""" +class ExternalLlm(BaseModel): + base_url: str + """Base URL for the external LLM endpoint.""" + + model: str + """Model identifier to use with the external LLM endpoint.""" + + authentication_method: Optional[Literal["token", "certificate"]] = None + """Authentication method used when connecting to the external LLM endpoint.""" + + certificate_ref: Optional[str] = None + """ + Integration secret identifier for the client certificate used with certificate + authentication. + """ + + forward_metadata: Optional[bool] = None + """ + 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: Optional[str] = None + """Integration secret identifier for the external LLM API key.""" + + token_retrieval_url: Optional[str] = None + """ + URL used to retrieve an access token when certificate authentication is enabled. + """ + + +class FallbackConfigExternalLlm(BaseModel): + base_url: str + """Base URL for the external LLM endpoint.""" + + model: str + """Model identifier to use with the external LLM endpoint.""" + + authentication_method: Optional[Literal["token", "certificate"]] = None + """Authentication method used when connecting to the external LLM endpoint.""" + + certificate_ref: Optional[str] = None + """ + Integration secret identifier for the client certificate used with certificate + authentication. + """ + + forward_metadata: Optional[bool] = None + """ + 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: Optional[str] = None + """Integration secret identifier for the external LLM API key.""" + + token_retrieval_url: Optional[str] = None + """ + URL used to retrieve an access token when certificate authentication is enabled. + """ + + +class FallbackConfig(BaseModel): + external_llm: Optional[FallbackConfigExternalLlm] = None + + llm_api_key_ref: Optional[str] = None + """Integration secret identifier for the fallback model API key.""" + + model: Optional[str] = None + """ + Fallback Telnyx-hosted model to use when the primary LLM provider is + unavailable. + """ + + +class Integration(BaseModel): + """Reference to a connected integration attached to an assistant. + + Discover available integrations with `/ai/integrations` and connected integrations with `/ai/integrations/connections`. + """ + + integration_id: str + """Catalog integration ID to attach. + + This is the `id` from the integrations catalog at `/ai/integrations` (the same + value also appears as `integration_id` on entries returned by + `/ai/integrations/connections`). It is **not** the connection-level `id` from + `/ai/integrations/connections`. + """ + + allowed_list: Optional[List[str]] = None + """Optional per-assistant allowlist of integration tool names. + + When omitted or empty, all tools allowed by the connected integration are + available to the assistant. + """ + + +class InterruptionSettingsStartSpeakingPlanTranscriptionEndpointingPlan(BaseModel): + """Endpointing thresholds used to decide when the user has finished speaking. + + Applies to non turn-taking transcription models. For `deepgram/flux`, use `transcription.settings.eot_threshold` / `eot_timeout_ms` / `eager_eot_threshold`. + """ + + on_no_punctuation_seconds: Optional[float] = None + """Seconds to wait after the transcript ends without punctuation.""" + + on_number_seconds: Optional[float] = None + """Seconds to wait after the transcript ends with a number.""" + + on_punctuation_seconds: Optional[float] = None + """Seconds to wait after the transcript ends with punctuation.""" + + +class InterruptionSettingsStartSpeakingPlan(BaseModel): + """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. + """ + + transcription_endpointing_plan: Optional[InterruptionSettingsStartSpeakingPlanTranscriptionEndpointingPlan] = None + """Endpointing thresholds used to decide when the user has finished speaking. + + Applies to non turn-taking transcription models. For `deepgram/flux`, use + `transcription.settings.eot_threshold` / `eot_timeout_ms` / + `eager_eot_threshold`. + """ + + wait_seconds: Optional[float] = None + """Minimum seconds to wait before the assistant starts speaking.""" + + +class InterruptionSettings(BaseModel): + """ + Settings for interruptions and how the assistant decides the user has finished speaking. These timings are most relevant when using non turn-taking transcription models. For turn-taking models like `deepgram/flux`, end-of-turn behavior is controlled by the transcription end-of-turn settings under `transcription.settings` (`eot_threshold`, `eot_timeout_ms`, `eager_eot_threshold`). + """ + + disable_greeting_interruption: Optional[bool] = None + """When true, disables user interruptions while the assistant greeting is playing.""" + + enable: Optional[bool] = None + """Whether users can interrupt the assistant while it is speaking.""" + + start_speaking_plan: Optional[InterruptionSettingsStartSpeakingPlan] = None + """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. + """ + + +class McpServer(BaseModel): + """Reference to an MCP server attached to an assistant. + + Create and manage MCP servers with the `/ai/mcp_servers` endpoints, then attach them to assistants by ID. + """ + + id: str + """ID of the MCP server to attach. + + This must be the `id` of an MCP server returned by the `/ai/mcp_servers` + endpoints. + """ + + allowed_tools: Optional[List[str]] = None + """Optional per-assistant allowlist of MCP tool names. + + When omitted, the assistant uses the MCP server's configured `allowed_tools`. + """ + + +class PostConversationSettings(BaseModel): + """Configuration for post-conversation processing. + + When enabled, the assistant receives one additional LLM turn after the conversation ends, allowing it to execute tool calls such as logging to a CRM or sending a summary. The assistant can execute multiple parallel or sequential tools during this phase. Telephony-control tools (e.g. hangup, transfer) are unavailable post-conversation. Beta feature. + """ + + enabled: Optional[bool] = None + """Whether post-conversation processing is enabled. + + When true, the assistant will be invoked after the conversation ends to perform + any final tool calls. Defaults to false. + """ + + class InferenceEmbedding(BaseModel): id: str @@ -537,7 +778,7 @@ class InferenceEmbedding(BaseModel): insight_settings: Optional[InsightSettings] = None - integrations: Optional[List[AssistantIntegration]] = None + integrations: Optional[List[Integration]] = None """Connected integrations attached to the assistant. The catalog of available integrations is at `/ai/integrations`; the user's @@ -545,7 +786,7 @@ class InferenceEmbedding(BaseModel): references a catalog integration by `integration_id`. """ - interruption_settings: Optional[InferenceEmbeddingInterruptionSettings] = None + interruption_settings: Optional[InterruptionSettings] = None """ Settings for interruptions and how the assistant decides the user has finished speaking. These timings are most relevant when using non turn-taking @@ -565,7 +806,7 @@ class InferenceEmbedding(BaseModel): are unlikely to work with this integration. """ - mcp_servers: Optional[List[AssistantMcpServer]] = None + mcp_servers: Optional[List[McpServer]] = None """MCP servers attached to the assistant. Create MCP servers with `/ai/mcp_servers`, then reference them by `id` here. diff --git a/src/telnyx/types/ai/inference_embedding_interruption_settings.py b/src/telnyx/types/ai/inference_embedding_interruption_settings.py deleted file mode 100644 index b7a216ee..00000000 --- a/src/telnyx/types/ai/inference_embedding_interruption_settings.py +++ /dev/null @@ -1,28 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Optional - -from ..._models import BaseModel -from .start_speaking_plan import StartSpeakingPlan - -__all__ = ["InferenceEmbeddingInterruptionSettings"] - - -class InferenceEmbeddingInterruptionSettings(BaseModel): - """ - Settings for interruptions and how the assistant decides the user has finished speaking. These timings are most relevant when using non turn-taking transcription models. For turn-taking models like `deepgram/flux`, end-of-turn behavior is controlled by the transcription end-of-turn settings under `transcription.settings` (`eot_threshold`, `eot_timeout_ms`, `eager_eot_threshold`). - """ - - disable_greeting_interruption: Optional[bool] = None - """When true, disables user interruptions while the assistant greeting is playing.""" - - enable: Optional[bool] = None - """Whether users can interrupt the assistant while it is speaking.""" - - start_speaking_plan: Optional[StartSpeakingPlan] = None - """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. - """ diff --git a/src/telnyx/types/ai/inference_embedding_interruption_settings_param.py b/src/telnyx/types/ai/inference_embedding_interruption_settings_param.py deleted file mode 100644 index 25a9c767..00000000 --- a/src/telnyx/types/ai/inference_embedding_interruption_settings_param.py +++ /dev/null @@ -1,29 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing_extensions import TypedDict - -from .start_speaking_plan_param import StartSpeakingPlanParam - -__all__ = ["InferenceEmbeddingInterruptionSettingsParam"] - - -class InferenceEmbeddingInterruptionSettingsParam(TypedDict, total=False): - """ - Settings for interruptions and how the assistant decides the user has finished speaking. These timings are most relevant when using non turn-taking transcription models. For turn-taking models like `deepgram/flux`, end-of-turn behavior is controlled by the transcription end-of-turn settings under `transcription.settings` (`eot_threshold`, `eot_timeout_ms`, `eager_eot_threshold`). - """ - - disable_greeting_interruption: bool - """When true, disables user interruptions while the assistant greeting is playing.""" - - enable: bool - """Whether users can interrupt the assistant while it is speaking.""" - - 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. - """ diff --git a/src/telnyx/types/ai/openai_list_models_response.py b/src/telnyx/types/ai/openai_list_models_response.py index 6710b3cd..d3eb4b54 100644 --- a/src/telnyx/types/ai/openai_list_models_response.py +++ b/src/telnyx/types/ai/openai_list_models_response.py @@ -1,14 +1,130 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import List, Optional +from typing import Dict, List, Optional +from datetime import datetime +from typing_extensions import Literal from ..._models import BaseModel -from ..model_metadata import ModelMetadata -__all__ = ["OpenAIListModelsResponse"] +__all__ = ["OpenAIListModelsResponse", "Data"] + + +class Data(BaseModel): + """Metadata for a model available on Telnyx Inference. + + Returned by `GET /v2/ai/openai/models` (and the deprecated `GET /v2/ai/models`). Open-source models live under their Hugging Face organization (e.g. `moonshotai/Kimi-K2.6`, `zai-org/GLM-5.1-FP8`, `MiniMaxAI/MiniMax-M2.7`); fine-tuned models are owned by the Telnyx organization that trained them. + """ + + id: str + """Model identifier. + + For open-source models, follows the `{organization}/{model_name}` convention + from Hugging Face (e.g. `moonshotai/Kimi-K2.6`). + """ + + context_length: int + """ + Maximum total tokens (prompt + completion) supported by the model in a single + request. + """ + + created: datetime + """Timestamp at which the model was registered on Telnyx Inference (ISO 8601).""" + + languages: List[str] + """ISO language codes the model supports (e.g. `en`, `es`).""" + + license: str + """License the model is distributed under, e.g. + + `Apache 2.0`, `MIT`, `Llama 3 Community License`. + """ + + organization: str + """ + Organization that originally published the model, matching the prefix of `id` + for open-source models. + """ + + owned_by: str + """Owner of the model. + + `Telnyx` for Telnyx-hosted open-source models, the upstream provider name for + proxied models, or the Telnyx organization id for fine-tuned models. + """ + + parameters: int + """Total parameter count of the model.""" + + tier: Literal["small", "medium", "large", "unlisted"] + """Billing tier the model belongs to. + + Used together with `pricing` to determine cost per 1M tokens. + """ + + base_model: Optional[str] = None + """Base model the fine-tuned model was trained from. + + Only set for fine-tuned models. + """ + + description: Optional[str] = None + """Short, human-readable summary of what the model is best suited for.""" + + is_fine_tunable: Optional[bool] = None + """ + Whether the model can be used as a base for a fine-tuning job via + `POST /v2/ai/fine_tuning/jobs`. + """ + + is_vision_supported: Optional[bool] = None + """ + Whether the model accepts image inputs in chat completions (multimodal vision + support). + """ + + max_completion_tokens: Optional[int] = None + """Maximum number of completion (output) tokens the model will generate per + request. + + `null` if unconstrained beyond `context_length`. + """ + + object: Optional[str] = None + """Object type. Always `model`.""" + + parameters_str: Optional[str] = None + """Human-readable parameter count, e.g. `1.0T`, `753.9B`, `8B`.""" + + pricing: Optional[Dict[str, str]] = None + """Mapping of token kind to price, as strings to preserve precision. + + Typical keys are `prompt`, `cached_prompt`, and `completion`. When pricing is + available the block also includes `currency` (ISO 4217 code matching the + account's configured billing currency) and `unit` (the denomination the prices + are quoted in, currently always `1M_tokens` for token-priced models). + """ + + recommended_for_assistants: Optional[bool] = None + """ + Whether Telnyx currently recommends this model as the LLM powering a Telnyx AI + Assistant. + """ + + regions: Optional[List[str]] = None + """Public region names where the model is currently deployed (e.g. + + `us-central-1`, `eu-central-1`). + """ + + task: Optional[str] = None + """Primary task the model is intended for, e.g. + + `text-generation`, `audio-text-to-text`, `feature-extraction` (embeddings). + """ class OpenAIListModelsResponse(BaseModel): - data: List[ModelMetadata] + data: List[Data] object: Optional[str] = None diff --git a/src/telnyx/types/ai/post_conversation_settings.py b/src/telnyx/types/ai/post_conversation_settings.py deleted file mode 100644 index d26676d9..00000000 --- a/src/telnyx/types/ai/post_conversation_settings.py +++ /dev/null @@ -1,21 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Optional - -from ..._models import BaseModel - -__all__ = ["PostConversationSettings"] - - -class PostConversationSettings(BaseModel): - """Configuration for post-conversation processing. - - When enabled, the assistant receives one additional LLM turn after the conversation ends, allowing it to execute tool calls such as logging to a CRM or sending a summary. The assistant can execute multiple parallel or sequential tools during this phase. Telephony-control tools (e.g. hangup, transfer) are unavailable post-conversation. Beta feature. - """ - - enabled: Optional[bool] = None - """Whether post-conversation processing is enabled. - - When true, the assistant will be invoked after the conversation ends to perform - any final tool calls. Defaults to false. - """ diff --git a/src/telnyx/types/ai/post_conversation_settings_req_param.py b/src/telnyx/types/ai/post_conversation_settings_req_param.py deleted file mode 100644 index 1198ac71..00000000 --- a/src/telnyx/types/ai/post_conversation_settings_req_param.py +++ /dev/null @@ -1,21 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing_extensions import TypedDict - -__all__ = ["PostConversationSettingsReqParam"] - - -class PostConversationSettingsReqParam(TypedDict, total=False): - """Configuration for post-conversation processing. - - When enabled, the assistant receives one additional LLM turn after the conversation ends, allowing it to execute tool calls such as logging to a CRM or sending a summary. The assistant can execute multiple parallel or sequential tools during this phase. Telephony-control tools (e.g. hangup, transfer) are unavailable post-conversation. Beta feature. - """ - - enabled: bool - """Whether post-conversation processing is enabled. - - When true, the assistant will be invoked after the conversation ends to perform - any final tool calls. Defaults to false. - """ diff --git a/src/telnyx/types/ai/start_speaking_plan.py b/src/telnyx/types/ai/start_speaking_plan.py deleted file mode 100644 index 318e8b41..00000000 --- a/src/telnyx/types/ai/start_speaking_plan.py +++ /dev/null @@ -1,26 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Optional - -from ..._models import BaseModel -from .transcription_endpointing_plan import TranscriptionEndpointingPlan - -__all__ = ["StartSpeakingPlan"] - - -class StartSpeakingPlan(BaseModel): - """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. - """ - - transcription_endpointing_plan: Optional[TranscriptionEndpointingPlan] = None - """Endpointing thresholds used to decide when the user has finished speaking. - - Applies to non turn-taking transcription models. For `deepgram/flux`, use - `transcription.settings.eot_threshold` / `eot_timeout_ms` / - `eager_eot_threshold`. - """ - - wait_seconds: Optional[float] = None - """Minimum seconds to wait before the assistant starts speaking.""" diff --git a/src/telnyx/types/ai/start_speaking_plan_param.py b/src/telnyx/types/ai/start_speaking_plan_param.py deleted file mode 100644 index eddc939e..00000000 --- a/src/telnyx/types/ai/start_speaking_plan_param.py +++ /dev/null @@ -1,27 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing_extensions import TypedDict - -from .transcription_endpointing_plan_param import TranscriptionEndpointingPlanParam - -__all__ = ["StartSpeakingPlanParam"] - - -class StartSpeakingPlanParam(TypedDict, total=False): - """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. - """ - - 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 - `transcription.settings.eot_threshold` / `eot_timeout_ms` / - `eager_eot_threshold`. - """ - - wait_seconds: float - """Minimum seconds to wait before the assistant starts speaking.""" diff --git a/src/telnyx/types/ai/transcription_endpointing_plan.py b/src/telnyx/types/ai/transcription_endpointing_plan.py deleted file mode 100644 index b8db019b..00000000 --- a/src/telnyx/types/ai/transcription_endpointing_plan.py +++ /dev/null @@ -1,23 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Optional - -from ..._models import BaseModel - -__all__ = ["TranscriptionEndpointingPlan"] - - -class TranscriptionEndpointingPlan(BaseModel): - """Endpointing thresholds used to decide when the user has finished speaking. - - Applies to non turn-taking transcription models. For `deepgram/flux`, use `transcription.settings.eot_threshold` / `eot_timeout_ms` / `eager_eot_threshold`. - """ - - on_no_punctuation_seconds: Optional[float] = None - """Seconds to wait after the transcript ends without punctuation.""" - - on_number_seconds: Optional[float] = None - """Seconds to wait after the transcript ends with a number.""" - - on_punctuation_seconds: Optional[float] = None - """Seconds to wait after the transcript ends with punctuation.""" diff --git a/src/telnyx/types/ai/transcription_endpointing_plan_param.py b/src/telnyx/types/ai/transcription_endpointing_plan_param.py deleted file mode 100644 index 7cb66dc7..00000000 --- a/src/telnyx/types/ai/transcription_endpointing_plan_param.py +++ /dev/null @@ -1,23 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing_extensions import TypedDict - -__all__ = ["TranscriptionEndpointingPlanParam"] - - -class TranscriptionEndpointingPlanParam(TypedDict, total=False): - """Endpointing thresholds used to decide when the user has finished speaking. - - Applies to non turn-taking transcription models. For `deepgram/flux`, use `transcription.settings.eot_threshold` / `eot_timeout_ms` / `eager_eot_threshold`. - """ - - on_no_punctuation_seconds: float - """Seconds to wait after the transcript ends without punctuation.""" - - on_number_seconds: float - """Seconds to wait after the transcript ends with a number.""" - - on_punctuation_seconds: float - """Seconds to wait after the transcript ends with punctuation.""" diff --git a/src/telnyx/types/ai/transfer_tool_param.py b/src/telnyx/types/ai/transfer_tool_param.py index d8d95a8f..67d21b67 100644 --- a/src/telnyx/types/ai/transfer_tool_param.py +++ b/src/telnyx/types/ai/transfer_tool_param.py @@ -5,10 +5,10 @@ from typing import Union, Iterable from typing_extensions import Literal, Required, TypedDict -__all__ = ["TransferToolParam", "Transfer", "TransferTargetsTargetsList"] +__all__ = ["TransferToolParam", "Transfer", "TransferTargetsUnionMember0"] -class TransferTargetsTargetsList(TypedDict, total=False): +class TransferTargetsUnionMember0(TypedDict, total=False): to: Required[str] """The destination number or SIP URI of the call.""" @@ -26,7 +26,7 @@ class TransferTargetsTargetsList(TypedDict, total=False): class Transfer(_TransferReservedKeywords, total=False): - targets: Required[Union[Iterable[TransferTargetsTargetsList], str]] + targets: Required[Union[Iterable[TransferTargetsUnionMember0], str]] """The different possible targets of the transfer. The assistant will be able to choose one of the targets to transfer the call to. diff --git a/src/telnyx/types/ai_retrieve_models_response.py b/src/telnyx/types/ai_retrieve_models_response.py index db67e0f0..30331107 100644 --- a/src/telnyx/types/ai_retrieve_models_response.py +++ b/src/telnyx/types/ai_retrieve_models_response.py @@ -1,14 +1,130 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import List, Optional +from typing import Dict, List, Optional +from datetime import datetime +from typing_extensions import Literal from .._models import BaseModel -from .model_metadata import ModelMetadata -__all__ = ["AIRetrieveModelsResponse"] +__all__ = ["AIRetrieveModelsResponse", "Data"] + + +class Data(BaseModel): + """Metadata for a model available on Telnyx Inference. + + Returned by `GET /v2/ai/openai/models` (and the deprecated `GET /v2/ai/models`). Open-source models live under their Hugging Face organization (e.g. `moonshotai/Kimi-K2.6`, `zai-org/GLM-5.1-FP8`, `MiniMaxAI/MiniMax-M2.7`); fine-tuned models are owned by the Telnyx organization that trained them. + """ + + id: str + """Model identifier. + + For open-source models, follows the `{organization}/{model_name}` convention + from Hugging Face (e.g. `moonshotai/Kimi-K2.6`). + """ + + context_length: int + """ + Maximum total tokens (prompt + completion) supported by the model in a single + request. + """ + + created: datetime + """Timestamp at which the model was registered on Telnyx Inference (ISO 8601).""" + + languages: List[str] + """ISO language codes the model supports (e.g. `en`, `es`).""" + + license: str + """License the model is distributed under, e.g. + + `Apache 2.0`, `MIT`, `Llama 3 Community License`. + """ + + organization: str + """ + Organization that originally published the model, matching the prefix of `id` + for open-source models. + """ + + owned_by: str + """Owner of the model. + + `Telnyx` for Telnyx-hosted open-source models, the upstream provider name for + proxied models, or the Telnyx organization id for fine-tuned models. + """ + + parameters: int + """Total parameter count of the model.""" + + tier: Literal["small", "medium", "large", "unlisted"] + """Billing tier the model belongs to. + + Used together with `pricing` to determine cost per 1M tokens. + """ + + base_model: Optional[str] = None + """Base model the fine-tuned model was trained from. + + Only set for fine-tuned models. + """ + + description: Optional[str] = None + """Short, human-readable summary of what the model is best suited for.""" + + is_fine_tunable: Optional[bool] = None + """ + Whether the model can be used as a base for a fine-tuning job via + `POST /v2/ai/fine_tuning/jobs`. + """ + + is_vision_supported: Optional[bool] = None + """ + Whether the model accepts image inputs in chat completions (multimodal vision + support). + """ + + max_completion_tokens: Optional[int] = None + """Maximum number of completion (output) tokens the model will generate per + request. + + `null` if unconstrained beyond `context_length`. + """ + + object: Optional[str] = None + """Object type. Always `model`.""" + + parameters_str: Optional[str] = None + """Human-readable parameter count, e.g. `1.0T`, `753.9B`, `8B`.""" + + pricing: Optional[Dict[str, str]] = None + """Mapping of token kind to price, as strings to preserve precision. + + Typical keys are `prompt`, `cached_prompt`, and `completion`. When pricing is + available the block also includes `currency` (ISO 4217 code matching the + account's configured billing currency) and `unit` (the denomination the prices + are quoted in, currently always `1M_tokens` for token-priced models). + """ + + recommended_for_assistants: Optional[bool] = None + """ + Whether Telnyx currently recommends this model as the LLM powering a Telnyx AI + Assistant. + """ + + regions: Optional[List[str]] = None + """Public region names where the model is currently deployed (e.g. + + `us-central-1`, `eu-central-1`). + """ + + task: Optional[str] = None + """Primary task the model is intended for, e.g. + + `text-generation`, `audio-text-to-text`, `feature-extraction` (embeddings). + """ class AIRetrieveModelsResponse(BaseModel): - data: List[ModelMetadata] + data: List[Data] object: Optional[str] = None diff --git a/src/telnyx/types/billing_address.py b/src/telnyx/types/billing_address.py index 5253582e..2384e5bd 100644 --- a/src/telnyx/types/billing_address.py +++ b/src/telnyx/types/billing_address.py @@ -9,19 +9,15 @@ class BillingAddress(BaseModel): administrative_area: str - """State or province""" + """State or province code (e.g. `IL`, `ON`).""" city: str - """City name""" country: str - """Country name (e.g., United States)""" + """ISO 3166-1 alpha-2 code (currently `US` or `CA`).""" postal_code: str - """ZIP or postal code""" street_address: str - """Street address""" extended_address: Optional[str] = None - """Additional address line (suite, apt, etc.)""" diff --git a/src/telnyx/types/billing_address_param.py b/src/telnyx/types/billing_address_param.py index 075b2663..db99536f 100644 --- a/src/telnyx/types/billing_address_param.py +++ b/src/telnyx/types/billing_address_param.py @@ -10,19 +10,15 @@ class BillingAddressParam(TypedDict, total=False): administrative_area: Required[str] - """State or province""" + """State or province code (e.g. `IL`, `ON`).""" city: Required[str] - """City name""" country: Required[str] - """Country name (e.g., United States)""" + """ISO 3166-1 alpha-2 code (currently `US` or `CA`).""" postal_code: Required[str] - """ZIP or postal code""" street_address: Required[str] - """Street address""" extended_address: Optional[str] - """Additional address line (suite, apt, etc.)""" diff --git a/src/telnyx/types/billing_contact.py b/src/telnyx/types/billing_contact.py index 88da12be..904a223f 100644 --- a/src/telnyx/types/billing_contact.py +++ b/src/telnyx/types/billing_contact.py @@ -7,13 +7,10 @@ class BillingContact(BaseModel): email: str - """Contact's email address""" first_name: str - """Contact's first name""" last_name: str - """Contact's last name""" phone_number: str - """Contact's phone number (10-15 digits)""" + """E.164 format with leading `+`.""" diff --git a/src/telnyx/types/billing_contact_param.py b/src/telnyx/types/billing_contact_param.py index 5bee10ba..bbe2c83f 100644 --- a/src/telnyx/types/billing_contact_param.py +++ b/src/telnyx/types/billing_contact_param.py @@ -9,13 +9,10 @@ class BillingContactParam(TypedDict, total=False): email: Required[str] - """Contact's email address""" first_name: Required[str] - """Contact's first name""" last_name: Required[str] - """Contact's last name""" phone_number: Required[str] - """Contact's phone number (10-15 digits)""" + """E.164 format with leading `+`.""" diff --git a/src/telnyx/types/call_dial_params.py b/src/telnyx/types/call_dial_params.py index 002139c4..f8f2bf1d 100644 --- a/src/telnyx/types/call_dial_params.py +++ b/src/telnyx/types/call_dial_params.py @@ -16,7 +16,6 @@ from .stream_bidirectional_codec import StreamBidirectionalCodec from .call_assistant_request_param import CallAssistantRequestParam from .calls.aws_voice_settings_param import AwsVoiceSettingsParam -from .shared_params.xai_voice_settings import XaiVoiceSettings from .stream_bidirectional_target_legs import StreamBidirectionalTargetLegs from .calls.telnyx_voice_settings_param import TelnyxVoiceSettingsParam from .shared_params.rime_voice_settings import RimeVoiceSettings @@ -36,8 +35,10 @@ "ConversationRelayConfigLanguage", "ConversationRelayConfigLanguageVoiceSettings", "ConversationRelayConfigLanguageVoiceSettingsInworldVoiceSettings", + "ConversationRelayConfigLanguageVoiceSettingsXaiVoiceSettings", "ConversationRelayConfigVoiceSettings", "ConversationRelayConfigVoiceSettingsInworldVoiceSettings", + "ConversationRelayConfigVoiceSettingsXaiVoiceSettings", "DeepfakeDetection", "WebhookRetriesPolicies", ] @@ -604,6 +605,14 @@ class ConversationRelayConfigLanguageVoiceSettingsInworldVoiceSettings(TypedDict """Voice settings provider type""" +class ConversationRelayConfigLanguageVoiceSettingsXaiVoiceSettings(TypedDict, total=False): + type: Required[Literal["xai"]] + """Voice settings provider type""" + + language: str + """Language code, or `auto` to detect automatically.""" + + ConversationRelayConfigLanguageVoiceSettings: TypeAlias = Union[ ElevenLabsVoiceSettingsParam, TelnyxVoiceSettingsParam, @@ -613,7 +622,7 @@ class ConversationRelayConfigLanguageVoiceSettingsInworldVoiceSettings(TypedDict RimeVoiceSettings, ResembleVoiceSettings, ConversationRelayConfigLanguageVoiceSettingsInworldVoiceSettings, - XaiVoiceSettings, + ConversationRelayConfigLanguageVoiceSettingsXaiVoiceSettings, ] @@ -673,6 +682,14 @@ class ConversationRelayConfigVoiceSettingsInworldVoiceSettings(TypedDict, total= """Voice settings provider type""" +class ConversationRelayConfigVoiceSettingsXaiVoiceSettings(TypedDict, total=False): + type: Required[Literal["xai"]] + """Voice settings provider type""" + + language: str + """Language code, or `auto` to detect automatically.""" + + ConversationRelayConfigVoiceSettings: TypeAlias = Union[ ElevenLabsVoiceSettingsParam, TelnyxVoiceSettingsParam, @@ -682,7 +699,7 @@ class ConversationRelayConfigVoiceSettingsInworldVoiceSettings(TypedDict, total= RimeVoiceSettings, ResembleVoiceSettings, ConversationRelayConfigVoiceSettingsInworldVoiceSettings, - XaiVoiceSettings, + ConversationRelayConfigVoiceSettingsXaiVoiceSettings, ] diff --git a/src/telnyx/types/call_reason_list_params.py b/src/telnyx/types/call_reason_list_params.py new file mode 100644 index 00000000..911d8730 --- /dev/null +++ b/src/telnyx/types/call_reason_list_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_extensions import Annotated, TypedDict + +from .._utils import PropertyInfo + +__all__ = ["CallReasonListParams"] + + +class CallReasonListParams(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. + + Default `100` for this endpoint (the call-reason library is small and most + callers want the whole list in one call). Maximum 250; values above are clamped + to 250. + """ diff --git a/src/telnyx/types/call_reason_list_response.py b/src/telnyx/types/call_reason_list_response.py new file mode 100644 index 00000000..16f098a0 --- /dev/null +++ b/src/telnyx/types/call_reason_list_response.py @@ -0,0 +1,17 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional + +from .._models import BaseModel + +__all__ = ["CallReasonListResponse"] + + +class CallReasonListResponse(BaseModel): + """Pre-vetted call-reason library entry.""" + + id: Optional[str] = None + + description: Optional[str] = None + + reason: Optional[str] = None diff --git a/src/telnyx/types/call_reason_validate_params.py b/src/telnyx/types/call_reason_validate_params.py new file mode 100644 index 00000000..519ea332 --- /dev/null +++ b/src/telnyx/types/call_reason_validate_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 Required, TypedDict + +from .._types import SequenceNotStr + +__all__ = ["CallReasonValidateParams"] + + +class CallReasonValidateParams(TypedDict, total=False): + body: Required[SequenceNotStr[str]] + """ + **Bare JSON array** of candidate call-reason strings (NOT an object — there is + no top-level `call_reasons` key on this endpoint). 1–10 strings, each ≤64 + characters. + """ diff --git a/src/telnyx/types/call_reason_validate_response.py b/src/telnyx/types/call_reason_validate_response.py new file mode 100644 index 00000000..e6d9bd46 --- /dev/null +++ b/src/telnyx/types/call_reason_validate_response.py @@ -0,0 +1,33 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List + +from .._models import BaseModel + +__all__ = ["CallReasonValidateResponse", "Data"] + + +class Data(BaseModel): + all_pre_approved: bool + """ + `true` when every supplied reason matches a pre-vetted entry in the call-reason + library. When `true`, the DIR will sail through the call-reasons portion of + vetting. + """ + + non_approved_reasons: List[str] + """Subset of the input that does NOT match the pre-vetted library. + + The DIR can still be submitted with these — they will go through manual review. + """ + + requires_manual_vetting: bool + """`true` when at least one supplied reason is in `non_approved_reasons`. + + Equivalent to `non_approved_reasons.length > 0` and the inverse of + `all_pre_approved`. + """ + + +class CallReasonValidateResponse(BaseModel): + data: Data diff --git a/src/telnyx/types/calls/__init__.py b/src/telnyx/types/calls/__init__.py index 16251b0a..42cb8b84 100644 --- a/src/telnyx/types/calls/__init__.py +++ b/src/telnyx/types/calls/__init__.py @@ -92,9 +92,6 @@ from .action_stop_conversation_relay_params import ( ActionStopConversationRelayParams as ActionStopConversationRelayParams, ) -from .transcription_engine_xai_config_param import ( - TranscriptionEngineXaiConfigParam as TranscriptionEngineXaiConfigParam, -) from .action_start_conversation_relay_params import ( ActionStartConversationRelayParams as ActionStartConversationRelayParams, ) @@ -128,9 +125,6 @@ from .action_add_ai_assistant_messages_response import ( ActionAddAIAssistantMessagesResponse as ActionAddAIAssistantMessagesResponse, ) -from .transcription_engine_assemblyai_config_param import ( - TranscriptionEngineAssemblyaiConfigParam as TranscriptionEngineAssemblyaiConfigParam, -) from .call_control_command_result_with_conversation_id import ( CallControlCommandResultWithConversationID as CallControlCommandResultWithConversationID, ) diff --git a/src/telnyx/types/calls/action_answer_params.py b/src/telnyx/types/calls/action_answer_params.py index 24526519..399b89b3 100644 --- a/src/telnyx/types/calls/action_answer_params.py +++ b/src/telnyx/types/calls/action_answer_params.py @@ -15,7 +15,6 @@ from .telnyx_voice_settings_param import TelnyxVoiceSettingsParam from ..call_assistant_request_param import CallAssistantRequestParam from .eleven_labs_voice_settings_param import ElevenLabsVoiceSettingsParam -from ..shared_params.xai_voice_settings import XaiVoiceSettings from ..stream_bidirectional_target_legs import StreamBidirectionalTargetLegs from .transcription_start_request_param import TranscriptionStartRequestParam from ..shared_params.rime_voice_settings import RimeVoiceSettings @@ -30,8 +29,10 @@ "ConversationRelayConfigLanguage", "ConversationRelayConfigLanguageVoiceSettings", "ConversationRelayConfigLanguageVoiceSettingsInworldVoiceSettings", + "ConversationRelayConfigLanguageVoiceSettingsXaiVoiceSettings", "ConversationRelayConfigVoiceSettings", "ConversationRelayConfigVoiceSettingsInworldVoiceSettings", + "ConversationRelayConfigVoiceSettingsXaiVoiceSettings", "DeepfakeDetection", "WebhookRetriesPolicies", ] @@ -249,6 +250,14 @@ class ConversationRelayConfigLanguageVoiceSettingsInworldVoiceSettings(TypedDict """Voice settings provider type""" +class ConversationRelayConfigLanguageVoiceSettingsXaiVoiceSettings(TypedDict, total=False): + type: Required[Literal["xai"]] + """Voice settings provider type""" + + language: str + """Language code, or `auto` to detect automatically.""" + + ConversationRelayConfigLanguageVoiceSettings: TypeAlias = Union[ ElevenLabsVoiceSettingsParam, TelnyxVoiceSettingsParam, @@ -258,7 +267,7 @@ class ConversationRelayConfigLanguageVoiceSettingsInworldVoiceSettings(TypedDict RimeVoiceSettings, ResembleVoiceSettings, ConversationRelayConfigLanguageVoiceSettingsInworldVoiceSettings, - XaiVoiceSettings, + ConversationRelayConfigLanguageVoiceSettingsXaiVoiceSettings, ] @@ -318,6 +327,14 @@ class ConversationRelayConfigVoiceSettingsInworldVoiceSettings(TypedDict, total= """Voice settings provider type""" +class ConversationRelayConfigVoiceSettingsXaiVoiceSettings(TypedDict, total=False): + type: Required[Literal["xai"]] + """Voice settings provider type""" + + language: str + """Language code, or `auto` to detect automatically.""" + + ConversationRelayConfigVoiceSettings: TypeAlias = Union[ ElevenLabsVoiceSettingsParam, TelnyxVoiceSettingsParam, @@ -327,7 +344,7 @@ class ConversationRelayConfigVoiceSettingsInworldVoiceSettings(TypedDict, total= RimeVoiceSettings, ResembleVoiceSettings, ConversationRelayConfigVoiceSettingsInworldVoiceSettings, - XaiVoiceSettings, + ConversationRelayConfigVoiceSettingsXaiVoiceSettings, ] 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 7441288a..b50c83d5 100644 --- a/src/telnyx/types/calls/action_gather_using_ai_params.py +++ b/src/telnyx/types/calls/action_gather_using_ai_params.py @@ -12,12 +12,11 @@ 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.rime_voice_settings import RimeVoiceSettings from ..shared_params.azure_voice_settings import AzureVoiceSettings from ..shared_params.resemble_voice_settings import ResembleVoiceSettings -__all__ = ["ActionGatherUsingAIParams", "MessageHistory", "VoiceSettings"] +__all__ = ["ActionGatherUsingAIParams", "MessageHistory", "VoiceSettings", "VoiceSettingsXaiVoiceSettings"] class ActionGatherUsingAIParams(TypedDict, total=False): @@ -143,6 +142,14 @@ class MessageHistory(TypedDict, total=False): """The role of the message sender""" +class VoiceSettingsXaiVoiceSettings(TypedDict, total=False): + type: Required[Literal["xai"]] + """Voice settings provider type""" + + language: str + """Language code, or `auto` to detect automatically.""" + + VoiceSettings: TypeAlias = Union[ ElevenLabsVoiceSettingsParam, TelnyxVoiceSettingsParam, @@ -150,5 +157,5 @@ class MessageHistory(TypedDict, total=False): AzureVoiceSettings, RimeVoiceSettings, ResembleVoiceSettings, - XaiVoiceSettings, + VoiceSettingsXaiVoiceSettings, ] 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 6d0cc32d..9d2de400 100644 --- a/src/telnyx/types/calls/action_gather_using_speak_params.py +++ b/src/telnyx/types/calls/action_gather_using_speak_params.py @@ -8,13 +8,17 @@ from .aws_voice_settings_param import AwsVoiceSettingsParam 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.rime_voice_settings import RimeVoiceSettings from ..shared_params.azure_voice_settings import AzureVoiceSettings from ..shared_params.minimax_voice_settings import MinimaxVoiceSettings from ..shared_params.resemble_voice_settings import ResembleVoiceSettings -__all__ = ["ActionGatherUsingSpeakParams", "VoiceSettings", "VoiceSettingsInworldVoiceSettings"] +__all__ = [ + "ActionGatherUsingSpeakParams", + "VoiceSettings", + "VoiceSettingsInworldVoiceSettings", + "VoiceSettingsXaiVoiceSettings", +] class ActionGatherUsingSpeakParams(TypedDict, total=False): @@ -180,6 +184,14 @@ class VoiceSettingsInworldVoiceSettings(TypedDict, total=False): """Voice settings provider type""" +class VoiceSettingsXaiVoiceSettings(TypedDict, total=False): + type: Required[Literal["xai"]] + """Voice settings provider type""" + + language: str + """Language code, or `auto` to detect automatically.""" + + VoiceSettings: TypeAlias = Union[ ElevenLabsVoiceSettingsParam, TelnyxVoiceSettingsParam, @@ -189,5 +201,5 @@ class VoiceSettingsInworldVoiceSettings(TypedDict, total=False): RimeVoiceSettings, ResembleVoiceSettings, VoiceSettingsInworldVoiceSettings, - XaiVoiceSettings, + VoiceSettingsXaiVoiceSettings, ] diff --git a/src/telnyx/types/calls/action_speak_params.py b/src/telnyx/types/calls/action_speak_params.py index 3d1629e1..b2f34204 100644 --- a/src/telnyx/types/calls/action_speak_params.py +++ b/src/telnyx/types/calls/action_speak_params.py @@ -9,13 +9,12 @@ from .aws_voice_settings_param import AwsVoiceSettingsParam 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.rime_voice_settings import RimeVoiceSettings from ..shared_params.azure_voice_settings import AzureVoiceSettings from ..shared_params.minimax_voice_settings import MinimaxVoiceSettings from ..shared_params.resemble_voice_settings import ResembleVoiceSettings -__all__ = ["ActionSpeakParams", "VoiceSettings", "VoiceSettingsInworldVoiceSettings"] +__all__ = ["ActionSpeakParams", "VoiceSettings", "VoiceSettingsInworldVoiceSettings", "VoiceSettingsXaiVoiceSettings"] class ActionSpeakParams(TypedDict, total=False): @@ -158,6 +157,14 @@ class VoiceSettingsInworldVoiceSettings(TypedDict, total=False): """Voice settings provider type""" +class VoiceSettingsXaiVoiceSettings(TypedDict, total=False): + type: Required[Literal["xai"]] + """Voice settings provider type""" + + language: str + """Language code, or `auto` to detect automatically.""" + + VoiceSettings: TypeAlias = Union[ ElevenLabsVoiceSettingsParam, TelnyxVoiceSettingsParam, @@ -167,5 +174,5 @@ class VoiceSettingsInworldVoiceSettings(TypedDict, total=False): RimeVoiceSettings, ResembleVoiceSettings, VoiceSettingsInworldVoiceSettings, - XaiVoiceSettings, + VoiceSettingsXaiVoiceSettings, ] 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 87a41a79..b00900db 100644 --- a/src/telnyx/types/calls/action_start_ai_assistant_params.py +++ b/src/telnyx/types/calls/action_start_ai_assistant_params.py @@ -11,7 +11,6 @@ from .telnyx_voice_settings_param import TelnyxVoiceSettingsParam from ..call_assistant_request_param import CallAssistantRequestParam from .eleven_labs_voice_settings_param import ElevenLabsVoiceSettingsParam -from ..shared_params.xai_voice_settings import XaiVoiceSettings from ..shared_params.rime_voice_settings import RimeVoiceSettings from ..shared_params.azure_voice_settings import AzureVoiceSettings from ..shared_params.resemble_voice_settings import ResembleVoiceSettings @@ -28,6 +27,7 @@ "MessageHistoryDeveloperMessage", "Participant", "VoiceSettings", + "VoiceSettingsXaiVoiceSettings", ] @@ -235,6 +235,14 @@ class Participant(TypedDict, total=False): """Determines what happens to the conversation when this participant hangs up.""" +class VoiceSettingsXaiVoiceSettings(TypedDict, total=False): + type: Required[Literal["xai"]] + """Voice settings provider type""" + + language: str + """Language code, or `auto` to detect automatically.""" + + VoiceSettings: TypeAlias = Union[ ElevenLabsVoiceSettingsParam, TelnyxVoiceSettingsParam, @@ -242,5 +250,5 @@ class Participant(TypedDict, total=False): AzureVoiceSettings, RimeVoiceSettings, ResembleVoiceSettings, - XaiVoiceSettings, + VoiceSettingsXaiVoiceSettings, ] 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 b92342e0..f303b736 100644 --- a/src/telnyx/types/calls/action_start_conversation_relay_params.py +++ b/src/telnyx/types/calls/action_start_conversation_relay_params.py @@ -8,7 +8,6 @@ from .aws_voice_settings_param import AwsVoiceSettingsParam 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.rime_voice_settings import RimeVoiceSettings from ..shared_params.azure_voice_settings import AzureVoiceSettings from ..shared_params.minimax_voice_settings import MinimaxVoiceSettings @@ -21,12 +20,15 @@ "ConversationRelaySettingsLanguage", "ConversationRelaySettingsLanguageVoiceSettings", "ConversationRelaySettingsLanguageVoiceSettingsInworldVoiceSettings", + "ConversationRelaySettingsLanguageVoiceSettingsXaiVoiceSettings", "InterruptionSettings", "Language", "LanguageVoiceSettings", "LanguageVoiceSettingsInworldVoiceSettings", + "LanguageVoiceSettingsXaiVoiceSettings", "VoiceSettings", "VoiceSettingsInworldVoiceSettings", + "VoiceSettingsXaiVoiceSettings", ] @@ -208,6 +210,14 @@ class ConversationRelaySettingsLanguageVoiceSettingsInworldVoiceSettings(TypedDi """Voice settings provider type""" +class ConversationRelaySettingsLanguageVoiceSettingsXaiVoiceSettings(TypedDict, total=False): + type: Required[Literal["xai"]] + """Voice settings provider type""" + + language: str + """Language code, or `auto` to detect automatically.""" + + ConversationRelaySettingsLanguageVoiceSettings: TypeAlias = Union[ ElevenLabsVoiceSettingsParam, TelnyxVoiceSettingsParam, @@ -217,7 +227,7 @@ class ConversationRelaySettingsLanguageVoiceSettingsInworldVoiceSettings(TypedDi RimeVoiceSettings, ResembleVoiceSettings, ConversationRelaySettingsLanguageVoiceSettingsInworldVoiceSettings, - XaiVoiceSettings, + ConversationRelaySettingsLanguageVoiceSettingsXaiVoiceSettings, ] @@ -342,6 +352,14 @@ class LanguageVoiceSettingsInworldVoiceSettings(TypedDict, total=False): """Voice settings provider type""" +class LanguageVoiceSettingsXaiVoiceSettings(TypedDict, total=False): + type: Required[Literal["xai"]] + """Voice settings provider type""" + + language: str + """Language code, or `auto` to detect automatically.""" + + LanguageVoiceSettings: TypeAlias = Union[ ElevenLabsVoiceSettingsParam, TelnyxVoiceSettingsParam, @@ -351,7 +369,7 @@ class LanguageVoiceSettingsInworldVoiceSettings(TypedDict, total=False): RimeVoiceSettings, ResembleVoiceSettings, LanguageVoiceSettingsInworldVoiceSettings, - XaiVoiceSettings, + LanguageVoiceSettingsXaiVoiceSettings, ] @@ -411,6 +429,14 @@ class VoiceSettingsInworldVoiceSettings(TypedDict, total=False): """Voice settings provider type""" +class VoiceSettingsXaiVoiceSettings(TypedDict, total=False): + type: Required[Literal["xai"]] + """Voice settings provider type""" + + language: str + """Language code, or `auto` to detect automatically.""" + + VoiceSettings: TypeAlias = Union[ ElevenLabsVoiceSettingsParam, TelnyxVoiceSettingsParam, @@ -420,5 +446,5 @@ class VoiceSettingsInworldVoiceSettings(TypedDict, total=False): RimeVoiceSettings, ResembleVoiceSettings, VoiceSettingsInworldVoiceSettings, - XaiVoiceSettings, + VoiceSettingsXaiVoiceSettings, ] diff --git a/src/telnyx/types/calls/action_start_transcription_params.py b/src/telnyx/types/calls/action_start_transcription_params.py index fb113b5f..a665fbf6 100644 --- a/src/telnyx/types/calls/action_start_transcription_params.py +++ b/src/telnyx/types/calls/action_start_transcription_params.py @@ -9,15 +9,15 @@ 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_google_config_param import TranscriptionEngineGoogleConfigParam from .transcription_engine_telnyx_config_param import TranscriptionEngineTelnyxConfigParam -from .transcription_engine_assemblyai_config_param import TranscriptionEngineAssemblyaiConfigParam __all__ = [ "ActionStartTranscriptionParams", "TranscriptionEngineConfig", + "TranscriptionEngineConfigTranscriptionEngineXaiConfig", + "TranscriptionEngineConfigTranscriptionEngineAssemblyaiConfig", "TranscriptionEngineConfigTranscriptionEngineSpeechmaticsConfig", "TranscriptionEngineConfigTranscriptionEngineSonioxConfig", ] @@ -56,6 +56,63 @@ class ActionStartTranscriptionParams(TypedDict, total=False): """ +class TranscriptionEngineConfigTranscriptionEngineXaiConfig(TypedDict, total=False): + interim_results: bool + """Whether to send also interim results. + + If set to false, only final results will be sent. + """ + + language: Literal[ + "ar", + "cs", + "da", + "de", + "en", + "es", + "fa", + "fil", + "fr", + "hi", + "id", + "it", + "ja", + "ko", + "mk", + "ms", + "nl", + "pl", + "pt", + "ro", + "ru", + "sv", + "th", + "tr", + "vi", + ] + """Language to use for speech recognition""" + + transcription_engine: Literal["xAI"] + """Engine identifier for xAI transcription service""" + + transcription_model: Literal["xai/grok-stt"] + """The model to use for transcription.""" + + +class TranscriptionEngineConfigTranscriptionEngineAssemblyaiConfig(TypedDict, total=False): + interim_results: bool + """Whether to send also interim results. + + If set to false, only final results will be sent. + """ + + transcription_engine: Literal["AssemblyAI"] + """Engine identifier for AssemblyAI transcription service""" + + transcription_model: Literal["assemblyai/universal-streaming"] + """The model to use for transcription.""" + + class TranscriptionEngineConfigTranscriptionEngineSpeechmaticsConfig(TypedDict, total=False): interim_results: bool """Whether to send also interim results. @@ -128,8 +185,8 @@ class TranscriptionEngineConfigTranscriptionEngineSonioxConfig(TypedDict, total= TranscriptionEngineGoogleConfigParam, TranscriptionEngineTelnyxConfigParam, TranscriptionEngineAzureConfigParam, - TranscriptionEngineXaiConfigParam, - TranscriptionEngineAssemblyaiConfigParam, + TranscriptionEngineConfigTranscriptionEngineXaiConfig, + TranscriptionEngineConfigTranscriptionEngineAssemblyaiConfig, TranscriptionEngineConfigTranscriptionEngineSpeechmaticsConfig, TranscriptionEngineConfigTranscriptionEngineSonioxConfig, TranscriptionEngineAConfigParam, diff --git a/src/telnyx/types/calls/transcription_engine_assemblyai_config_param.py b/src/telnyx/types/calls/transcription_engine_assemblyai_config_param.py deleted file mode 100644 index b5f62f19..00000000 --- a/src/telnyx/types/calls/transcription_engine_assemblyai_config_param.py +++ /dev/null @@ -1,21 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing_extensions import Literal, TypedDict - -__all__ = ["TranscriptionEngineAssemblyaiConfigParam"] - - -class TranscriptionEngineAssemblyaiConfigParam(TypedDict, total=False): - interim_results: bool - """Whether to send also interim results. - - If set to false, only final results will be sent. - """ - - transcription_engine: Literal["AssemblyAI"] - """Engine identifier for AssemblyAI transcription service""" - - transcription_model: Literal["assemblyai/universal-streaming"] - """The model to use for transcription.""" diff --git a/src/telnyx/types/calls/transcription_engine_xai_config_param.py b/src/telnyx/types/calls/transcription_engine_xai_config_param.py deleted file mode 100644 index 66256ff0..00000000 --- a/src/telnyx/types/calls/transcription_engine_xai_config_param.py +++ /dev/null @@ -1,50 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing_extensions import Literal, TypedDict - -__all__ = ["TranscriptionEngineXaiConfigParam"] - - -class TranscriptionEngineXaiConfigParam(TypedDict, total=False): - interim_results: bool - """Whether to send also interim results. - - If set to false, only final results will be sent. - """ - - language: Literal[ - "ar", - "cs", - "da", - "de", - "en", - "es", - "fa", - "fil", - "fr", - "hi", - "id", - "it", - "ja", - "ko", - "mk", - "ms", - "nl", - "pl", - "pt", - "ro", - "ru", - "sv", - "th", - "tr", - "vi", - ] - """Language to use for speech recognition""" - - transcription_engine: Literal["xAI"] - """Engine identifier for xAI transcription service""" - - transcription_model: Literal["xai/grok-stt"] - """The model to use for transcription.""" diff --git a/src/telnyx/types/calls/transcription_start_request_param.py b/src/telnyx/types/calls/transcription_start_request_param.py index 8b6e8ce5..d52231be 100644 --- a/src/telnyx/types/calls/transcription_start_request_param.py +++ b/src/telnyx/types/calls/transcription_start_request_param.py @@ -9,20 +9,77 @@ 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_google_config_param import TranscriptionEngineGoogleConfigParam from .transcription_engine_telnyx_config_param import TranscriptionEngineTelnyxConfigParam -from .transcription_engine_assemblyai_config_param import TranscriptionEngineAssemblyaiConfigParam __all__ = [ "TranscriptionStartRequestParam", "TranscriptionEngineConfig", + "TranscriptionEngineConfigTranscriptionEngineXaiConfig", + "TranscriptionEngineConfigTranscriptionEngineAssemblyaiConfig", "TranscriptionEngineConfigTranscriptionEngineSpeechmaticsConfig", "TranscriptionEngineConfigTranscriptionEngineSonioxConfig", ] +class TranscriptionEngineConfigTranscriptionEngineXaiConfig(TypedDict, total=False): + interim_results: bool + """Whether to send also interim results. + + If set to false, only final results will be sent. + """ + + language: Literal[ + "ar", + "cs", + "da", + "de", + "en", + "es", + "fa", + "fil", + "fr", + "hi", + "id", + "it", + "ja", + "ko", + "mk", + "ms", + "nl", + "pl", + "pt", + "ro", + "ru", + "sv", + "th", + "tr", + "vi", + ] + """Language to use for speech recognition""" + + transcription_engine: Literal["xAI"] + """Engine identifier for xAI transcription service""" + + transcription_model: Literal["xai/grok-stt"] + """The model to use for transcription.""" + + +class TranscriptionEngineConfigTranscriptionEngineAssemblyaiConfig(TypedDict, total=False): + interim_results: bool + """Whether to send also interim results. + + If set to false, only final results will be sent. + """ + + transcription_engine: Literal["AssemblyAI"] + """Engine identifier for AssemblyAI transcription service""" + + transcription_model: Literal["assemblyai/universal-streaming"] + """The model to use for transcription.""" + + class TranscriptionEngineConfigTranscriptionEngineSpeechmaticsConfig(TypedDict, total=False): interim_results: bool """Whether to send also interim results. @@ -95,8 +152,8 @@ class TranscriptionEngineConfigTranscriptionEngineSonioxConfig(TypedDict, total= TranscriptionEngineGoogleConfigParam, TranscriptionEngineTelnyxConfigParam, TranscriptionEngineAzureConfigParam, - TranscriptionEngineXaiConfigParam, - TranscriptionEngineAssemblyaiConfigParam, + TranscriptionEngineConfigTranscriptionEngineXaiConfig, + TranscriptionEngineConfigTranscriptionEngineAssemblyaiConfig, TranscriptionEngineConfigTranscriptionEngineSpeechmaticsConfig, TranscriptionEngineConfigTranscriptionEngineSonioxConfig, TranscriptionEngineAConfigParam, diff --git a/src/telnyx/types/conferences/action_speak_params.py b/src/telnyx/types/conferences/action_speak_params.py index 99490c47..c6d0ce88 100644 --- a/src/telnyx/types/conferences/action_speak_params.py +++ b/src/telnyx/types/conferences/action_speak_params.py @@ -7,7 +7,6 @@ from ..._types import SequenceNotStr from ..calls.aws_voice_settings_param import AwsVoiceSettingsParam -from ..shared_params.xai_voice_settings import XaiVoiceSettings from ..calls.telnyx_voice_settings_param import TelnyxVoiceSettingsParam from ..shared_params.rime_voice_settings import RimeVoiceSettings from ..shared_params.azure_voice_settings import AzureVoiceSettings @@ -15,7 +14,7 @@ from ..shared_params.resemble_voice_settings import ResembleVoiceSettings from ..calls.eleven_labs_voice_settings_param import ElevenLabsVoiceSettingsParam -__all__ = ["ActionSpeakParams", "VoiceSettings", "VoiceSettingsInworldVoiceSettings"] +__all__ = ["ActionSpeakParams", "VoiceSettings", "VoiceSettingsInworldVoiceSettings", "VoiceSettingsXaiVoiceSettings"] class ActionSpeakParams(TypedDict, total=False): @@ -140,6 +139,14 @@ class VoiceSettingsInworldVoiceSettings(TypedDict, total=False): """Voice settings provider type""" +class VoiceSettingsXaiVoiceSettings(TypedDict, total=False): + type: Required[Literal["xai"]] + """Voice settings provider type""" + + language: str + """Language code, or `auto` to detect automatically.""" + + VoiceSettings: TypeAlias = Union[ ElevenLabsVoiceSettingsParam, TelnyxVoiceSettingsParam, @@ -149,5 +156,5 @@ class VoiceSettingsInworldVoiceSettings(TypedDict, total=False): RimeVoiceSettings, ResembleVoiceSettings, VoiceSettingsInworldVoiceSettings, - XaiVoiceSettings, + VoiceSettingsXaiVoiceSettings, ] diff --git a/src/telnyx/types/dir/__init__.py b/src/telnyx/types/dir/__init__.py new file mode 100644 index 00000000..948ad449 --- /dev/null +++ b/src/telnyx/types/dir/__init__.py @@ -0,0 +1,17 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from .comment_list_params import CommentListParams as CommentListParams +from .comment_create_params import CommentCreateParams as CommentCreateParams +from .comment_list_response import CommentListResponse as CommentListResponse +from .comment_create_response import CommentCreateResponse as CommentCreateResponse +from .phone_number_add_params import PhoneNumberAddParams as PhoneNumberAddParams +from .phone_number_list_params import PhoneNumberListParams as PhoneNumberListParams +from .phone_number_add_response import PhoneNumberAddResponse as PhoneNumberAddResponse +from .phone_number_list_response import PhoneNumberListResponse as PhoneNumberListResponse +from .phone_number_remove_params import PhoneNumberRemoveParams as PhoneNumberRemoveParams +from .phone_number_remove_response import PhoneNumberRemoveResponse as PhoneNumberRemoveResponse +from .phone_number_batch_list_params import PhoneNumberBatchListParams as PhoneNumberBatchListParams +from .phone_number_batch_list_response import PhoneNumberBatchListResponse as PhoneNumberBatchListResponse +from .phone_number_batch_retrieve_response import PhoneNumberBatchRetrieveResponse as PhoneNumberBatchRetrieveResponse diff --git a/src/telnyx/types/dir/comment_create_params.py b/src/telnyx/types/dir/comment_create_params.py new file mode 100644 index 00000000..a2bc419b --- /dev/null +++ b/src/telnyx/types/dir/comment_create_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 Required, TypedDict + +__all__ = ["CommentCreateParams"] + + +class CommentCreateParams(TypedDict, total=False): + content: Required[str] + """Comment body. 1–5000 characters.""" + + parent_comment_id: str + """Optional parent comment id to thread this reply under.""" diff --git a/src/telnyx/types/dir/comment_create_response.py b/src/telnyx/types/dir/comment_create_response.py new file mode 100644 index 00000000..0664c1e2 --- /dev/null +++ b/src/telnyx/types/dir/comment_create_response.py @@ -0,0 +1,51 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional +from datetime import datetime +from typing_extensions import Literal + +from ..._models import BaseModel + +__all__ = ["CommentCreateResponse", "Data"] + + +class Data(BaseModel): + id: Optional[str] = None + + author_name: Optional[str] = None + """Display name of the author. May be `null`.""" + + author_role: Optional[Literal["customer", "admin"]] = None + """Who wrote the comment. `admin` covers the Telnyx vetting team.""" + + comment_type: Optional[ + Literal[ + "vetting_comment", + "rejection_reason", + "internal_note", + "notification", + "status_update", + "customer_inquiry", + "admin_response", + ] + ] = None + """Comment categorisation. + + Customers post `customer_inquiry`. The Telnyx team posts `vetting_comment`, + `rejection_reason`, `notification`, `status_update`, or `admin_response`. + `internal_note` is filtered out of customer-visible responses. + """ + + content: Optional[str] = None + + created_at: Optional[datetime] = None + + entity_type: Optional[Literal["dir"]] = None + """Resource the comment is attached to. Always `dir` on this endpoint.""" + + visibility: Optional[Literal["customer"]] = None + """Always `customer` on this endpoint — internal-only comments are filtered out.""" + + +class CommentCreateResponse(BaseModel): + data: Data diff --git a/src/telnyx/types/dir/comment_list_params.py b/src/telnyx/types/dir/comment_list_params.py new file mode 100644 index 00000000..2d718f27 --- /dev/null +++ b/src/telnyx/types/dir/comment_list_params.py @@ -0,0 +1,35 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal, Annotated, TypedDict + +from ..._utils import PropertyInfo + +__all__ = ["CommentListParams"] + + +class CommentListParams(TypedDict, total=False): + comment_type: Literal[ + "vetting_comment", + "rejection_reason", + "internal_note", + "notification", + "status_update", + "customer_inquiry", + "admin_response", + ] + """Restrict to comments of this category. + + Customer-visible categories only: internal-only comments are filtered out + regardless of this filter. + """ + + 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/comment_list_response.py b/src/telnyx/types/dir/comment_list_response.py new file mode 100644 index 00000000..6becf4f2 --- /dev/null +++ b/src/telnyx/types/dir/comment_list_response.py @@ -0,0 +1,47 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional +from datetime import datetime +from typing_extensions import Literal + +from ..._models import BaseModel + +__all__ = ["CommentListResponse"] + + +class CommentListResponse(BaseModel): + id: Optional[str] = None + + author_name: Optional[str] = None + """Display name of the author. May be `null`.""" + + author_role: Optional[Literal["customer", "admin"]] = None + """Who wrote the comment. `admin` covers the Telnyx vetting team.""" + + comment_type: Optional[ + Literal[ + "vetting_comment", + "rejection_reason", + "internal_note", + "notification", + "status_update", + "customer_inquiry", + "admin_response", + ] + ] = None + """Comment categorisation. + + Customers post `customer_inquiry`. The Telnyx team posts `vetting_comment`, + `rejection_reason`, `notification`, `status_update`, or `admin_response`. + `internal_note` is filtered out of customer-visible responses. + """ + + content: Optional[str] = None + + created_at: Optional[datetime] = None + + entity_type: Optional[Literal["dir"]] = None + """Resource the comment is attached to. Always `dir` on this endpoint.""" + + visibility: Optional[Literal["customer"]] = None + """Always `customer` on this endpoint — internal-only comments are filtered out.""" diff --git a/src/telnyx/types/dir/phone_number_add_params.py b/src/telnyx/types/dir/phone_number_add_params.py new file mode 100644 index 00000000..d19f394a --- /dev/null +++ b/src/telnyx/types/dir/phone_number_add_params.py @@ -0,0 +1,61 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Iterable +from typing_extensions import Literal, Required, TypedDict + +from ..._types import SequenceNotStr + +__all__ = ["PhoneNumberAddParams", "Document"] + + +class PhoneNumberAddParams(TypedDict, total=False): + documents: Required[Iterable[Document]] + """Supporting documents covering this batch. + + At least one entry with `document_type: letter_of_authorization` is required — + the LOA authorises Telnyx to register these numbers under the DIR. Each + `document_id` must come from the Telnyx Documents API. Additional document types + (e.g. business registration) may be included alongside the LOA. + """ + + phone_numbers: Required[SequenceNotStr[str]] + """1–15 phone numbers in E.164 format. + + 10-digit US numbers are auto-prefixed with `1`. + """ + + +class Document(TypedDict, total=False): + document_id: Required[str] + """ + Id returned by the Telnyx Documents API after you upload the file (upload via + `POST /v2/documents`; see https://developers.telnyx.com/api/documents). + """ + + document_type: Required[ + Literal[ + "letter_of_authorization", + "business_registration", + "articles_of_incorporation", + "tax_document", + "ein_letter", + "trademark_registration", + "website_ownership", + "business_license", + "professional_license", + "government_id", + "utility_bill", + "bank_statement", + "other", + ] + ] + """Type of supporting document. + + Pick the closest match to what the file actually contains; `other` triggers + manual vetting and may slow approval. The matching short_name reference list is + at `GET /v2/dir/document_types`. + """ + + description: str diff --git a/src/telnyx/types/dir/phone_number_add_response.py b/src/telnyx/types/dir/phone_number_add_response.py new file mode 100644 index 00000000..8bafc2aa --- /dev/null +++ b/src/telnyx/types/dir/phone_number_add_response.py @@ -0,0 +1,82 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional +from datetime import datetime +from typing_extensions import Literal + +from ..._models import BaseModel + +__all__ = ["PhoneNumberAddResponse", "Data", "DataRejectionReason"] + + +class DataRejectionReason(BaseModel): + """Populated when `status` is `unsuccessful` or `permanently_rejected`.""" + + code: Optional[str] = None + + detail: Optional[str] = None + + message: Optional[str] = None + """Customer-visible free-text comment from the Telnyx vetting team. + + Only the first entry of `rejection_reasons` carries this; the rest are `null`. + """ + + title: Optional[str] = None + + +class Data(BaseModel): + id: Optional[str] = None + + batch_id: Optional[str] = None + """Id of the batch this number was vetted as part of.""" + + created_at: Optional[datetime] = None + + dir_id: Optional[str] = None + + enterprise_id: Optional[str] = None + + loa_document_id: Optional[str] = None + """Id of the Letter of Authorization document attached to this number's batch.""" + + phone_number: Optional[str] = None + """E.164 with leading `+`.""" + + rejection_reason: Optional[DataRejectionReason] = None + """Populated when `status` is `unsuccessful` or `permanently_rejected`.""" + + status: Optional[ + Literal["submitted", "in_review", "verified", "unsuccessful", "suspended", "expired", "permanently_rejected"] + ] = None + """Phone-number lifecycle status. + + - `submitted` / `in_review` — Telnyx is reviewing the batch this number belongs + to. + - `verified` — approved; the DIR's display identity will be shown on outbound + calls from this number. + - `unsuccessful` — Telnyx rejected this submission; the customer may re-add to + retry. + - `suspended` — temporarily disabled (e.g. by an active infringement claim on + the DIR). + - `expired` — verification expired; re-add to renew. + - `permanently_rejected` — terminal; cannot be re-added on this or any other DIR + you own. + """ + + updated_at: Optional[datetime] = None + + verified_at: Optional[datetime] = None + + +class PhoneNumberAddResponse(BaseModel): + """Bulk-add success response (HTTP 201). + + All numbers in the request were accepted into a single new batch. Every entry in `data` shares the same `batch_id` — read it from any element to obtain the batch id for subsequent `GET .../phone_number_batches/{batch_id}` calls. If any number in the request fails (schema-invalid, not in inventory, already attached to another DIR, etc.) the entire request is rejected with HTTP 400 and the canonical Telnyx error envelope; the success body described here is therefore an all-or-nothing payload. + """ + + data: List[Data] + """Phone numbers accepted into the new batch. + + List order mirrors the request order. Each element shares the same `batch_id`. + """ diff --git a/src/telnyx/types/dir/phone_number_batch_list_params.py b/src/telnyx/types/dir/phone_number_batch_list_params.py new file mode 100644 index 00000000..606c5ca0 --- /dev/null +++ b/src/telnyx/types/dir/phone_number_batch_list_params.py @@ -0,0 +1,26 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal, Annotated, TypedDict + +from ..._utils import PropertyInfo + +__all__ = ["PhoneNumberBatchListParams"] + + +class PhoneNumberBatchListParams(TypedDict, total=False): + filter_status: Annotated[ + Literal["submitted", "in_review", "verified", "unsuccessful", "suspended", "expired", "permanently_rejected"], + PropertyInfo(alias="filter[status]"), + ] + """Restrict to batches whose aggregate status equals this value.""" + + 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/phone_number_batch_list_response.py b/src/telnyx/types/dir/phone_number_batch_list_response.py new file mode 100644 index 00000000..0139f9b5 --- /dev/null +++ b/src/telnyx/types/dir/phone_number_batch_list_response.py @@ -0,0 +1,141 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional +from datetime import datetime +from typing_extensions import Literal + +from ..._models import BaseModel + +__all__ = ["PhoneNumberBatchListResponse", "Document", "PhoneNumber", "PhoneNumberRejectionReason"] + + +class Document(BaseModel): + document_id: str + """ + Id returned by the Telnyx Documents API after you upload the file (upload via + `POST /v2/documents`; see https://developers.telnyx.com/api/documents). + """ + + document_type: Literal[ + "letter_of_authorization", + "business_registration", + "articles_of_incorporation", + "tax_document", + "ein_letter", + "trademark_registration", + "website_ownership", + "business_license", + "professional_license", + "government_id", + "utility_bill", + "bank_statement", + "other", + ] + """Type of supporting document. + + Pick the closest match to what the file actually contains; `other` triggers + manual vetting and may slow approval. The matching short_name reference list is + at `GET /v2/dir/document_types`. + """ + + description: Optional[str] = None + + +class PhoneNumberRejectionReason(BaseModel): + """Populated when `status` is `unsuccessful` or `permanently_rejected`.""" + + code: Optional[str] = None + + detail: Optional[str] = None + + message: Optional[str] = None + """Customer-visible free-text comment from the Telnyx vetting team. + + Only the first entry of `rejection_reasons` carries this; the rest are `null`. + """ + + title: Optional[str] = None + + +class PhoneNumber(BaseModel): + id: Optional[str] = None + + batch_id: Optional[str] = None + """Id of the batch this number was vetted as part of.""" + + created_at: Optional[datetime] = None + + dir_id: Optional[str] = None + + enterprise_id: Optional[str] = None + + loa_document_id: Optional[str] = None + """Id of the Letter of Authorization document attached to this number's batch.""" + + phone_number: Optional[str] = None + """E.164 with leading `+`.""" + + rejection_reason: Optional[PhoneNumberRejectionReason] = None + """Populated when `status` is `unsuccessful` or `permanently_rejected`.""" + + status: Optional[ + Literal["submitted", "in_review", "verified", "unsuccessful", "suspended", "expired", "permanently_rejected"] + ] = None + """Phone-number lifecycle status. + + - `submitted` / `in_review` — Telnyx is reviewing the batch this number belongs + to. + - `verified` — approved; the DIR's display identity will be shown on outbound + calls from this number. + - `unsuccessful` — Telnyx rejected this submission; the customer may re-add to + retry. + - `suspended` — temporarily disabled (e.g. by an active infringement claim on + the DIR). + - `expired` — verification expired; re-add to renew. + - `permanently_rejected` — terminal; cannot be re-added on this or any other DIR + you own. + """ + + updated_at: Optional[datetime] = None + + verified_at: Optional[datetime] = None + + +class PhoneNumberBatchListResponse(BaseModel): + """A phone-number batch groups all numbers added in a single bulk-add request. + + Telnyx vets the batch as a unit. The response embeds the full `phone_numbers` array so you can read per-number status without a separate call, plus a batch-level `status` summarising the unit's progress. + """ + + batch_id: Optional[str] = None + + dir_display_name: Optional[str] = None + """The DIR's display name at the time the batch was read.""" + + dir_id: Optional[str] = None + + documents: Optional[List[Document]] = None + """Documents attached to this batch (e.g. + + a Letter of Authorization). Empty when none were supplied at add time. + """ + + enterprise_id: Optional[str] = None + + phone_numbers: Optional[List[PhoneNumber]] = None + """All phone numbers in this batch, with per-number status.""" + + status: Optional[ + Literal["submitted", "in_review", "verified", "unsuccessful", "suspended", "expired", "permanently_rejected"] + ] = None + """Aggregate batch status. + + Mirrors the values used on individual phone numbers (`submitted`, `in_review`, + `verified`, `unsuccessful`, `permanently_rejected`, etc.). + """ + + submitted_at: Optional[datetime] = None + """When the batch was created (and implicitly submitted for vetting).""" + + total_count: Optional[int] = None + """Number of phone numbers in this batch (length of `phone_numbers`).""" diff --git a/src/telnyx/types/dir/phone_number_batch_retrieve_response.py b/src/telnyx/types/dir/phone_number_batch_retrieve_response.py new file mode 100644 index 00000000..76d62b70 --- /dev/null +++ b/src/telnyx/types/dir/phone_number_batch_retrieve_response.py @@ -0,0 +1,157 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional +from datetime import datetime +from typing_extensions import Literal + +from ..._models import BaseModel + +__all__ = [ + "PhoneNumberBatchRetrieveResponse", + "Data", + "DataDocument", + "DataPhoneNumber", + "DataPhoneNumberRejectionReason", +] + + +class DataDocument(BaseModel): + document_id: str + """ + Id returned by the Telnyx Documents API after you upload the file (upload via + `POST /v2/documents`; see https://developers.telnyx.com/api/documents). + """ + + document_type: Literal[ + "letter_of_authorization", + "business_registration", + "articles_of_incorporation", + "tax_document", + "ein_letter", + "trademark_registration", + "website_ownership", + "business_license", + "professional_license", + "government_id", + "utility_bill", + "bank_statement", + "other", + ] + """Type of supporting document. + + Pick the closest match to what the file actually contains; `other` triggers + manual vetting and may slow approval. The matching short_name reference list is + at `GET /v2/dir/document_types`. + """ + + description: Optional[str] = None + + +class DataPhoneNumberRejectionReason(BaseModel): + """Populated when `status` is `unsuccessful` or `permanently_rejected`.""" + + code: Optional[str] = None + + detail: Optional[str] = None + + message: Optional[str] = None + """Customer-visible free-text comment from the Telnyx vetting team. + + Only the first entry of `rejection_reasons` carries this; the rest are `null`. + """ + + title: Optional[str] = None + + +class DataPhoneNumber(BaseModel): + id: Optional[str] = None + + batch_id: Optional[str] = None + """Id of the batch this number was vetted as part of.""" + + created_at: Optional[datetime] = None + + dir_id: Optional[str] = None + + enterprise_id: Optional[str] = None + + loa_document_id: Optional[str] = None + """Id of the Letter of Authorization document attached to this number's batch.""" + + phone_number: Optional[str] = None + """E.164 with leading `+`.""" + + rejection_reason: Optional[DataPhoneNumberRejectionReason] = None + """Populated when `status` is `unsuccessful` or `permanently_rejected`.""" + + status: Optional[ + Literal["submitted", "in_review", "verified", "unsuccessful", "suspended", "expired", "permanently_rejected"] + ] = None + """Phone-number lifecycle status. + + - `submitted` / `in_review` — Telnyx is reviewing the batch this number belongs + to. + - `verified` — approved; the DIR's display identity will be shown on outbound + calls from this number. + - `unsuccessful` — Telnyx rejected this submission; the customer may re-add to + retry. + - `suspended` — temporarily disabled (e.g. by an active infringement claim on + the DIR). + - `expired` — verification expired; re-add to renew. + - `permanently_rejected` — terminal; cannot be re-added on this or any other DIR + you own. + """ + + updated_at: Optional[datetime] = None + + verified_at: Optional[datetime] = None + + +class Data(BaseModel): + """A phone-number batch groups all numbers added in a single bulk-add request. + + Telnyx vets the batch as a unit. The response embeds the full `phone_numbers` array so you can read per-number status without a separate call, plus a batch-level `status` summarising the unit's progress. + """ + + batch_id: Optional[str] = None + + dir_display_name: Optional[str] = None + """The DIR's display name at the time the batch was read.""" + + dir_id: Optional[str] = None + + documents: Optional[List[DataDocument]] = None + """Documents attached to this batch (e.g. + + a Letter of Authorization). Empty when none were supplied at add time. + """ + + enterprise_id: Optional[str] = None + + phone_numbers: Optional[List[DataPhoneNumber]] = None + """All phone numbers in this batch, with per-number status.""" + + status: Optional[ + Literal["submitted", "in_review", "verified", "unsuccessful", "suspended", "expired", "permanently_rejected"] + ] = None + """Aggregate batch status. + + Mirrors the values used on individual phone numbers (`submitted`, `in_review`, + `verified`, `unsuccessful`, `permanently_rejected`, etc.). + """ + + submitted_at: Optional[datetime] = None + """When the batch was created (and implicitly submitted for vetting).""" + + total_count: Optional[int] = None + """Number of phone numbers in this batch (length of `phone_numbers`).""" + + +class PhoneNumberBatchRetrieveResponse(BaseModel): + data: Data + """A phone-number batch groups all numbers added in a single bulk-add request. + + Telnyx vets the batch as a unit. The response embeds the full `phone_numbers` + array so you can read per-number status without a separate call, plus a + batch-level `status` summarising the unit's progress. + """ diff --git a/src/telnyx/types/dir/phone_number_list_params.py b/src/telnyx/types/dir/phone_number_list_params.py new file mode 100644 index 00000000..5d4ff87f --- /dev/null +++ b/src/telnyx/types/dir/phone_number_list_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_extensions import Literal, Annotated, TypedDict + +from ..._utils import PropertyInfo + +__all__ = ["PhoneNumberListParams"] + + +class PhoneNumberListParams(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.""" + + status: Literal[ + "submitted", "in_review", "verified", "unsuccessful", "suspended", "expired", "permanently_rejected" + ] + """Filter by phone-number status.""" diff --git a/src/telnyx/types/dir/phone_number_list_response.py b/src/telnyx/types/dir/phone_number_list_response.py new file mode 100644 index 00000000..d7c59404 --- /dev/null +++ b/src/telnyx/types/dir/phone_number_list_response.py @@ -0,0 +1,69 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional +from datetime import datetime +from typing_extensions import Literal + +from ..._models import BaseModel + +__all__ = ["PhoneNumberListResponse", "RejectionReason"] + + +class RejectionReason(BaseModel): + """Populated when `status` is `unsuccessful` or `permanently_rejected`.""" + + code: Optional[str] = None + + detail: Optional[str] = None + + message: Optional[str] = None + """Customer-visible free-text comment from the Telnyx vetting team. + + Only the first entry of `rejection_reasons` carries this; the rest are `null`. + """ + + title: Optional[str] = None + + +class PhoneNumberListResponse(BaseModel): + id: Optional[str] = None + + batch_id: Optional[str] = None + """Id of the batch this number was vetted as part of.""" + + created_at: Optional[datetime] = None + + dir_id: Optional[str] = None + + enterprise_id: Optional[str] = None + + loa_document_id: Optional[str] = None + """Id of the Letter of Authorization document attached to this number's batch.""" + + phone_number: Optional[str] = None + """E.164 with leading `+`.""" + + rejection_reason: Optional[RejectionReason] = None + """Populated when `status` is `unsuccessful` or `permanently_rejected`.""" + + status: Optional[ + Literal["submitted", "in_review", "verified", "unsuccessful", "suspended", "expired", "permanently_rejected"] + ] = None + """Phone-number lifecycle status. + + - `submitted` / `in_review` — Telnyx is reviewing the batch this number belongs + to. + - `verified` — approved; the DIR's display identity will be shown on outbound + calls from this number. + - `unsuccessful` — Telnyx rejected this submission; the customer may re-add to + retry. + - `suspended` — temporarily disabled (e.g. by an active infringement claim on + the DIR). + - `expired` — verification expired; re-add to renew. + - `permanently_rejected` — terminal; cannot be re-added on this or any other DIR + you own. + """ + + updated_at: Optional[datetime] = None + + verified_at: Optional[datetime] = None diff --git a/src/telnyx/types/dir/phone_number_remove_params.py b/src/telnyx/types/dir/phone_number_remove_params.py new file mode 100644 index 00000000..1e695d95 --- /dev/null +++ b/src/telnyx/types/dir/phone_number_remove_params.py @@ -0,0 +1,13 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, TypedDict + +from ..._types import SequenceNotStr + +__all__ = ["PhoneNumberRemoveParams"] + + +class PhoneNumberRemoveParams(TypedDict, total=False): + phone_numbers: Required[SequenceNotStr[str]] diff --git a/src/telnyx/types/dir/phone_number_remove_response.py b/src/telnyx/types/dir/phone_number_remove_response.py new file mode 100644 index 00000000..a69d231c --- /dev/null +++ b/src/telnyx/types/dir/phone_number_remove_response.py @@ -0,0 +1,48 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List +from typing_extensions import Literal + +from ..._models import BaseModel + +__all__ = ["PhoneNumberRemoveResponse", "Meta", "MetaError"] + + +class MetaError(BaseModel): + """Per-number error returned by the bulk-delete endpoint. + + Bulk-add does not use this shape — it returns a 400 with the canonical envelope grouping numbers by failure category. + """ + + code: Literal["not_associated"] + """Stable per-number error code. + + Currently only `not_associated` is emitted, when the number is not attached to + this DIR. + """ + + detail: str + + phone_number: str + + title: str + + +class Meta(BaseModel): + errors: List[MetaError] + """Per-number failures that did not block the call. + + Each entry has `phone_number`, `code`, `title`, `detail`. + """ + + +class PhoneNumberRemoveResponse(BaseModel): + """Bulk-delete partial-success response. + + `data` is the list of phone numbers that were soft-deleted. `meta.errors` holds per-number failures (e.g. number not associated with this DIR). When EVERY number in the request fails, the endpoint instead returns 400 with the canonical Telnyx error envelope and `data`/`meta` are absent. + """ + + data: List[str] + """Phone numbers that were successfully soft-deleted. Bare E.164 strings.""" + + meta: Meta diff --git a/src/telnyx/types/dir_list_document_types_response.py b/src/telnyx/types/dir_list_document_types_response.py new file mode 100644 index 00000000..636035d3 --- /dev/null +++ b/src/telnyx/types/dir_list_document_types_response.py @@ -0,0 +1,50 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional + +from .._models import BaseModel + +__all__ = ["DirListDocumentTypesResponse", "Data", "Meta"] + + +class Data(BaseModel): + """Single supported document type.""" + + description: Optional[str] = None + + short_name: Optional[str] = None + """Stable identifier passed to `Document.document_type`.""" + + +class Meta(BaseModel): + """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. + """ + + page_number: int + """1-based index of this page. + + Echoes the `page[number]` query parameter (default `1`). + """ + + page_size: int + """Number of items returned in this page's `data` array. Capped at 250.""" + + total_pages: int + """Total number of pages available given the current `page_size`.""" + + total_results: int + """Total number of items across all pages (excludes soft-deleted rows).""" + + +class DirListDocumentTypesResponse(BaseModel): + data: List[Data] + + meta: Meta + """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_list_infringement_claims_params.py b/src/telnyx/types/dir_list_infringement_claims_params.py new file mode 100644 index 00000000..930ed1f3 --- /dev/null +++ b/src/telnyx/types/dir_list_infringement_claims_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__ = ["DirListInfringementClaimsParams"] + + +class DirListInfringementClaimsParams(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_list_infringement_claims_response.py b/src/telnyx/types/dir_list_infringement_claims_response.py new file mode 100644 index 00000000..fc33b3b1 --- /dev/null +++ b/src/telnyx/types/dir_list_infringement_claims_response.py @@ -0,0 +1,145 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional +from datetime import datetime +from typing_extensions import Literal + +from .._models import BaseModel + +__all__ = ["DirListInfringementClaimsResponse", "ContestDocument", "ContestHistory", "Dir"] + + +class ContestDocument(BaseModel): + document_id: str + """ + Id returned by the Telnyx Documents API after you upload the file (upload via + `POST /v2/documents`; see https://developers.telnyx.com/api/documents). + """ + + document_type: Literal[ + "letter_of_authorization", + "business_registration", + "articles_of_incorporation", + "tax_document", + "ein_letter", + "trademark_registration", + "website_ownership", + "business_license", + "professional_license", + "government_id", + "utility_bill", + "bank_statement", + "other", + ] + """Type of supporting document. + + Pick the closest match to what the file actually contains; `other` triggers + manual vetting and may slow approval. The matching short_name reference list is + at `GET /v2/dir/document_types`. + """ + + description: Optional[str] = None + + +class ContestHistory(BaseModel): + """One round of customer contest evidence on an infringement claim. + + The aggregated documents across rounds live on the parent claim's `contest_documents`; this submission record carries only the per-round notes and document count. + """ + + document_count: Optional[int] = None + + notes: Optional[str] = None + + submitted_at: Optional[datetime] = None + + +class Dir(BaseModel): + """Snapshot of the DIR the claim is filed against, embedded for convenience.""" + + id: Optional[str] = None + + display_name: Optional[str] = None + + enterprise_id: Optional[str] = None + + status: Optional[ + Literal[ + "draft", + "submitted", + "in_review", + "verified", + "rejected", + "unsuccessful", + "suspended", + "expired", + "infringement_claimed", + "permanently_rejected", + ] + ] = None + """DIR lifecycle status. + + - `draft` — newly created; editable; not yet submitted. + - `submitted` / `in_review` — Telnyx is reviewing. + - `verified` — approved; phone numbers may be attached. + - `rejected` — Telnyx rejected this submission; `rejection_reasons` is + populated; customer can edit and resubmit. + - `unsuccessful` — system-side error during processing; customer can edit and + resubmit. + - `suspended` — temporarily disabled (e.g. by an active infringement claim). + - `expired` — verification expired; customer must resubmit. + - `infringement_claimed` — a trademark/impersonation claim is open against this + DIR. + - `permanently_rejected` — terminal; cannot be resubmitted. + """ + + +class DirListInfringementClaimsResponse(BaseModel): + id: Optional[str] = None + + claim_date: Optional[datetime] = None + """When the claim was filed (set by the claimant's representative at file time).""" + + claim_description: Optional[str] = None + + claim_type: Optional[Literal["trademark", "copyright"]] = None + """Category of infringement being claimed.""" + + claimant_contact: Optional[str] = None + + claimant_name: Optional[str] = None + + contest_documents: Optional[List[ContestDocument]] = None + """Aggregated across all customer contest submissions on this claim.""" + + contest_history: Optional[List[ContestHistory]] = None + """Per-round submission audit trail. + + Each entry records one `POST /infringement_claims/{id}/contest` call (notes, + timestamp, document count). Aggregated documents live on `contest_documents`. + """ + + created_at: Optional[datetime] = None + + dir: Optional[Dir] = None + """Snapshot of the DIR the claim is filed against, embedded for convenience.""" + + dir_id: Optional[str] = None + + enterprise_id: Optional[str] = None + + resolution: Optional[Literal["upheld", "rejected", "modified"]] = None + """Set only when `status` is `resolved`.""" + + resolution_date: Optional[datetime] = None + + resolution_notes: Optional[str] = None + + status: Optional[Literal["pending", "contested", "resolved"]] = None + """Lifecycle status. + + `pending` — newly filed; the DIR is auto-suspended. `contested` — you have + submitted contest evidence; awaiting Telnyx review. `resolved` — final. + """ + + updated_at: Optional[datetime] = None diff --git a/src/telnyx/types/dir_list_params.py b/src/telnyx/types/dir_list_params.py new file mode 100644 index 00000000..ed19064c --- /dev/null +++ b/src/telnyx/types/dir_list_params.py @@ -0,0 +1,64 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Union +from datetime import datetime +from typing_extensions import Literal, Annotated, TypedDict + +from .._utils import PropertyInfo + +__all__ = ["DirListParams"] + + +class DirListParams(TypedDict, total=False): + enterprise_id: str + """Restrict results to a single enterprise.""" + + filter_expiring_at_gte: Annotated[ + Union[str, datetime], PropertyInfo(alias="filter[expiring_at][gte]", format="iso8601") + ] + """Return only DIRs whose `expiring_at` is at or after this ISO-8601 timestamp. + + Pairs with the `[lte]` variant to build renewal-window dashboards. + """ + + filter_expiring_at_lte: Annotated[ + Union[str, datetime], PropertyInfo(alias="filter[expiring_at][lte]", format="iso8601") + ] + """Return only DIRs whose `expiring_at` is at or before this ISO-8601 timestamp.""" + + 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.""" + + search: str + """Case-insensitive partial match on `display_name` or call reason.""" + + sort: Literal[ + "created_at", "-created_at", "updated_at", "-updated_at", "display_name", "-display_name", "status", "-status" + ] + """Sort field. + + Allowed values: `created_at`, `updated_at`, `display_name`, `status`. Prefix + with `-` for descending. Default `-created_at`. + """ + + status: Literal[ + "draft", + "submitted", + "in_review", + "verified", + "rejected", + "unsuccessful", + "suspended", + "expired", + "infringement_claimed", + "permanently_rejected", + ] + """Filter by DIR status.""" diff --git a/src/telnyx/types/dir_list_response.py b/src/telnyx/types/dir_list_response.py new file mode 100644 index 00000000..4954d44d --- /dev/null +++ b/src/telnyx/types/dir_list_response.py @@ -0,0 +1,135 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional +from datetime import datetime +from typing_extensions import Literal + +from .._models import BaseModel + +__all__ = ["DirListResponse", "CallReason", "Document", "RejectionReason"] + + +class CallReason(BaseModel): + created_at: Optional[datetime] = None + + reason: Optional[str] = None + + +class Document(BaseModel): + document_id: str + """ + Id returned by the Telnyx Documents API after you upload the file (upload via + `POST /v2/documents`; see https://developers.telnyx.com/api/documents). + """ + + document_type: Literal[ + "letter_of_authorization", + "business_registration", + "articles_of_incorporation", + "tax_document", + "ein_letter", + "trademark_registration", + "website_ownership", + "business_license", + "professional_license", + "government_id", + "utility_bill", + "bank_statement", + "other", + ] + """Type of supporting document. + + Pick the closest match to what the file actually contains; `other` triggers + manual vetting and may slow approval. The matching short_name reference list is + at `GET /v2/dir/document_types`. + """ + + description: Optional[str] = None + + +class RejectionReason(BaseModel): + code: Optional[str] = None + + detail: Optional[str] = None + + message: Optional[str] = None + """Customer-visible free-text comment from the Telnyx vetting team. + + Only the first entry of `rejection_reasons` carries this; the rest are `null`. + """ + + title: Optional[str] = None + + +class DirListResponse(BaseModel): + id: Optional[str] = None + + authorizer_email: Optional[str] = None + + authorizer_name: Optional[str] = None + + call_reasons: Optional[List[CallReason]] = None + + certify_brand_is_accurate: Optional[bool] = None + + certify_ip_ownership: Optional[bool] = None + + certify_no_shaft_content: Optional[bool] = None + + created_at: Optional[datetime] = None + + display_name: Optional[str] = None + + documents: Optional[List[Document]] = None + + enterprise_id: Optional[str] = None + + expiring_at: Optional[datetime] = None + + logo_url: Optional[str] = None + + rejected_at: Optional[datetime] = None + + rejection_reasons: Optional[List[RejectionReason]] = None + """ + Populated when `status` is `rejected`; cleared on `/submit` or successful + approval. + """ + + reselling: Optional[bool] = None + + status: Optional[ + Literal[ + "draft", + "submitted", + "in_review", + "verified", + "rejected", + "unsuccessful", + "suspended", + "expired", + "infringement_claimed", + "permanently_rejected", + ] + ] = None + """DIR lifecycle status. + + - `draft` — newly created; editable; not yet submitted. + - `submitted` / `in_review` — Telnyx is reviewing. + - `verified` — approved; phone numbers may be attached. + - `rejected` — Telnyx rejected this submission; `rejection_reasons` is + populated; customer can edit and resubmit. + - `unsuccessful` — system-side error during processing; customer can edit and + resubmit. + - `suspended` — temporarily disabled (e.g. by an active infringement claim). + - `expired` — verification expired; customer must resubmit. + - `infringement_claimed` — a trademark/impersonation claim is open against this + DIR. + - `permanently_rejected` — terminal; cannot be resubmitted. + """ + + submitted_at: Optional[datetime] = None + + updated_at: Optional[datetime] = None + + verified_at: Optional[datetime] = None diff --git a/src/telnyx/types/dir_retrieve_response.py b/src/telnyx/types/dir_retrieve_response.py new file mode 100644 index 00000000..f0558c73 --- /dev/null +++ b/src/telnyx/types/dir_retrieve_response.py @@ -0,0 +1,139 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional +from datetime import datetime +from typing_extensions import Literal + +from .._models import BaseModel + +__all__ = ["DirRetrieveResponse", "Data", "DataCallReason", "DataDocument", "DataRejectionReason"] + + +class DataCallReason(BaseModel): + created_at: Optional[datetime] = None + + reason: Optional[str] = None + + +class DataDocument(BaseModel): + document_id: str + """ + Id returned by the Telnyx Documents API after you upload the file (upload via + `POST /v2/documents`; see https://developers.telnyx.com/api/documents). + """ + + document_type: Literal[ + "letter_of_authorization", + "business_registration", + "articles_of_incorporation", + "tax_document", + "ein_letter", + "trademark_registration", + "website_ownership", + "business_license", + "professional_license", + "government_id", + "utility_bill", + "bank_statement", + "other", + ] + """Type of supporting document. + + Pick the closest match to what the file actually contains; `other` triggers + manual vetting and may slow approval. The matching short_name reference list is + at `GET /v2/dir/document_types`. + """ + + description: Optional[str] = None + + +class DataRejectionReason(BaseModel): + code: Optional[str] = None + + detail: Optional[str] = None + + message: Optional[str] = None + """Customer-visible free-text comment from the Telnyx vetting team. + + Only the first entry of `rejection_reasons` carries this; the rest are `null`. + """ + + title: Optional[str] = None + + +class Data(BaseModel): + id: Optional[str] = None + + authorizer_email: Optional[str] = None + + authorizer_name: Optional[str] = None + + call_reasons: Optional[List[DataCallReason]] = None + + certify_brand_is_accurate: Optional[bool] = None + + certify_ip_ownership: Optional[bool] = None + + certify_no_shaft_content: Optional[bool] = None + + created_at: Optional[datetime] = None + + display_name: Optional[str] = None + + documents: Optional[List[DataDocument]] = None + + enterprise_id: Optional[str] = None + + expiring_at: Optional[datetime] = None + + logo_url: Optional[str] = None + + rejected_at: Optional[datetime] = None + + rejection_reasons: Optional[List[DataRejectionReason]] = None + """ + Populated when `status` is `rejected`; cleared on `/submit` or successful + approval. + """ + + reselling: Optional[bool] = None + + status: Optional[ + Literal[ + "draft", + "submitted", + "in_review", + "verified", + "rejected", + "unsuccessful", + "suspended", + "expired", + "infringement_claimed", + "permanently_rejected", + ] + ] = None + """DIR lifecycle status. + + - `draft` — newly created; editable; not yet submitted. + - `submitted` / `in_review` — Telnyx is reviewing. + - `verified` — approved; phone numbers may be attached. + - `rejected` — Telnyx rejected this submission; `rejection_reasons` is + populated; customer can edit and resubmit. + - `unsuccessful` — system-side error during processing; customer can edit and + resubmit. + - `suspended` — temporarily disabled (e.g. by an active infringement claim). + - `expired` — verification expired; customer must resubmit. + - `infringement_claimed` — a trademark/impersonation claim is open against this + DIR. + - `permanently_rejected` — terminal; cannot be resubmitted. + """ + + submitted_at: Optional[datetime] = None + + updated_at: Optional[datetime] = None + + verified_at: Optional[datetime] = None + + +class DirRetrieveResponse(BaseModel): + data: Data diff --git a/src/telnyx/types/dir_submit_response.py b/src/telnyx/types/dir_submit_response.py new file mode 100644 index 00000000..89e5ce38 --- /dev/null +++ b/src/telnyx/types/dir_submit_response.py @@ -0,0 +1,139 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional +from datetime import datetime +from typing_extensions import Literal + +from .._models import BaseModel + +__all__ = ["DirSubmitResponse", "Data", "DataCallReason", "DataDocument", "DataRejectionReason"] + + +class DataCallReason(BaseModel): + created_at: Optional[datetime] = None + + reason: Optional[str] = None + + +class DataDocument(BaseModel): + document_id: str + """ + Id returned by the Telnyx Documents API after you upload the file (upload via + `POST /v2/documents`; see https://developers.telnyx.com/api/documents). + """ + + document_type: Literal[ + "letter_of_authorization", + "business_registration", + "articles_of_incorporation", + "tax_document", + "ein_letter", + "trademark_registration", + "website_ownership", + "business_license", + "professional_license", + "government_id", + "utility_bill", + "bank_statement", + "other", + ] + """Type of supporting document. + + Pick the closest match to what the file actually contains; `other` triggers + manual vetting and may slow approval. The matching short_name reference list is + at `GET /v2/dir/document_types`. + """ + + description: Optional[str] = None + + +class DataRejectionReason(BaseModel): + code: Optional[str] = None + + detail: Optional[str] = None + + message: Optional[str] = None + """Customer-visible free-text comment from the Telnyx vetting team. + + Only the first entry of `rejection_reasons` carries this; the rest are `null`. + """ + + title: Optional[str] = None + + +class Data(BaseModel): + id: Optional[str] = None + + authorizer_email: Optional[str] = None + + authorizer_name: Optional[str] = None + + call_reasons: Optional[List[DataCallReason]] = None + + certify_brand_is_accurate: Optional[bool] = None + + certify_ip_ownership: Optional[bool] = None + + certify_no_shaft_content: Optional[bool] = None + + created_at: Optional[datetime] = None + + display_name: Optional[str] = None + + documents: Optional[List[DataDocument]] = None + + enterprise_id: Optional[str] = None + + expiring_at: Optional[datetime] = None + + logo_url: Optional[str] = None + + rejected_at: Optional[datetime] = None + + rejection_reasons: Optional[List[DataRejectionReason]] = None + """ + Populated when `status` is `rejected`; cleared on `/submit` or successful + approval. + """ + + reselling: Optional[bool] = None + + status: Optional[ + Literal[ + "draft", + "submitted", + "in_review", + "verified", + "rejected", + "unsuccessful", + "suspended", + "expired", + "infringement_claimed", + "permanently_rejected", + ] + ] = None + """DIR lifecycle status. + + - `draft` — newly created; editable; not yet submitted. + - `submitted` / `in_review` — Telnyx is reviewing. + - `verified` — approved; phone numbers may be attached. + - `rejected` — Telnyx rejected this submission; `rejection_reasons` is + populated; customer can edit and resubmit. + - `unsuccessful` — system-side error during processing; customer can edit and + resubmit. + - `suspended` — temporarily disabled (e.g. by an active infringement claim). + - `expired` — verification expired; customer must resubmit. + - `infringement_claimed` — a trademark/impersonation claim is open against this + DIR. + - `permanently_rejected` — terminal; cannot be resubmitted. + """ + + submitted_at: Optional[datetime] = None + + updated_at: Optional[datetime] = None + + verified_at: Optional[datetime] = None + + +class DirSubmitResponse(BaseModel): + data: Data diff --git a/src/telnyx/types/dir_update_infringement_params.py b/src/telnyx/types/dir_update_infringement_params.py new file mode 100644 index 00000000..b59eaf10 --- /dev/null +++ b/src/telnyx/types/dir_update_infringement_params.py @@ -0,0 +1,71 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Iterable, Optional +from typing_extensions import Literal, Required, TypedDict + +from .._types import SequenceNotStr + +__all__ = ["DirUpdateInfringementParams", "Document"] + + +class DirUpdateInfringementParams(TypedDict, total=False): + certify_brand_is_accurate: Required[Literal[True]] + """Must be `true`.""" + + certify_ip_ownership: Required[Literal[True]] + """Must be `true`.""" + + certify_no_infringement: Required[Literal[True]] + """Must be `true`.""" + + certify_no_shaft_content: Required[Literal[True]] + """Must be `true`.""" + + infringement_resolution_notes: Required[str] + """Explanation of how the infringement concern was addressed.""" + + call_reasons: Optional[SequenceNotStr[str]] + + display_name: Optional[str] + + documents: Optional[Iterable[Document]] + """Append-only supporting documents.""" + + logo_url: Optional[str] + """Publicly accessible HTTPS URL (max 128 chars) to a 256x256 BMP logo (max 1 MB).""" + + +class Document(TypedDict, total=False): + document_id: Required[str] + """ + Id returned by the Telnyx Documents API after you upload the file (upload via + `POST /v2/documents`; see https://developers.telnyx.com/api/documents). + """ + + document_type: Required[ + Literal[ + "letter_of_authorization", + "business_registration", + "articles_of_incorporation", + "tax_document", + "ein_letter", + "trademark_registration", + "website_ownership", + "business_license", + "professional_license", + "government_id", + "utility_bill", + "bank_statement", + "other", + ] + ] + """Type of supporting document. + + Pick the closest match to what the file actually contains; `other` triggers + manual vetting and may slow approval. The matching short_name reference list is + at `GET /v2/dir/document_types`. + """ + + description: str diff --git a/src/telnyx/types/dir_update_infringement_response.py b/src/telnyx/types/dir_update_infringement_response.py new file mode 100644 index 00000000..f86071fa --- /dev/null +++ b/src/telnyx/types/dir_update_infringement_response.py @@ -0,0 +1,139 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional +from datetime import datetime +from typing_extensions import Literal + +from .._models import BaseModel + +__all__ = ["DirUpdateInfringementResponse", "Data", "DataCallReason", "DataDocument", "DataRejectionReason"] + + +class DataCallReason(BaseModel): + created_at: Optional[datetime] = None + + reason: Optional[str] = None + + +class DataDocument(BaseModel): + document_id: str + """ + Id returned by the Telnyx Documents API after you upload the file (upload via + `POST /v2/documents`; see https://developers.telnyx.com/api/documents). + """ + + document_type: Literal[ + "letter_of_authorization", + "business_registration", + "articles_of_incorporation", + "tax_document", + "ein_letter", + "trademark_registration", + "website_ownership", + "business_license", + "professional_license", + "government_id", + "utility_bill", + "bank_statement", + "other", + ] + """Type of supporting document. + + Pick the closest match to what the file actually contains; `other` triggers + manual vetting and may slow approval. The matching short_name reference list is + at `GET /v2/dir/document_types`. + """ + + description: Optional[str] = None + + +class DataRejectionReason(BaseModel): + code: Optional[str] = None + + detail: Optional[str] = None + + message: Optional[str] = None + """Customer-visible free-text comment from the Telnyx vetting team. + + Only the first entry of `rejection_reasons` carries this; the rest are `null`. + """ + + title: Optional[str] = None + + +class Data(BaseModel): + id: Optional[str] = None + + authorizer_email: Optional[str] = None + + authorizer_name: Optional[str] = None + + call_reasons: Optional[List[DataCallReason]] = None + + certify_brand_is_accurate: Optional[bool] = None + + certify_ip_ownership: Optional[bool] = None + + certify_no_shaft_content: Optional[bool] = None + + created_at: Optional[datetime] = None + + display_name: Optional[str] = None + + documents: Optional[List[DataDocument]] = None + + enterprise_id: Optional[str] = None + + expiring_at: Optional[datetime] = None + + logo_url: Optional[str] = None + + rejected_at: Optional[datetime] = None + + rejection_reasons: Optional[List[DataRejectionReason]] = None + """ + Populated when `status` is `rejected`; cleared on `/submit` or successful + approval. + """ + + reselling: Optional[bool] = None + + status: Optional[ + Literal[ + "draft", + "submitted", + "in_review", + "verified", + "rejected", + "unsuccessful", + "suspended", + "expired", + "infringement_claimed", + "permanently_rejected", + ] + ] = None + """DIR lifecycle status. + + - `draft` — newly created; editable; not yet submitted. + - `submitted` / `in_review` — Telnyx is reviewing. + - `verified` — approved; phone numbers may be attached. + - `rejected` — Telnyx rejected this submission; `rejection_reasons` is + populated; customer can edit and resubmit. + - `unsuccessful` — system-side error during processing; customer can edit and + resubmit. + - `suspended` — temporarily disabled (e.g. by an active infringement claim). + - `expired` — verification expired; customer must resubmit. + - `infringement_claimed` — a trademark/impersonation claim is open against this + DIR. + - `permanently_rejected` — terminal; cannot be resubmitted. + """ + + submitted_at: Optional[datetime] = None + + updated_at: Optional[datetime] = None + + verified_at: Optional[datetime] = None + + +class DirUpdateInfringementResponse(BaseModel): + data: Data diff --git a/src/telnyx/types/dir_update_params.py b/src/telnyx/types/dir_update_params.py new file mode 100644 index 00000000..e82265e7 --- /dev/null +++ b/src/telnyx/types/dir_update_params.py @@ -0,0 +1,41 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import TypedDict + +from .._types import SequenceNotStr + +__all__ = ["DirUpdateParams"] + + +class DirUpdateParams(TypedDict, total=False): + authorizer_email: str + """Contact email of the authorizer. + + Telnyx may send verification or infringement notices here. + """ + + authorizer_name: str + """Name of the person at your enterprise authorizing this DIR. + + Must be a real individual. + """ + + call_reasons: SequenceNotStr[str] + """1–10 reasons your business calls customers. + + Validate phrasing against `POST /call_reasons/validate`. + """ + + display_name: str + """Name shown to call recipients. 1–35 characters, no emoji, not whitespace-only.""" + + logo_url: str + """Publicly accessible HTTPS URL (max 128 chars) to a 256x256 BMP logo (max 1 MB).""" + + reselling: bool + """ + Set to true if your organization places calls on behalf of other enterprises + (BPO/reseller). Updating this triggers re-vetting on next submit. + """ diff --git a/src/telnyx/types/dir_update_response.py b/src/telnyx/types/dir_update_response.py new file mode 100644 index 00000000..555c5dc6 --- /dev/null +++ b/src/telnyx/types/dir_update_response.py @@ -0,0 +1,139 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional +from datetime import datetime +from typing_extensions import Literal + +from .._models import BaseModel + +__all__ = ["DirUpdateResponse", "Data", "DataCallReason", "DataDocument", "DataRejectionReason"] + + +class DataCallReason(BaseModel): + created_at: Optional[datetime] = None + + reason: Optional[str] = None + + +class DataDocument(BaseModel): + document_id: str + """ + Id returned by the Telnyx Documents API after you upload the file (upload via + `POST /v2/documents`; see https://developers.telnyx.com/api/documents). + """ + + document_type: Literal[ + "letter_of_authorization", + "business_registration", + "articles_of_incorporation", + "tax_document", + "ein_letter", + "trademark_registration", + "website_ownership", + "business_license", + "professional_license", + "government_id", + "utility_bill", + "bank_statement", + "other", + ] + """Type of supporting document. + + Pick the closest match to what the file actually contains; `other` triggers + manual vetting and may slow approval. The matching short_name reference list is + at `GET /v2/dir/document_types`. + """ + + description: Optional[str] = None + + +class DataRejectionReason(BaseModel): + code: Optional[str] = None + + detail: Optional[str] = None + + message: Optional[str] = None + """Customer-visible free-text comment from the Telnyx vetting team. + + Only the first entry of `rejection_reasons` carries this; the rest are `null`. + """ + + title: Optional[str] = None + + +class Data(BaseModel): + id: Optional[str] = None + + authorizer_email: Optional[str] = None + + authorizer_name: Optional[str] = None + + call_reasons: Optional[List[DataCallReason]] = None + + certify_brand_is_accurate: Optional[bool] = None + + certify_ip_ownership: Optional[bool] = None + + certify_no_shaft_content: Optional[bool] = None + + created_at: Optional[datetime] = None + + display_name: Optional[str] = None + + documents: Optional[List[DataDocument]] = None + + enterprise_id: Optional[str] = None + + expiring_at: Optional[datetime] = None + + logo_url: Optional[str] = None + + rejected_at: Optional[datetime] = None + + rejection_reasons: Optional[List[DataRejectionReason]] = None + """ + Populated when `status` is `rejected`; cleared on `/submit` or successful + approval. + """ + + reselling: Optional[bool] = None + + status: Optional[ + Literal[ + "draft", + "submitted", + "in_review", + "verified", + "rejected", + "unsuccessful", + "suspended", + "expired", + "infringement_claimed", + "permanently_rejected", + ] + ] = None + """DIR lifecycle status. + + - `draft` — newly created; editable; not yet submitted. + - `submitted` / `in_review` — Telnyx is reviewing. + - `verified` — approved; phone numbers may be attached. + - `rejected` — Telnyx rejected this submission; `rejection_reasons` is + populated; customer can edit and resubmit. + - `unsuccessful` — system-side error during processing; customer can edit and + resubmit. + - `suspended` — temporarily disabled (e.g. by an active infringement claim). + - `expired` — verification expired; customer must resubmit. + - `infringement_claimed` — a trademark/impersonation claim is open against this + DIR. + - `permanently_rejected` — terminal; cannot be resubmitted. + """ + + submitted_at: Optional[datetime] = None + + updated_at: Optional[datetime] = None + + verified_at: Optional[datetime] = None + + +class DirUpdateResponse(BaseModel): + data: Data diff --git a/src/telnyx/types/enterprise_activate_branded_calling_response.py b/src/telnyx/types/enterprise_activate_branded_calling_response.py new file mode 100644 index 00000000..7d8b87f3 --- /dev/null +++ b/src/telnyx/types/enterprise_activate_branded_calling_response.py @@ -0,0 +1,10 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from .._models import BaseModel +from .enterprise_public import EnterprisePublic + +__all__ = ["EnterpriseActivateBrandedCallingResponse"] + + +class EnterpriseActivateBrandedCallingResponse(BaseModel): + data: EnterprisePublic diff --git a/src/telnyx/types/enterprise_create_params.py b/src/telnyx/types/enterprise_create_params.py index eb3c61b3..96c9e5aa 100644 --- a/src/telnyx/types/enterprise_create_params.py +++ b/src/telnyx/types/enterprise_create_params.py @@ -2,6 +2,7 @@ from __future__ import annotations +from typing import Optional from typing_extensions import Literal, Required, TypedDict from .billing_address_param import BillingAddressParam @@ -18,67 +19,124 @@ class EnterpriseCreateParams(TypedDict, total=False): billing_contact: Required[BillingContactParam] country_code: Required[str] - """Country code. Currently only 'US' is accepted.""" + """ISO 3166-1 alpha-2 country code. Currently `US` and `CA` are supported.""" doing_business_as: Required[str] - """Primary business name / DBA name""" fein: Required[str] - """Federal Employer Identification Number. - - Format: XX-XXXXXXX or 9-digit number (minimum 9 digits). """ - - industry: Required[str] - """Industry classification. - - Case-insensitive. Accepted values: accounting, finance, billing, collections, - business, charity, nonprofit, communications, telecom, customer service, - support, delivery, shipping, logistics, education, financial, banking, - government, public, healthcare, health, pharmacy, medical, insurance, legal, - law, notifications, scheduling, real estate, property, retail, ecommerce, sales, - marketing, software, technology, tech, media, surveys, market research, travel, - hospitality, hotel + US Federal Employer Identification Number (`NN-NNNNNNN`) or Canadian equivalent. """ + industry: Required[ + Literal[ + "accounting", + "finance", + "billing", + "collections", + "business", + "charity", + "nonprofit", + "communications", + "telecom", + "customer service", + "support", + "delivery", + "shipping", + "logistics", + "education", + "financial", + "banking", + "government", + "public", + "healthcare", + "health", + "pharmacy", + "medical", + "insurance", + "legal", + "law", + "notifications", + "scheduling", + "real estate", + "property", + "retail", + "ecommerce", + "sales", + "marketing", + "software", + "technology", + "tech", + "media", + "surveys", + "market research", + "travel", + "hospitality", + "hotel", + ] + ] + """Industry classification.""" + + jurisdiction_of_incorporation: Required[str] + legal_name: Required[str] - """Legal name of the enterprise""" + """Legal name of the enterprise.""" number_of_employees: Required[Literal["1-10", "11-50", "51-200", "201-500", "501-2000", "2001-10000", "10001+"]] - """Employee count range""" + """Approximate headcount range. - organization_contact: Required[OrganizationContactParam] - """Organization contact information. - - Note: the response returns this object with the phone field as 'phone' (not - 'phone_number'). + Used for vetting heuristics; pick the bucket that contains your current employee + count. """ + organization_contact: Required[OrganizationContactParam] + organization_legal_type: Required[Literal["corporation", "llc", "partnership", "nonprofit", "other"]] - """Legal structure 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. + """ organization_physical_address: Required[PhysicalAddressParam] organization_type: Required[Literal["commercial", "government", "non_profit"]] - """Type of organization""" + """Organization category for vetting purposes: + + - `commercial` — for-profit business entities (LLC, corp, partnership, sole + proprietorship). Most callers fall here. + - `government` — federal/state/local government bodies. + - `non_profit` — registered 501(c)(3)/equivalent (incl. educational + institutions, charities, religious organisations). + """ website: Required[str] - """Enterprise website URL. Accepts any string — no URL format validation enforced.""" - corporate_registration_number: str - """Corporate registration number (optional)""" + corporate_registration_number: Optional[str] + """Optional corporate-registration / company-number identifier.""" customer_reference: str - """Optional customer reference identifier for your own tracking""" + """Optional free-form string the caller can attach for their own bookkeeping. - dun_bradstreet_number: str - """D-U-N-S Number (optional)""" + Telnyx does not interpret it. + """ - primary_business_domain_sic_code: str - """SIC Code (optional)""" + dun_bradstreet_number: Optional[str] + """Optional D-U-N-S Number.""" - professional_license_number: str - """Professional license number (optional)""" + primary_business_domain_sic_code: Optional[str] + """Optional SIC code for the primary line of business.""" + + professional_license_number: Optional[str] + """Optional professional-license number for regulated industries.""" role_type: Literal["enterprise", "bpo"] - """Role type in Branded Calling / Number Reputation services""" + """ + `enterprise` for an organization registering its own DIRs; `bpo` for a Business + Process Outsourcer placing calls on behalf of one or more enterprises. + """ diff --git a/src/telnyx/types/enterprise_create_response.py b/src/telnyx/types/enterprise_create_response.py index 82ff1b5f..1b551042 100644 --- a/src/telnyx/types/enterprise_create_response.py +++ b/src/telnyx/types/enterprise_create_response.py @@ -1,7 +1,5 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import Optional - from .._models import BaseModel from .enterprise_public import EnterprisePublic @@ -9,4 +7,4 @@ class EnterpriseCreateResponse(BaseModel): - data: Optional[EnterprisePublic] = None + data: EnterprisePublic diff --git a/src/telnyx/types/enterprise_list_params.py b/src/telnyx/types/enterprise_list_params.py index f36a17c5..12f42899 100644 --- a/src/telnyx/types/enterprise_list_params.py +++ b/src/telnyx/types/enterprise_list_params.py @@ -11,10 +11,13 @@ class EnterpriseListParams(TypedDict, total=False): legal_name: str - """Filter by legal name (partial match)""" + """Filter by legal name (partial match).""" page_number: Annotated[int, PropertyInfo(alias="page[number]")] - """Page number (1-indexed)""" + """1-based page number. + + Out-of-range values return an empty page with correct meta. + """ page_size: Annotated[int, PropertyInfo(alias="page[size]")] - """Number of items per page""" + """Items per page. Default 10. Maximum 250; values above are clamped to 250.""" diff --git a/src/telnyx/types/enterprise_public.py b/src/telnyx/types/enterprise_public.py index 0ff758c4..2a5665f1 100644 --- a/src/telnyx/types/enterprise_public.py +++ b/src/telnyx/types/enterprise_public.py @@ -2,7 +2,6 @@ from typing import Optional from datetime import datetime -from typing_extensions import Literal from .._models import BaseModel from .billing_address import BillingAddress @@ -15,70 +14,63 @@ class EnterprisePublic(BaseModel): id: Optional[str] = None - """Unique identifier of the enterprise""" billing_address: Optional[BillingAddress] = None billing_contact: Optional[BillingContact] = None + branded_calling_enabled: Optional[bool] = None + """ + True once Branded Calling has been activated on this enterprise (see + `POST /enterprises/{id}/branded_calling`). + """ + corporate_registration_number: Optional[str] = None - """Corporate registration number""" + """Optional corporate-registration / company-number identifier.""" country_code: Optional[str] = None - """ISO 3166-1 alpha-2 country code""" created_at: Optional[datetime] = None - """When the enterprise was created""" customer_reference: Optional[str] = None - """Customer reference identifier""" doing_business_as: Optional[str] = None - """DBA name""" dun_bradstreet_number: Optional[str] = None - """D-U-N-S Number""" + """Optional D-U-N-S Number issued by Dun & Bradstreet.""" fein: Optional[str] = None - """Federal Employer Identification Number""" industry: Optional[str] = None - """Industry classification""" + + jurisdiction_of_incorporation: Optional[str] = None legal_name: Optional[str] = None - """Legal name of the enterprise""" - number_of_employees: Optional[Literal["1-10", "11-50", "51-200", "201-500", "501-2000", "2001-10000", "10001+"]] = ( - None - ) - """Employee count range""" + number_of_employees: Optional[str] = None - organization_contact: Optional[OrganizationContact] = None - """Organization contact information. - - Note: the response returns this object with the phone field as 'phone' (not - 'phone_number'). + number_reputation_enabled: Optional[bool] = None + """ + True once Phone Number Reputation has been enabled on this enterprise (see + `POST /enterprises/{id}/reputation`). """ - organization_legal_type: Optional[Literal["corporation", "llc", "partnership", "nonprofit", "other"]] = None - """Legal structure type""" + organization_contact: Optional[OrganizationContact] = None + + organization_legal_type: Optional[str] = None organization_physical_address: Optional[PhysicalAddress] = None - organization_type: Optional[Literal["commercial", "government", "non_profit"]] = None - """Type of organization""" + organization_type: Optional[str] = None primary_business_domain_sic_code: Optional[str] = None - """SIC Code""" + """Optional SIC code for the primary line of business.""" professional_license_number: Optional[str] = None - """Professional license number""" + """Optional professional-license number for regulated industries.""" - role_type: Optional[Literal["enterprise", "bpo"]] = None - """Role type in Branded Calling / Number Reputation services""" + role_type: Optional[str] = None updated_at: Optional[datetime] = None - """When the enterprise was last updated""" website: Optional[str] = None - """Company website URL""" diff --git a/src/telnyx/types/enterprise_retrieve_response.py b/src/telnyx/types/enterprise_retrieve_response.py index 7ad609fd..10335698 100644 --- a/src/telnyx/types/enterprise_retrieve_response.py +++ b/src/telnyx/types/enterprise_retrieve_response.py @@ -1,7 +1,5 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import Optional - from .._models import BaseModel from .enterprise_public import EnterprisePublic @@ -9,4 +7,4 @@ class EnterpriseRetrieveResponse(BaseModel): - data: Optional[EnterprisePublic] = None + data: EnterprisePublic diff --git a/src/telnyx/types/enterprise_update_params.py b/src/telnyx/types/enterprise_update_params.py index d5fde94c..0a452e92 100644 --- a/src/telnyx/types/enterprise_update_params.py +++ b/src/telnyx/types/enterprise_update_params.py @@ -2,6 +2,7 @@ from __future__ import annotations +from typing import Optional from typing_extensions import Literal, TypedDict from .billing_address_param import BillingAddressParam @@ -17,47 +18,78 @@ class EnterpriseUpdateParams(TypedDict, total=False): billing_contact: BillingContactParam - corporate_registration_number: str - """Corporate registration number""" + corporate_registration_number: Optional[str] customer_reference: str - """Customer reference identifier""" doing_business_as: str - """DBA name""" - dun_bradstreet_number: str - """D-U-N-S Number""" + dun_bradstreet_number: Optional[str] fein: str - """Federal Employer Identification Number. Format: XX-XXXXXXX or XXXXXXXXX""" - industry: str - """Industry classification""" + industry: Literal[ + "accounting", + "finance", + "billing", + "collections", + "business", + "charity", + "nonprofit", + "communications", + "telecom", + "customer service", + "support", + "delivery", + "shipping", + "logistics", + "education", + "financial", + "banking", + "government", + "public", + "healthcare", + "health", + "pharmacy", + "medical", + "insurance", + "legal", + "law", + "notifications", + "scheduling", + "real estate", + "property", + "retail", + "ecommerce", + "sales", + "marketing", + "software", + "technology", + "tech", + "media", + "surveys", + "market research", + "travel", + "hospitality", + "hotel", + ] + + jurisdiction_of_incorporation: str + """Updated state/province/country of incorporation. Optional on update.""" legal_name: str - """Legal name of the enterprise""" + """Legal name of the enterprise.""" - number_of_employees: Literal["1-10", "11-50", "51-200", "201-500", "501-2000", "2001-10000", "10001+"] - """Employee count range""" + number_of_employees: str organization_contact: OrganizationContactParam - """Organization contact information. - Note: the response returns this object with the phone field as 'phone' (not - 'phone_number'). - """ - - organization_legal_type: Literal["corporation", "llc", "partnership", "nonprofit", "other"] - """Legal structure type""" + organization_legal_type: str organization_physical_address: PhysicalAddressParam - primary_business_domain_sic_code: str - """SIC Code""" + primary_business_domain_sic_code: Optional[str] - professional_license_number: str - """Professional license number""" + professional_license_number: Optional[str] website: str - """Company website URL""" diff --git a/src/telnyx/types/enterprise_update_response.py b/src/telnyx/types/enterprise_update_response.py index 8ec5e815..ba6e1ac7 100644 --- a/src/telnyx/types/enterprise_update_response.py +++ b/src/telnyx/types/enterprise_update_response.py @@ -1,7 +1,5 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import Optional - from .._models import BaseModel from .enterprise_public import EnterprisePublic @@ -9,4 +7,4 @@ class EnterpriseUpdateResponse(BaseModel): - data: Optional[EnterprisePublic] = None + data: EnterprisePublic diff --git a/src/telnyx/types/enterprises/__init__.py b/src/telnyx/types/enterprises/__init__.py index b0427e0f..46601025 100644 --- a/src/telnyx/types/enterprises/__init__.py +++ b/src/telnyx/types/enterprises/__init__.py @@ -2,6 +2,10 @@ from __future__ import annotations +from .dir_list_params import DirListParams as DirListParams +from .dir_create_params import DirCreateParams as DirCreateParams +from .dir_list_response import DirListResponse as DirListResponse +from .dir_create_response import DirCreateResponse as DirCreateResponse from .reputation_enable_params import ReputationEnableParams as ReputationEnableParams from .reputation_enable_response import ReputationEnableResponse as ReputationEnableResponse from .enterprise_reputation_public import EnterpriseReputationPublic as EnterpriseReputationPublic diff --git a/src/telnyx/types/enterprises/dir/__init__.py b/src/telnyx/types/enterprises/dir/__init__.py new file mode 100644 index 00000000..f8ee8b14 --- /dev/null +++ b/src/telnyx/types/enterprises/dir/__init__.py @@ -0,0 +1,3 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations diff --git a/src/telnyx/types/enterprises/dir_create_params.py b/src/telnyx/types/enterprises/dir_create_params.py new file mode 100644 index 00000000..00cf1e5a --- /dev/null +++ b/src/telnyx/types/enterprises/dir_create_params.py @@ -0,0 +1,93 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Iterable +from typing_extensions import Literal, Required, TypedDict + +from ..._types import SequenceNotStr + +__all__ = ["DirCreateParams", "Document"] + + +class DirCreateParams(TypedDict, total=False): + authorizer_email: Required[str] + """Contact email of the authorizer. + + Telnyx may send verification or infringement-notice email here; use a monitored + mailbox. + """ + + authorizer_name: Required[str] + """Name of the person at your enterprise who is authorizing this DIR registration. + + Must be a real individual (used for audit and trademark-claim contests). + """ + + certify_brand_is_accurate: Required[Literal[True]] + """Must be `true`.""" + + certify_ip_ownership: Required[Literal[True]] + """Must be `true`. Confirms ownership of any logos/trademarks shown.""" + + certify_no_shaft_content: Required[Literal[True]] + """Must be `true`. + + Confirms this DIR is not used for SHAFT content (Sex, Hate, Alcohol, Firearms, + Tobacco) where prohibited. + """ + + display_name: Required[str] + """Name shown to call recipients. No emoji; not whitespace-only.""" + + call_reasons: SequenceNotStr[str] + """1–10 reasons your business calls customers. + + Validate phrasing against `POST /call_reasons/validate`. + """ + + documents: Iterable[Document] + """Supporting documents. Each `document_id` may appear at most once on a DIR.""" + + logo_url: str + """Publicly accessible HTTPS URL (max 128 chars) to a 256x256 BMP logo (max 1 MB).""" + + reselling: bool + """ + Set to true if your organization places calls on behalf of other enterprises + (BPO/reseller). + """ + + +class Document(TypedDict, total=False): + document_id: Required[str] + """ + Id returned by the Telnyx Documents API after you upload the file (upload via + `POST /v2/documents`; see https://developers.telnyx.com/api/documents). + """ + + document_type: Required[ + Literal[ + "letter_of_authorization", + "business_registration", + "articles_of_incorporation", + "tax_document", + "ein_letter", + "trademark_registration", + "website_ownership", + "business_license", + "professional_license", + "government_id", + "utility_bill", + "bank_statement", + "other", + ] + ] + """Type of supporting document. + + Pick the closest match to what the file actually contains; `other` triggers + manual vetting and may slow approval. The matching short_name reference list is + at `GET /v2/dir/document_types`. + """ + + description: str diff --git a/src/telnyx/types/enterprises/dir_create_response.py b/src/telnyx/types/enterprises/dir_create_response.py new file mode 100644 index 00000000..403ef5a1 --- /dev/null +++ b/src/telnyx/types/enterprises/dir_create_response.py @@ -0,0 +1,139 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional +from datetime import datetime +from typing_extensions import Literal + +from ..._models import BaseModel + +__all__ = ["DirCreateResponse", "Data", "DataCallReason", "DataDocument", "DataRejectionReason"] + + +class DataCallReason(BaseModel): + created_at: Optional[datetime] = None + + reason: Optional[str] = None + + +class DataDocument(BaseModel): + document_id: str + """ + Id returned by the Telnyx Documents API after you upload the file (upload via + `POST /v2/documents`; see https://developers.telnyx.com/api/documents). + """ + + document_type: Literal[ + "letter_of_authorization", + "business_registration", + "articles_of_incorporation", + "tax_document", + "ein_letter", + "trademark_registration", + "website_ownership", + "business_license", + "professional_license", + "government_id", + "utility_bill", + "bank_statement", + "other", + ] + """Type of supporting document. + + Pick the closest match to what the file actually contains; `other` triggers + manual vetting and may slow approval. The matching short_name reference list is + at `GET /v2/dir/document_types`. + """ + + description: Optional[str] = None + + +class DataRejectionReason(BaseModel): + code: Optional[str] = None + + detail: Optional[str] = None + + message: Optional[str] = None + """Customer-visible free-text comment from the Telnyx vetting team. + + Only the first entry of `rejection_reasons` carries this; the rest are `null`. + """ + + title: Optional[str] = None + + +class Data(BaseModel): + id: Optional[str] = None + + authorizer_email: Optional[str] = None + + authorizer_name: Optional[str] = None + + call_reasons: Optional[List[DataCallReason]] = None + + certify_brand_is_accurate: Optional[bool] = None + + certify_ip_ownership: Optional[bool] = None + + certify_no_shaft_content: Optional[bool] = None + + created_at: Optional[datetime] = None + + display_name: Optional[str] = None + + documents: Optional[List[DataDocument]] = None + + enterprise_id: Optional[str] = None + + expiring_at: Optional[datetime] = None + + logo_url: Optional[str] = None + + rejected_at: Optional[datetime] = None + + rejection_reasons: Optional[List[DataRejectionReason]] = None + """ + Populated when `status` is `rejected`; cleared on `/submit` or successful + approval. + """ + + reselling: Optional[bool] = None + + status: Optional[ + Literal[ + "draft", + "submitted", + "in_review", + "verified", + "rejected", + "unsuccessful", + "suspended", + "expired", + "infringement_claimed", + "permanently_rejected", + ] + ] = None + """DIR lifecycle status. + + - `draft` — newly created; editable; not yet submitted. + - `submitted` / `in_review` — Telnyx is reviewing. + - `verified` — approved; phone numbers may be attached. + - `rejected` — Telnyx rejected this submission; `rejection_reasons` is + populated; customer can edit and resubmit. + - `unsuccessful` — system-side error during processing; customer can edit and + resubmit. + - `suspended` — temporarily disabled (e.g. by an active infringement claim). + - `expired` — verification expired; customer must resubmit. + - `infringement_claimed` — a trademark/impersonation claim is open against this + DIR. + - `permanently_rejected` — terminal; cannot be resubmitted. + """ + + submitted_at: Optional[datetime] = None + + updated_at: Optional[datetime] = None + + verified_at: Optional[datetime] = None + + +class DirCreateResponse(BaseModel): + data: Data diff --git a/src/telnyx/types/enterprises/dir_list_params.py b/src/telnyx/types/enterprises/dir_list_params.py new file mode 100644 index 00000000..b9a63156 --- /dev/null +++ b/src/telnyx/types/enterprises/dir_list_params.py @@ -0,0 +1,80 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Union +from datetime import datetime +from typing_extensions import Literal, Annotated, TypedDict + +from ..._utils import PropertyInfo + +__all__ = ["DirListParams"] + + +class DirListParams(TypedDict, total=False): + filter_expiring_at_gte: Annotated[ + Union[str, datetime], PropertyInfo(alias="filter[expiring_at][gte]", format="iso8601") + ] + """Return only DIRs whose `expiring_at` is at or after this ISO-8601 timestamp.""" + + filter_expiring_at_lte: Annotated[ + Union[str, datetime], PropertyInfo(alias="filter[expiring_at][lte]", format="iso8601") + ] + """Return only DIRs whose `expiring_at` is at or before this ISO-8601 timestamp.""" + + filter_expiring_within_days: Annotated[int, PropertyInfo(alias="filter[expiring_within_days]")] + """ + Convenience: returns DIRs whose `expiring_at` falls within the next N days + (1–365). Equivalent to setting `filter[expiring_at][gte]=` + + `filter[expiring_at][lte]=`. Mutually exclusive with the explicit + `[gte]`/`[lte]` filters — combining returns 400. + """ + + 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.""" + + search: str + """Case-insensitive partial match on `display_name`.""" + + sort: Literal[ + "created_at", + "-created_at", + "updated_at", + "-updated_at", + "display_name", + "-display_name", + "status", + "-status", + "submitted_at", + "-submitted_at", + "verified_at", + "-verified_at", + "expiring_at", + "-expiring_at", + ] + """Sort field. + + Allowed: `created_at`, `updated_at`, `display_name`, `status`, `submitted_at`, + `verified_at`, `expiring_at`. Prefix with `-` for descending. Default + `-created_at`. + """ + + status: Literal[ + "draft", + "submitted", + "in_review", + "verified", + "rejected", + "unsuccessful", + "suspended", + "expired", + "infringement_claimed", + "permanently_rejected", + ] + """Filter by DIR status.""" diff --git a/src/telnyx/types/enterprises/dir_list_response.py b/src/telnyx/types/enterprises/dir_list_response.py new file mode 100644 index 00000000..36e25043 --- /dev/null +++ b/src/telnyx/types/enterprises/dir_list_response.py @@ -0,0 +1,135 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional +from datetime import datetime +from typing_extensions import Literal + +from ..._models import BaseModel + +__all__ = ["DirListResponse", "CallReason", "Document", "RejectionReason"] + + +class CallReason(BaseModel): + created_at: Optional[datetime] = None + + reason: Optional[str] = None + + +class Document(BaseModel): + document_id: str + """ + Id returned by the Telnyx Documents API after you upload the file (upload via + `POST /v2/documents`; see https://developers.telnyx.com/api/documents). + """ + + document_type: Literal[ + "letter_of_authorization", + "business_registration", + "articles_of_incorporation", + "tax_document", + "ein_letter", + "trademark_registration", + "website_ownership", + "business_license", + "professional_license", + "government_id", + "utility_bill", + "bank_statement", + "other", + ] + """Type of supporting document. + + Pick the closest match to what the file actually contains; `other` triggers + manual vetting and may slow approval. The matching short_name reference list is + at `GET /v2/dir/document_types`. + """ + + description: Optional[str] = None + + +class RejectionReason(BaseModel): + code: Optional[str] = None + + detail: Optional[str] = None + + message: Optional[str] = None + """Customer-visible free-text comment from the Telnyx vetting team. + + Only the first entry of `rejection_reasons` carries this; the rest are `null`. + """ + + title: Optional[str] = None + + +class DirListResponse(BaseModel): + id: Optional[str] = None + + authorizer_email: Optional[str] = None + + authorizer_name: Optional[str] = None + + call_reasons: Optional[List[CallReason]] = None + + certify_brand_is_accurate: Optional[bool] = None + + certify_ip_ownership: Optional[bool] = None + + certify_no_shaft_content: Optional[bool] = None + + created_at: Optional[datetime] = None + + display_name: Optional[str] = None + + documents: Optional[List[Document]] = None + + enterprise_id: Optional[str] = None + + expiring_at: Optional[datetime] = None + + logo_url: Optional[str] = None + + rejected_at: Optional[datetime] = None + + rejection_reasons: Optional[List[RejectionReason]] = None + """ + Populated when `status` is `rejected`; cleared on `/submit` or successful + approval. + """ + + reselling: Optional[bool] = None + + status: Optional[ + Literal[ + "draft", + "submitted", + "in_review", + "verified", + "rejected", + "unsuccessful", + "suspended", + "expired", + "infringement_claimed", + "permanently_rejected", + ] + ] = None + """DIR lifecycle status. + + - `draft` — newly created; editable; not yet submitted. + - `submitted` / `in_review` — Telnyx is reviewing. + - `verified` — approved; phone numbers may be attached. + - `rejected` — Telnyx rejected this submission; `rejection_reasons` is + populated; customer can edit and resubmit. + - `unsuccessful` — system-side error during processing; customer can edit and + resubmit. + - `suspended` — temporarily disabled (e.g. by an active infringement claim). + - `expired` — verification expired; customer must resubmit. + - `infringement_claimed` — a trademark/impersonation claim is open against this + DIR. + - `permanently_rejected` — terminal; cannot be resubmitted. + """ + + submitted_at: Optional[datetime] = None + + updated_at: Optional[datetime] = None + + verified_at: Optional[datetime] = None diff --git a/src/telnyx/types/enterprises/enterprise_reputation_public.py b/src/telnyx/types/enterprises/enterprise_reputation_public.py index c44093e1..4b119427 100644 --- a/src/telnyx/types/enterprises/enterprise_reputation_public.py +++ b/src/telnyx/types/enterprises/enterprise_reputation_public.py @@ -11,22 +11,29 @@ class EnterpriseReputationPublic(BaseModel): check_frequency: Optional[Literal["business_daily", "daily", "weekly", "biweekly", "monthly", "never"]] = None - """Frequency for refreshing reputation data""" + """ + How often Telnyx refreshes the stored reputation data for this enterprise's + registered numbers. + """ created_at: Optional[datetime] = None - """When the reputation settings were created""" enterprise_id: Optional[str] = None - """ID of the associated enterprise""" loa_document_id: Optional[str] = None - """ID of the signed LOA document""" + """Id of the signed LOA document.""" + + loa_status: Optional[Literal["pending", "approved", "rejected"]] = None + """Customer-facing Letter-of-Authorization verification state. + + `approved` is required (alongside reputation status) before phone numbers can be + added. + """ rejection_reasons: Optional[List[str]] = None - """Reasons for rejection (present when status is rejected)""" + """Populated when `status` is `rejected`.""" - status: Optional[Literal["pending", "approved", "rejected", "deleted"]] = None - """Current enrollment status""" + status: Optional[Literal["pending", "approved", "deleted", "rejected"]] = None + """Lifecycle status of the enterprise's Phone Number Reputation activation.""" updated_at: Optional[datetime] = None - """When the reputation settings were last updated""" diff --git a/src/telnyx/types/enterprises/reputation/__init__.py b/src/telnyx/types/enterprises/reputation/__init__.py index e47c43b9..1566b521 100644 --- a/src/telnyx/types/enterprises/reputation/__init__.py +++ b/src/telnyx/types/enterprises/reputation/__init__.py @@ -2,8 +2,14 @@ from __future__ import annotations +from .loa_render_params import LoaRenderParams as LoaRenderParams +from .loa_update_params import LoaUpdateParams as LoaUpdateParams from .number_list_params import NumberListParams as NumberListParams +from .loa_update_response import LoaUpdateResponse as LoaUpdateResponse +from .number_list_response import NumberListResponse as NumberListResponse +from .number_refresh_params import NumberRefreshParams as NumberRefreshParams from .number_retrieve_params import NumberRetrieveParams as NumberRetrieveParams from .number_associate_params import NumberAssociateParams as NumberAssociateParams +from .number_refresh_response import NumberRefreshResponse as NumberRefreshResponse from .number_retrieve_response import NumberRetrieveResponse as NumberRetrieveResponse from .number_associate_response import NumberAssociateResponse as NumberAssociateResponse diff --git a/src/telnyx/types/enterprises/reputation/loa_render_params.py b/src/telnyx/types/enterprises/reputation/loa_render_params.py new file mode 100644 index 00000000..f30109d7 --- /dev/null +++ b/src/telnyx/types/enterprises/reputation/loa_render_params.py @@ -0,0 +1,65 @@ +# 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__ = ["LoaRenderParams", "Agent", "Signature"] + + +class LoaRenderParams(TypedDict, total=False): + agent: Agent + """Third-party reseller / partner managing the enterprise's phone numbers. + + Omit when the enterprise works directly with Telnyx. + """ + + signature: Signature + """Optional signature embedded in the rendered PDF. + + When omitted the PDF is returned unsigned for the customer to sign and upload. + """ + + +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. + + When omitted the PDF is returned unsigned for the customer to sign and upload. + """ + + image_base64: Required[str] + """Base64-encoded signature image.""" + + signer_name: Optional[str] diff --git a/src/telnyx/types/enterprises/reputation/loa_update_params.py b/src/telnyx/types/enterprises/reputation/loa_update_params.py new file mode 100644 index 00000000..5984f41f --- /dev/null +++ b/src/telnyx/types/enterprises/reputation/loa_update_params.py @@ -0,0 +1,16 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, TypedDict + +__all__ = ["LoaUpdateParams"] + + +class LoaUpdateParams(TypedDict, total=False): + loa_document_id: Required[str] + """Id of the new signed LOA document (from the Telnyx Documents API). + + Changing it resets LOA approval; the new document must be approved before more + numbers can be added. + """ diff --git a/src/telnyx/types/enterprises/reputation/loa_update_response.py b/src/telnyx/types/enterprises/reputation/loa_update_response.py new file mode 100644 index 00000000..836d71a3 --- /dev/null +++ b/src/telnyx/types/enterprises/reputation/loa_update_response.py @@ -0,0 +1,10 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from ...._models import BaseModel +from ..enterprise_reputation_public import EnterpriseReputationPublic + +__all__ = ["LoaUpdateResponse"] + + +class LoaUpdateResponse(BaseModel): + data: EnterpriseReputationPublic diff --git a/src/telnyx/types/enterprises/reputation/number_associate_params.py b/src/telnyx/types/enterprises/reputation/number_associate_params.py index 56cf75ad..31831e53 100644 --- a/src/telnyx/types/enterprises/reputation/number_associate_params.py +++ b/src/telnyx/types/enterprises/reputation/number_associate_params.py @@ -11,4 +11,4 @@ class NumberAssociateParams(TypedDict, total=False): phone_numbers: Required[SequenceNotStr[str]] - """List of phone numbers to associate for reputation monitoring (max 100)""" + """1–100 phone numbers in E.164 format with a leading `+`.""" diff --git a/src/telnyx/types/enterprises/reputation/number_associate_response.py b/src/telnyx/types/enterprises/reputation/number_associate_response.py index e1fd5fb4..7d3444de 100644 --- a/src/telnyx/types/enterprises/reputation/number_associate_response.py +++ b/src/telnyx/types/enterprises/reputation/number_associate_response.py @@ -4,29 +4,56 @@ from datetime import datetime from ...._models import BaseModel -from ...shared.meta_info import MetaInfo +from ...shared.reputation_data import ReputationData -__all__ = ["NumberAssociateResponse", "Data"] +__all__ = ["NumberAssociateResponse", "Data", "Meta"] class Data(BaseModel): id: Optional[str] = None - """Unique identifier""" created_at: Optional[datetime] = None - """When the number was associated""" enterprise_id: Optional[str] = None - """ID of the associated enterprise""" phone_number: Optional[str] = None - """Phone number in E.164 format""" + """E.164 with leading `+`.""" + + reputation_data: Optional[ReputationData] = None + """`null` until the first refresh has been collected for this number.""" updated_at: Optional[datetime] = None - """When the record was last updated""" + + +class Meta(BaseModel): + """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. + """ + + page_number: int + """1-based index of this page. + + Echoes the `page[number]` query parameter (default `1`). + """ + + page_size: int + """Number of items returned in this page's `data` array. Capped at 250.""" + + total_pages: int + """Total number of pages available given the current `page_size`.""" + + total_results: int + """Total number of items across all pages (excludes soft-deleted rows).""" class NumberAssociateResponse(BaseModel): - data: Optional[List[Data]] = None + data: List[Data] + + meta: Meta + """JSON:API pagination metadata returned with every paginated list response. - meta: Optional[MetaInfo] = None + 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/enterprises/reputation/number_list_params.py b/src/telnyx/types/enterprises/reputation/number_list_params.py index 26426662..46dd4bee 100644 --- a/src/telnyx/types/enterprises/reputation/number_list_params.py +++ b/src/telnyx/types/enterprises/reputation/number_list_params.py @@ -11,10 +11,13 @@ class NumberListParams(TypedDict, total=False): page_number: Annotated[int, PropertyInfo(alias="page[number]")] - """Page number (1-indexed)""" + """1-based page number. + + Out-of-range values return an empty page with correct meta. + """ page_size: Annotated[int, PropertyInfo(alias="page[size]")] - """Number of items per page""" + """Items per page. Default 10. Maximum 250; values above are clamped to 250.""" phone_number: str - """Filter by specific phone number (E.164 format)""" + """Filter by specific phone number (E.164 format).""" diff --git a/src/telnyx/types/enterprises/reputation/number_list_response.py b/src/telnyx/types/enterprises/reputation/number_list_response.py new file mode 100644 index 00000000..016cdfb6 --- /dev/null +++ b/src/telnyx/types/enterprises/reputation/number_list_response.py @@ -0,0 +1,25 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional +from datetime import datetime + +from ...._models import BaseModel +from ...shared.reputation_data import ReputationData + +__all__ = ["NumberListResponse"] + + +class NumberListResponse(BaseModel): + id: Optional[str] = None + + created_at: Optional[datetime] = None + + enterprise_id: Optional[str] = None + + phone_number: Optional[str] = None + """E.164 with leading `+`.""" + + reputation_data: Optional[ReputationData] = None + """`null` until the first refresh has been collected for this number.""" + + updated_at: Optional[datetime] = None diff --git a/src/telnyx/types/enterprises/reputation/number_refresh_params.py b/src/telnyx/types/enterprises/reputation/number_refresh_params.py new file mode 100644 index 00000000..c8d0cced --- /dev/null +++ b/src/telnyx/types/enterprises/reputation/number_refresh_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 Required, TypedDict + +from ...._types import SequenceNotStr + +__all__ = ["NumberRefreshParams"] + + +class NumberRefreshParams(TypedDict, total=False): + phone_numbers: Required[SequenceNotStr[str]] + """Phone numbers to refresh reputation data for. + + 1–100 numbers per request, each in E.164 format. Reputation refreshes are + subject to per-enterprise rate limits. + """ diff --git a/src/telnyx/types/enterprises/reputation/number_refresh_response.py b/src/telnyx/types/enterprises/reputation/number_refresh_response.py new file mode 100644 index 00000000..0b92103c --- /dev/null +++ b/src/telnyx/types/enterprises/reputation/number_refresh_response.py @@ -0,0 +1,31 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional + +from ...._models import BaseModel + +__all__ = ["NumberRefreshResponse", "Data", "DataResult"] + + +class DataResult(BaseModel): + phone_number: str + + success: bool + + error: Optional[str] = None + """`null` when `success` is `true`; carries an error message otherwise.""" + + +class Data(BaseModel): + results: List[DataResult] + """Per-number outcome of the refresh.""" + + total_failed: int + + total_requested: int + + total_successful: int + + +class NumberRefreshResponse(BaseModel): + data: Data diff --git a/src/telnyx/types/enterprises/reputation/number_retrieve_params.py b/src/telnyx/types/enterprises/reputation/number_retrieve_params.py index 5d1e7c69..f7bf00f4 100644 --- a/src/telnyx/types/enterprises/reputation/number_retrieve_params.py +++ b/src/telnyx/types/enterprises/reputation/number_retrieve_params.py @@ -13,5 +13,5 @@ class NumberRetrieveParams(TypedDict, total=False): fresh: bool """When true, fetches fresh reputation data (incurs API cost). - When false, returns cached data. + When false (default), returns cached data. """ diff --git a/src/telnyx/types/enterprises/reputation/number_retrieve_response.py b/src/telnyx/types/enterprises/reputation/number_retrieve_response.py index 3fabc71c..9bcccafb 100644 --- a/src/telnyx/types/enterprises/reputation/number_retrieve_response.py +++ b/src/telnyx/types/enterprises/reputation/number_retrieve_response.py @@ -1,12 +1,29 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional +from datetime import datetime from ...._models import BaseModel -from ...shared.reputation_phone_number_with_reputation_data import ReputationPhoneNumberWithReputationData +from ...shared.reputation_data import ReputationData -__all__ = ["NumberRetrieveResponse"] +__all__ = ["NumberRetrieveResponse", "Data"] + + +class Data(BaseModel): + id: Optional[str] = None + + created_at: Optional[datetime] = None + + enterprise_id: Optional[str] = None + + phone_number: Optional[str] = None + """E.164 with leading `+`.""" + + reputation_data: Optional[ReputationData] = None + """`null` until the first refresh has been collected for this number.""" + + updated_at: Optional[datetime] = None class NumberRetrieveResponse(BaseModel): - data: Optional[ReputationPhoneNumberWithReputationData] = None + data: Data diff --git a/src/telnyx/types/enterprises/reputation_enable_params.py b/src/telnyx/types/enterprises/reputation_enable_params.py index c0894e37..cbe35f87 100644 --- a/src/telnyx/types/enterprises/reputation_enable_params.py +++ b/src/telnyx/types/enterprises/reputation_enable_params.py @@ -10,9 +10,13 @@ class ReputationEnableParams(TypedDict, total=False): loa_document_id: Required[str] """ - ID of the signed Letter of Authorization (LOA) document uploaded to the document - service + Id of the signed Letter of Authorization document, returned by the Telnyx + Documents API after upload (upload via `POST /v2/documents`; see + https://developers.telnyx.com/api/documents). """ check_frequency: Literal["business_daily", "daily", "weekly", "biweekly", "monthly", "never"] - """Frequency for automatically refreshing reputation data""" + """ + How often Telnyx refreshes the stored reputation data for this enterprise's + registered numbers. + """ diff --git a/src/telnyx/types/enterprises/reputation_enable_response.py b/src/telnyx/types/enterprises/reputation_enable_response.py index c22a6292..281c1780 100644 --- a/src/telnyx/types/enterprises/reputation_enable_response.py +++ b/src/telnyx/types/enterprises/reputation_enable_response.py @@ -1,7 +1,5 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import Optional - from ..._models import BaseModel from .enterprise_reputation_public import EnterpriseReputationPublic @@ -9,4 +7,4 @@ class ReputationEnableResponse(BaseModel): - data: Optional[EnterpriseReputationPublic] = None + data: EnterpriseReputationPublic diff --git a/src/telnyx/types/enterprises/reputation_retrieve_response.py b/src/telnyx/types/enterprises/reputation_retrieve_response.py index abb44ffb..98d61de8 100644 --- a/src/telnyx/types/enterprises/reputation_retrieve_response.py +++ b/src/telnyx/types/enterprises/reputation_retrieve_response.py @@ -1,7 +1,5 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import Optional - from ..._models import BaseModel from .enterprise_reputation_public import EnterpriseReputationPublic @@ -9,4 +7,4 @@ class ReputationRetrieveResponse(BaseModel): - data: Optional[EnterpriseReputationPublic] = None + data: EnterpriseReputationPublic diff --git a/src/telnyx/types/enterprises/reputation_update_frequency_params.py b/src/telnyx/types/enterprises/reputation_update_frequency_params.py index a3fd2f6b..9dca829a 100644 --- a/src/telnyx/types/enterprises/reputation_update_frequency_params.py +++ b/src/telnyx/types/enterprises/reputation_update_frequency_params.py @@ -9,4 +9,7 @@ class ReputationUpdateFrequencyParams(TypedDict, total=False): check_frequency: Required[Literal["business_daily", "daily", "weekly", "biweekly", "monthly", "never"]] - """New frequency for refreshing reputation data""" + """ + How often Telnyx refreshes the stored reputation data for this enterprise's + registered numbers. + """ diff --git a/src/telnyx/types/enterprises/reputation_update_frequency_response.py b/src/telnyx/types/enterprises/reputation_update_frequency_response.py index c1119c77..febe619f 100644 --- a/src/telnyx/types/enterprises/reputation_update_frequency_response.py +++ b/src/telnyx/types/enterprises/reputation_update_frequency_response.py @@ -1,7 +1,5 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import Optional - from ..._models import BaseModel from .enterprise_reputation_public import EnterpriseReputationPublic @@ -9,4 +7,4 @@ class ReputationUpdateFrequencyResponse(BaseModel): - data: Optional[EnterpriseReputationPublic] = None + data: EnterpriseReputationPublic diff --git a/src/telnyx/types/infringement_claim_contest_params.py b/src/telnyx/types/infringement_claim_contest_params.py new file mode 100644 index 00000000..45c8ff2a --- /dev/null +++ b/src/telnyx/types/infringement_claim_contest_params.py @@ -0,0 +1,54 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Iterable +from typing_extensions import Literal, Required, TypedDict + +__all__ = ["InfringementClaimContestParams", "Document"] + + +class InfringementClaimContestParams(TypedDict, total=False): + contest_notes: Required[str] + """Customer's response to the claim. 10–2000 characters.""" + + documents: Iterable[Document] + """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. + """ + + +class Document(TypedDict, total=False): + document_id: Required[str] + """ + Id returned by the Telnyx Documents API after you upload the file (upload via + `POST /v2/documents`; see https://developers.telnyx.com/api/documents). + """ + + document_type: Required[ + Literal[ + "letter_of_authorization", + "business_registration", + "articles_of_incorporation", + "tax_document", + "ein_letter", + "trademark_registration", + "website_ownership", + "business_license", + "professional_license", + "government_id", + "utility_bill", + "bank_statement", + "other", + ] + ] + """Type of supporting document. + + Pick the closest match to what the file actually contains; `other` triggers + manual vetting and may slow approval. The matching short_name reference list is + at `GET /v2/dir/document_types`. + """ + + description: str diff --git a/src/telnyx/types/infringement_claim_contest_response.py b/src/telnyx/types/infringement_claim_contest_response.py new file mode 100644 index 00000000..ada12724 --- /dev/null +++ b/src/telnyx/types/infringement_claim_contest_response.py @@ -0,0 +1,149 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional +from datetime import datetime +from typing_extensions import Literal + +from .._models import BaseModel + +__all__ = ["InfringementClaimContestResponse", "Data", "DataContestDocument", "DataContestHistory", "DataDir"] + + +class DataContestDocument(BaseModel): + document_id: str + """ + Id returned by the Telnyx Documents API after you upload the file (upload via + `POST /v2/documents`; see https://developers.telnyx.com/api/documents). + """ + + document_type: Literal[ + "letter_of_authorization", + "business_registration", + "articles_of_incorporation", + "tax_document", + "ein_letter", + "trademark_registration", + "website_ownership", + "business_license", + "professional_license", + "government_id", + "utility_bill", + "bank_statement", + "other", + ] + """Type of supporting document. + + Pick the closest match to what the file actually contains; `other` triggers + manual vetting and may slow approval. The matching short_name reference list is + at `GET /v2/dir/document_types`. + """ + + description: Optional[str] = None + + +class DataContestHistory(BaseModel): + """One round of customer contest evidence on an infringement claim. + + The aggregated documents across rounds live on the parent claim's `contest_documents`; this submission record carries only the per-round notes and document count. + """ + + document_count: Optional[int] = None + + notes: Optional[str] = None + + submitted_at: Optional[datetime] = None + + +class DataDir(BaseModel): + """Snapshot of the DIR the claim is filed against, embedded for convenience.""" + + id: Optional[str] = None + + display_name: Optional[str] = None + + enterprise_id: Optional[str] = None + + status: Optional[ + Literal[ + "draft", + "submitted", + "in_review", + "verified", + "rejected", + "unsuccessful", + "suspended", + "expired", + "infringement_claimed", + "permanently_rejected", + ] + ] = None + """DIR lifecycle status. + + - `draft` — newly created; editable; not yet submitted. + - `submitted` / `in_review` — Telnyx is reviewing. + - `verified` — approved; phone numbers may be attached. + - `rejected` — Telnyx rejected this submission; `rejection_reasons` is + populated; customer can edit and resubmit. + - `unsuccessful` — system-side error during processing; customer can edit and + resubmit. + - `suspended` — temporarily disabled (e.g. by an active infringement claim). + - `expired` — verification expired; customer must resubmit. + - `infringement_claimed` — a trademark/impersonation claim is open against this + DIR. + - `permanently_rejected` — terminal; cannot be resubmitted. + """ + + +class Data(BaseModel): + id: Optional[str] = None + + claim_date: Optional[datetime] = None + """When the claim was filed (set by the claimant's representative at file time).""" + + claim_description: Optional[str] = None + + claim_type: Optional[Literal["trademark", "copyright"]] = None + """Category of infringement being claimed.""" + + claimant_contact: Optional[str] = None + + claimant_name: Optional[str] = None + + contest_documents: Optional[List[DataContestDocument]] = None + """Aggregated across all customer contest submissions on this claim.""" + + contest_history: Optional[List[DataContestHistory]] = None + """Per-round submission audit trail. + + Each entry records one `POST /infringement_claims/{id}/contest` call (notes, + timestamp, document count). Aggregated documents live on `contest_documents`. + """ + + created_at: Optional[datetime] = None + + dir: Optional[DataDir] = None + """Snapshot of the DIR the claim is filed against, embedded for convenience.""" + + dir_id: Optional[str] = None + + enterprise_id: Optional[str] = None + + resolution: Optional[Literal["upheld", "rejected", "modified"]] = None + """Set only when `status` is `resolved`.""" + + resolution_date: Optional[datetime] = None + + resolution_notes: Optional[str] = None + + status: Optional[Literal["pending", "contested", "resolved"]] = None + """Lifecycle status. + + `pending` — newly filed; the DIR is auto-suspended. `contested` — you have + submitted contest evidence; awaiting Telnyx review. `resolved` — final. + """ + + updated_at: Optional[datetime] = None + + +class InfringementClaimContestResponse(BaseModel): + data: Data diff --git a/src/telnyx/types/infringement_claim_retrieve_response.py b/src/telnyx/types/infringement_claim_retrieve_response.py new file mode 100644 index 00000000..fb57b8fd --- /dev/null +++ b/src/telnyx/types/infringement_claim_retrieve_response.py @@ -0,0 +1,149 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional +from datetime import datetime +from typing_extensions import Literal + +from .._models import BaseModel + +__all__ = ["InfringementClaimRetrieveResponse", "Data", "DataContestDocument", "DataContestHistory", "DataDir"] + + +class DataContestDocument(BaseModel): + document_id: str + """ + Id returned by the Telnyx Documents API after you upload the file (upload via + `POST /v2/documents`; see https://developers.telnyx.com/api/documents). + """ + + document_type: Literal[ + "letter_of_authorization", + "business_registration", + "articles_of_incorporation", + "tax_document", + "ein_letter", + "trademark_registration", + "website_ownership", + "business_license", + "professional_license", + "government_id", + "utility_bill", + "bank_statement", + "other", + ] + """Type of supporting document. + + Pick the closest match to what the file actually contains; `other` triggers + manual vetting and may slow approval. The matching short_name reference list is + at `GET /v2/dir/document_types`. + """ + + description: Optional[str] = None + + +class DataContestHistory(BaseModel): + """One round of customer contest evidence on an infringement claim. + + The aggregated documents across rounds live on the parent claim's `contest_documents`; this submission record carries only the per-round notes and document count. + """ + + document_count: Optional[int] = None + + notes: Optional[str] = None + + submitted_at: Optional[datetime] = None + + +class DataDir(BaseModel): + """Snapshot of the DIR the claim is filed against, embedded for convenience.""" + + id: Optional[str] = None + + display_name: Optional[str] = None + + enterprise_id: Optional[str] = None + + status: Optional[ + Literal[ + "draft", + "submitted", + "in_review", + "verified", + "rejected", + "unsuccessful", + "suspended", + "expired", + "infringement_claimed", + "permanently_rejected", + ] + ] = None + """DIR lifecycle status. + + - `draft` — newly created; editable; not yet submitted. + - `submitted` / `in_review` — Telnyx is reviewing. + - `verified` — approved; phone numbers may be attached. + - `rejected` — Telnyx rejected this submission; `rejection_reasons` is + populated; customer can edit and resubmit. + - `unsuccessful` — system-side error during processing; customer can edit and + resubmit. + - `suspended` — temporarily disabled (e.g. by an active infringement claim). + - `expired` — verification expired; customer must resubmit. + - `infringement_claimed` — a trademark/impersonation claim is open against this + DIR. + - `permanently_rejected` — terminal; cannot be resubmitted. + """ + + +class Data(BaseModel): + id: Optional[str] = None + + claim_date: Optional[datetime] = None + """When the claim was filed (set by the claimant's representative at file time).""" + + claim_description: Optional[str] = None + + claim_type: Optional[Literal["trademark", "copyright"]] = None + """Category of infringement being claimed.""" + + claimant_contact: Optional[str] = None + + claimant_name: Optional[str] = None + + contest_documents: Optional[List[DataContestDocument]] = None + """Aggregated across all customer contest submissions on this claim.""" + + contest_history: Optional[List[DataContestHistory]] = None + """Per-round submission audit trail. + + Each entry records one `POST /infringement_claims/{id}/contest` call (notes, + timestamp, document count). Aggregated documents live on `contest_documents`. + """ + + created_at: Optional[datetime] = None + + dir: Optional[DataDir] = None + """Snapshot of the DIR the claim is filed against, embedded for convenience.""" + + dir_id: Optional[str] = None + + enterprise_id: Optional[str] = None + + resolution: Optional[Literal["upheld", "rejected", "modified"]] = None + """Set only when `status` is `resolved`.""" + + resolution_date: Optional[datetime] = None + + resolution_notes: Optional[str] = None + + status: Optional[Literal["pending", "contested", "resolved"]] = None + """Lifecycle status. + + `pending` — newly filed; the DIR is auto-suspended. `contested` — you have + submitted contest evidence; awaiting Telnyx review. `resolved` — final. + """ + + updated_at: Optional[datetime] = None + + +class InfringementClaimRetrieveResponse(BaseModel): + data: Data diff --git a/src/telnyx/types/model_metadata.py b/src/telnyx/types/model_metadata.py deleted file mode 100644 index 465f1372..00000000 --- a/src/telnyx/types/model_metadata.py +++ /dev/null @@ -1,124 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Dict, List, Optional -from datetime import datetime -from typing_extensions import Literal - -from .._models import BaseModel - -__all__ = ["ModelMetadata"] - - -class ModelMetadata(BaseModel): - """Metadata for a model available on Telnyx Inference. - - Returned by `GET /v2/ai/openai/models` (and the deprecated `GET /v2/ai/models`). Open-source models live under their Hugging Face organization (e.g. `moonshotai/Kimi-K2.6`, `zai-org/GLM-5.1-FP8`, `MiniMaxAI/MiniMax-M2.7`); fine-tuned models are owned by the Telnyx organization that trained them. - """ - - id: str - """Model identifier. - - For open-source models, follows the `{organization}/{model_name}` convention - from Hugging Face (e.g. `moonshotai/Kimi-K2.6`). - """ - - context_length: int - """ - Maximum total tokens (prompt + completion) supported by the model in a single - request. - """ - - created: datetime - """Timestamp at which the model was registered on Telnyx Inference (ISO 8601).""" - - languages: List[str] - """ISO language codes the model supports (e.g. `en`, `es`).""" - - license: str - """License the model is distributed under, e.g. - - `Apache 2.0`, `MIT`, `Llama 3 Community License`. - """ - - organization: str - """ - Organization that originally published the model, matching the prefix of `id` - for open-source models. - """ - - owned_by: str - """Owner of the model. - - `Telnyx` for Telnyx-hosted open-source models, the upstream provider name for - proxied models, or the Telnyx organization id for fine-tuned models. - """ - - parameters: int - """Total parameter count of the model.""" - - tier: Literal["small", "medium", "large", "unlisted"] - """Billing tier the model belongs to. - - Used together with `pricing` to determine cost per 1M tokens. - """ - - base_model: Optional[str] = None - """Base model the fine-tuned model was trained from. - - Only set for fine-tuned models. - """ - - description: Optional[str] = None - """Short, human-readable summary of what the model is best suited for.""" - - is_fine_tunable: Optional[bool] = None - """ - Whether the model can be used as a base for a fine-tuning job via - `POST /v2/ai/fine_tuning/jobs`. - """ - - is_vision_supported: Optional[bool] = None - """ - Whether the model accepts image inputs in chat completions (multimodal vision - support). - """ - - max_completion_tokens: Optional[int] = None - """Maximum number of completion (output) tokens the model will generate per - request. - - `null` if unconstrained beyond `context_length`. - """ - - object: Optional[str] = None - """Object type. Always `model`.""" - - parameters_str: Optional[str] = None - """Human-readable parameter count, e.g. `1.0T`, `753.9B`, `8B`.""" - - pricing: Optional[Dict[str, str]] = None - """Mapping of token kind to price, as strings to preserve precision. - - Typical keys are `prompt`, `cached_prompt`, and `completion`. When pricing is - available the block also includes `currency` (ISO 4217 code matching the - account's configured billing currency) and `unit` (the denomination the prices - are quoted in, currently always `1M_tokens` for token-priced models). - """ - - recommended_for_assistants: Optional[bool] = None - """ - Whether Telnyx currently recommends this model as the LLM powering a Telnyx AI - Assistant. - """ - - regions: Optional[List[str]] = None - """Public region names where the model is currently deployed (e.g. - - `us-central-1`, `eu-central-1`). - """ - - task: Optional[str] = None - """Primary task the model is intended for, e.g. - - `text-generation`, `audio-text-to-text`, `feature-extraction` (embeddings). - """ diff --git a/src/telnyx/types/network_interface.py b/src/telnyx/types/network_interface.py new file mode 100644 index 00000000..f133b69d --- /dev/null +++ b/src/telnyx/types/network_interface.py @@ -0,0 +1,19 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional + +from .._models import BaseModel +from .interface_status import InterfaceStatus + +__all__ = ["NetworkInterface"] + + +class NetworkInterface(BaseModel): + name: Optional[str] = None + """A user specified name for the interface.""" + + network_id: Optional[str] = None + """The id of the network associated with the interface.""" + + status: Optional[InterfaceStatus] = None + """The current status of the interface deployment.""" diff --git a/src/telnyx/types/network_list_interfaces_response.py b/src/telnyx/types/network_list_interfaces_response.py index ebf8ccec..e045dd1f 100644 --- a/src/telnyx/types/network_list_interfaces_response.py +++ b/src/telnyx/types/network_list_interfaces_response.py @@ -2,13 +2,14 @@ from typing import Optional +from .record import Record from .._models import BaseModel -from .interface_status import InterfaceStatus +from .network_interface import NetworkInterface -__all__ = ["NetworkListInterfacesResponse", "Region"] +__all__ = ["NetworkListInterfacesResponse", "NetworkListInterfacesResponseRegion"] -class Region(BaseModel): +class NetworkListInterfacesResponseRegion(BaseModel): code: Optional[str] = None """Region code of the interface.""" @@ -19,32 +20,14 @@ class Region(BaseModel): """Identifies the type of the resource.""" -class NetworkListInterfacesResponse(BaseModel): - id: Optional[str] = None - """Identifies the resource.""" - - created_at: Optional[str] = None - """ISO 8601 formatted date-time indicating when the resource was created.""" - - name: Optional[str] = None - """A user specified name for the interface.""" - - network_id: Optional[str] = None - """The id of the network associated with the interface.""" - - record_type: Optional[str] = None +class NetworkListInterfacesResponse(Record, NetworkInterface): + record_type: Optional[str] = None # type: ignore """Identifies the type of the resource.""" - region: Optional[Region] = None + region: Optional[NetworkListInterfacesResponseRegion] = None region_code: Optional[str] = None """The region interface is deployed to.""" - status: Optional[InterfaceStatus] = None - """The current status of the interface deployment.""" - type: Optional[str] = None """Identifies the type of the interface.""" - - updated_at: Optional[str] = None - """ISO 8601 formatted date-time indicating when the resource was updated.""" diff --git a/src/telnyx/types/organization_contact.py b/src/telnyx/types/organization_contact.py index 7f26ac77..3bc69298 100644 --- a/src/telnyx/types/organization_contact.py +++ b/src/telnyx/types/organization_contact.py @@ -6,22 +6,13 @@ class OrganizationContact(BaseModel): - """Organization contact information. - - Note: the response returns this object with the phone field as 'phone' (not 'phone_number'). - """ - email: str - """Contact's email address""" first_name: str - """Contact's first name""" job_title: str - """Contact's job title (required)""" last_name: str - """Contact's last name""" - phone: str - """Contact's phone number in E.164 format""" + phone_number: str + """E.164 format with leading `+`.""" diff --git a/src/telnyx/types/organization_contact_param.py b/src/telnyx/types/organization_contact_param.py index 623a5779..7948928a 100644 --- a/src/telnyx/types/organization_contact_param.py +++ b/src/telnyx/types/organization_contact_param.py @@ -8,22 +8,13 @@ class OrganizationContactParam(TypedDict, total=False): - """Organization contact information. - - Note: the response returns this object with the phone field as 'phone' (not 'phone_number'). - """ - email: Required[str] - """Contact's email address""" first_name: Required[str] - """Contact's first name""" job_title: Required[str] - """Contact's job title (required)""" last_name: Required[str] - """Contact's last name""" - phone: Required[str] - """Contact's phone number in E.164 format""" + phone_number: Required[str] + """E.164 format with leading `+`.""" diff --git a/src/telnyx/types/physical_address.py b/src/telnyx/types/physical_address.py index c700580e..77c1c437 100644 --- a/src/telnyx/types/physical_address.py +++ b/src/telnyx/types/physical_address.py @@ -9,19 +9,15 @@ class PhysicalAddress(BaseModel): administrative_area: str - """State or province""" + """State or province code (e.g. `IL`, `ON`).""" city: str - """City name""" country: str - """Country name (e.g., United States)""" + """ISO 3166-1 alpha-2 code (currently `US` or `CA`).""" postal_code: str - """ZIP or postal code""" street_address: str - """Street address""" extended_address: Optional[str] = None - """Additional address line (suite, apt, etc.)""" diff --git a/src/telnyx/types/physical_address_param.py b/src/telnyx/types/physical_address_param.py index 951e6b31..b0fd0c4d 100644 --- a/src/telnyx/types/physical_address_param.py +++ b/src/telnyx/types/physical_address_param.py @@ -10,19 +10,15 @@ class PhysicalAddressParam(TypedDict, total=False): administrative_area: Required[str] - """State or province""" + """State or province code (e.g. `IL`, `ON`).""" city: Required[str] - """City name""" country: Required[str] - """Country name (e.g., United States)""" + """ISO 3166-1 alpha-2 code (currently `US` or `CA`).""" postal_code: Required[str] - """ZIP or postal code""" street_address: Required[str] - """Street address""" extended_address: Optional[str] - """Additional address line (suite, apt, etc.)""" diff --git a/src/telnyx/types/public_internet_gateway_create_response.py b/src/telnyx/types/public_internet_gateway_create_response.py index 76e78efa..11e16259 100644 --- a/src/telnyx/types/public_internet_gateway_create_response.py +++ b/src/telnyx/types/public_internet_gateway_create_response.py @@ -2,11 +2,20 @@ from typing import Optional +from .record import Record from .._models import BaseModel -from .public_internet_gateway_read import PublicInternetGatewayRead +from .network_interface import NetworkInterface -__all__ = ["PublicInternetGatewayCreateResponse"] +__all__ = ["PublicInternetGatewayCreateResponse", "Data"] + + +class Data(Record, NetworkInterface): + public_ip: Optional[str] = None + """The publically accessible ip for this interface.""" + + region_code: Optional[str] = None + """The region interface is deployed to.""" class PublicInternetGatewayCreateResponse(BaseModel): - data: Optional[PublicInternetGatewayRead] = None + data: Optional[Data] = None diff --git a/src/telnyx/types/public_internet_gateway_delete_response.py b/src/telnyx/types/public_internet_gateway_delete_response.py index 1935227e..8bc2e312 100644 --- a/src/telnyx/types/public_internet_gateway_delete_response.py +++ b/src/telnyx/types/public_internet_gateway_delete_response.py @@ -2,11 +2,20 @@ from typing import Optional +from .record import Record from .._models import BaseModel -from .public_internet_gateway_read import PublicInternetGatewayRead +from .network_interface import NetworkInterface -__all__ = ["PublicInternetGatewayDeleteResponse"] +__all__ = ["PublicInternetGatewayDeleteResponse", "Data"] + + +class Data(Record, NetworkInterface): + public_ip: Optional[str] = None + """The publically accessible ip for this interface.""" + + region_code: Optional[str] = None + """The region interface is deployed to.""" class PublicInternetGatewayDeleteResponse(BaseModel): - data: Optional[PublicInternetGatewayRead] = None + data: Optional[Data] = None diff --git a/src/telnyx/types/public_internet_gateway_list_response.py b/src/telnyx/types/public_internet_gateway_list_response.py new file mode 100644 index 00000000..ac8fa8a6 --- /dev/null +++ b/src/telnyx/types/public_internet_gateway_list_response.py @@ -0,0 +1,16 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional + +from .record import Record +from .network_interface import NetworkInterface + +__all__ = ["PublicInternetGatewayListResponse"] + + +class PublicInternetGatewayListResponse(Record, NetworkInterface): + public_ip: Optional[str] = None + """The publically accessible ip for this interface.""" + + region_code: Optional[str] = None + """The region interface is deployed to.""" diff --git a/src/telnyx/types/public_internet_gateway_read.py b/src/telnyx/types/public_internet_gateway_read.py deleted file mode 100644 index 88d1785f..00000000 --- a/src/telnyx/types/public_internet_gateway_read.py +++ /dev/null @@ -1,37 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Optional - -from .._models import BaseModel -from .interface_status import InterfaceStatus - -__all__ = ["PublicInternetGatewayRead"] - - -class PublicInternetGatewayRead(BaseModel): - id: Optional[str] = None - """Identifies the resource.""" - - created_at: Optional[str] = None - """ISO 8601 formatted date-time indicating when the resource was created.""" - - name: Optional[str] = None - """A user specified name for the interface.""" - - network_id: Optional[str] = None - """The id of the network associated with the interface.""" - - public_ip: Optional[str] = None - """The publically accessible ip for this interface.""" - - record_type: Optional[str] = None - """Identifies the type of the resource.""" - - region_code: Optional[str] = None - """The region interface is deployed to.""" - - status: Optional[InterfaceStatus] = None - """The current status of the interface deployment.""" - - updated_at: Optional[str] = None - """ISO 8601 formatted date-time indicating when the resource was updated.""" diff --git a/src/telnyx/types/public_internet_gateway_retrieve_response.py b/src/telnyx/types/public_internet_gateway_retrieve_response.py index 5c95dcce..c1b162e1 100644 --- a/src/telnyx/types/public_internet_gateway_retrieve_response.py +++ b/src/telnyx/types/public_internet_gateway_retrieve_response.py @@ -2,11 +2,20 @@ from typing import Optional +from .record import Record from .._models import BaseModel -from .public_internet_gateway_read import PublicInternetGatewayRead +from .network_interface import NetworkInterface -__all__ = ["PublicInternetGatewayRetrieveResponse"] +__all__ = ["PublicInternetGatewayRetrieveResponse", "Data"] + + +class Data(Record, NetworkInterface): + public_ip: Optional[str] = None + """The publically accessible ip for this interface.""" + + region_code: Optional[str] = None + """The region interface is deployed to.""" class PublicInternetGatewayRetrieveResponse(BaseModel): - data: Optional[PublicInternetGatewayRead] = None + data: Optional[Data] = None diff --git a/src/telnyx/types/reputation/__init__.py b/src/telnyx/types/reputation/__init__.py index 480b014b..9c9276a5 100644 --- a/src/telnyx/types/reputation/__init__.py +++ b/src/telnyx/types/reputation/__init__.py @@ -3,5 +3,6 @@ from __future__ import annotations from .number_list_params import NumberListParams as NumberListParams +from .number_list_response import NumberListResponse as NumberListResponse from .number_retrieve_params import NumberRetrieveParams as NumberRetrieveParams from .number_retrieve_response import NumberRetrieveResponse as NumberRetrieveResponse diff --git a/src/telnyx/types/reputation/number_list_params.py b/src/telnyx/types/reputation/number_list_params.py index 6091dce7..545ae09f 100644 --- a/src/telnyx/types/reputation/number_list_params.py +++ b/src/telnyx/types/reputation/number_list_params.py @@ -11,10 +11,13 @@ class NumberListParams(TypedDict, total=False): page_number: Annotated[int, PropertyInfo(alias="page[number]")] - """Page number (1-indexed)""" + """1-based page number. + + Out-of-range values return an empty page with correct meta. + """ page_size: Annotated[int, PropertyInfo(alias="page[size]")] - """Number of items per page""" + """Items per page. Maximum 250; values above are clamped to 250.""" phone_number: str - """Filter by specific phone number (E.164 format)""" + """Filter by specific phone number (E.164 format).""" diff --git a/src/telnyx/types/shared/reputation_phone_number_with_reputation_data.py b/src/telnyx/types/reputation/number_list_response.py similarity index 53% rename from src/telnyx/types/shared/reputation_phone_number_with_reputation_data.py rename to src/telnyx/types/reputation/number_list_response.py index 2099474d..2ba40d46 100644 --- a/src/telnyx/types/shared/reputation_phone_number_with_reputation_data.py +++ b/src/telnyx/types/reputation/number_list_response.py @@ -4,26 +4,22 @@ from datetime import datetime from ..._models import BaseModel -from .reputation_data import ReputationData +from ..shared.reputation_data import ReputationData -__all__ = ["ReputationPhoneNumberWithReputationData"] +__all__ = ["NumberListResponse"] -class ReputationPhoneNumberWithReputationData(BaseModel): +class NumberListResponse(BaseModel): id: Optional[str] = None - """Unique identifier""" created_at: Optional[datetime] = None - """When the number was associated""" enterprise_id: Optional[str] = None - """ID of the associated enterprise""" phone_number: Optional[str] = None - """Phone number in E.164 format""" + """E.164 with leading `+`.""" reputation_data: Optional[ReputationData] = None - """Reputation metrics""" + """`null` until the first refresh has been collected for this number.""" updated_at: Optional[datetime] = None - """When the record was last updated""" diff --git a/src/telnyx/types/reputation/number_retrieve_params.py b/src/telnyx/types/reputation/number_retrieve_params.py index 3c27c672..aa635b30 100644 --- a/src/telnyx/types/reputation/number_retrieve_params.py +++ b/src/telnyx/types/reputation/number_retrieve_params.py @@ -11,5 +11,5 @@ class NumberRetrieveParams(TypedDict, total=False): fresh: bool """When true, fetches fresh reputation data (incurs API cost). - When false, returns cached data. + When false (default), returns cached data. """ diff --git a/src/telnyx/types/reputation/number_retrieve_response.py b/src/telnyx/types/reputation/number_retrieve_response.py index ddc5a7bf..a44ae4e7 100644 --- a/src/telnyx/types/reputation/number_retrieve_response.py +++ b/src/telnyx/types/reputation/number_retrieve_response.py @@ -1,12 +1,29 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional +from datetime import datetime from ..._models import BaseModel -from ..shared.reputation_phone_number_with_reputation_data import ReputationPhoneNumberWithReputationData +from ..shared.reputation_data import ReputationData -__all__ = ["NumberRetrieveResponse"] +__all__ = ["NumberRetrieveResponse", "Data"] + + +class Data(BaseModel): + id: Optional[str] = None + + created_at: Optional[datetime] = None + + enterprise_id: Optional[str] = None + + phone_number: Optional[str] = None + """E.164 with leading `+`.""" + + reputation_data: Optional[ReputationData] = None + """`null` until the first refresh has been collected for this number.""" + + updated_at: Optional[datetime] = None class NumberRetrieveResponse(BaseModel): - data: Optional[ReputationPhoneNumberWithReputationData] = None + data: Data diff --git a/src/telnyx/types/shared/__init__.py b/src/telnyx/types/shared/__init__.py index 5c06c0cc..92f4ac00 100644 --- a/src/telnyx/types/shared/__init__.py +++ b/src/telnyx/types/shared/__init__.py @@ -4,7 +4,6 @@ from .feature import Feature as Feature from .metadata import Metadata as Metadata from .api_error import APIError as APIError -from .meta_info import MetaInfo as MetaInfo from .short_code import ShortCode as ShortCode from .hosted_number import HostedNumber as HostedNumber from .reputation_data import ReputationData as ReputationData @@ -14,7 +13,6 @@ from .netapps_location import NetappsLocation as NetappsLocation from .room_participant import RoomParticipant as RoomParticipant from .region_information import RegionInformation as RegionInformation -from .xai_voice_settings import XaiVoiceSettings as XaiVoiceSettings from .rime_voice_settings import RimeVoiceSettings as RimeVoiceSettings from .azure_voice_settings import AzureVoiceSettings as AzureVoiceSettings from .porting_order_status import PortingOrderStatus as PortingOrderStatus @@ -40,9 +38,6 @@ from .available_phone_numbers_metadata import AvailablePhoneNumbersMetadata as AvailablePhoneNumbersMetadata from .connection_noise_suppression_details import ConnectionNoiseSuppressionDetails as ConnectionNoiseSuppressionDetails from .phone_number_with_messaging_settings import PhoneNumberWithMessagingSettings as PhoneNumberWithMessagingSettings -from .reputation_phone_number_with_reputation_data import ( - ReputationPhoneNumberWithReputationData as ReputationPhoneNumberWithReputationData, -) from .sub_number_order_regulatory_requirement_with_value import ( SubNumberOrderRegulatoryRequirementWithValue as SubNumberOrderRegulatoryRequirementWithValue, ) diff --git a/src/telnyx/types/shared/meta_info.py b/src/telnyx/types/shared/meta_info.py deleted file mode 100644 index 6066280d..00000000 --- a/src/telnyx/types/shared/meta_info.py +++ /dev/null @@ -1,21 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Optional - -from ..._models import BaseModel - -__all__ = ["MetaInfo"] - - -class MetaInfo(BaseModel): - page_number: Optional[int] = None - """Current page number""" - - page_size: Optional[int] = None - """Items per page""" - - total_pages: Optional[int] = None - """Total number of pages""" - - total_results: Optional[int] = None - """Total number of results""" diff --git a/src/telnyx/types/shared/reputation_data.py b/src/telnyx/types/shared/reputation_data.py index 46f61348..2602ea52 100644 --- a/src/telnyx/types/shared/reputation_data.py +++ b/src/telnyx/types/shared/reputation_data.py @@ -10,25 +10,23 @@ class ReputationData(BaseModel): - """Reputation metrics""" + """Reputation snapshot for a phone number. + + Each metric is a 0–100 score; `spam_risk` is a coarse bucket. Field set may grow over time — read by key. + """ connection_score: Optional[int] = None - """Connection quality metric (0–100)""" engagement_score: Optional[int] = None - """Engagement metric (0–100). Higher = more positive engagement""" last_refreshed_at: Optional[datetime] = None - """Timestamp of the last reputation data refresh""" maturity_score: Optional[int] = None - """Maturity metric (0–100). Higher = more established number""" sentiment_score: Optional[int] = None - """Sentiment metric (0–100). Higher = more positive sentiment""" spam_category: Optional[str] = None - """Spam category classification (e.g., Telemarketing, Debt Collector)""" + """Category label from the reputation feed when the number is flagged.""" spam_risk: Optional[Literal["low", "medium", "high"]] = None - """Overall spam risk level""" + """Overall spam-risk classification.""" diff --git a/src/telnyx/types/shared/xai_voice_settings.py b/src/telnyx/types/shared/xai_voice_settings.py deleted file mode 100644 index 3ad6ade7..00000000 --- a/src/telnyx/types/shared/xai_voice_settings.py +++ /dev/null @@ -1,16 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Optional -from typing_extensions import Literal - -from ..._models import BaseModel - -__all__ = ["XaiVoiceSettings"] - - -class XaiVoiceSettings(BaseModel): - type: Literal["xai"] - """Voice settings provider type""" - - language: Optional[str] = None - """Language code, or `auto` to detect automatically.""" diff --git a/src/telnyx/types/shared_params/__init__.py b/src/telnyx/types/shared_params/__init__.py index 277b4842..1143dd3d 100644 --- a/src/telnyx/types/shared_params/__init__.py +++ b/src/telnyx/types/shared_params/__init__.py @@ -1,7 +1,6 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from .sim_card_status import SimCardStatus as SimCardStatus -from .xai_voice_settings import XaiVoiceSettings as XaiVoiceSettings from .rime_voice_settings import RimeVoiceSettings as RimeVoiceSettings from .azure_voice_settings import AzureVoiceSettings as AzureVoiceSettings from .book_appointment_tool import BookAppointmentTool as BookAppointmentTool diff --git a/src/telnyx/types/shared_params/xai_voice_settings.py b/src/telnyx/types/shared_params/xai_voice_settings.py deleted file mode 100644 index 522c82e7..00000000 --- a/src/telnyx/types/shared_params/xai_voice_settings.py +++ /dev/null @@ -1,15 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing_extensions import Literal, Required, TypedDict - -__all__ = ["XaiVoiceSettings"] - - -class XaiVoiceSettings(TypedDict, total=False): - type: Required[Literal["xai"]] - """Voice settings provider type""" - - language: str - """Language code, or `auto` to detect automatically.""" diff --git a/src/telnyx/types/terms_of_service/__init__.py b/src/telnyx/types/terms_of_service/__init__.py index f8ee8b14..2a11efeb 100644 --- a/src/telnyx/types/terms_of_service/__init__.py +++ b/src/telnyx/types/terms_of_service/__init__.py @@ -1,3 +1,9 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from __future__ import annotations + +from .agreement_list_params import AgreementListParams as AgreementListParams +from .agreement_list_response import AgreementListResponse as AgreementListResponse +from .agreement_retrieve_response import AgreementRetrieveResponse as AgreementRetrieveResponse +from .branded_calling_agree_response import BrandedCallingAgreeResponse as BrandedCallingAgreeResponse +from .number_reputation_agree_response import NumberReputationAgreeResponse as NumberReputationAgreeResponse diff --git a/src/telnyx/types/terms_of_service/agreement_list_params.py b/src/telnyx/types/terms_of_service/agreement_list_params.py new file mode 100644 index 00000000..b0b99e32 --- /dev/null +++ b/src/telnyx/types/terms_of_service/agreement_list_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 Literal, Annotated, TypedDict + +from ..._utils import PropertyInfo + +__all__ = ["AgreementListParams"] + + +class AgreementListParams(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.""" + + product_type: Literal["branded_calling", "number_reputation"] + """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. + """ diff --git a/src/telnyx/types/terms_of_service/agreement_list_response.py b/src/telnyx/types/terms_of_service/agreement_list_response.py new file mode 100644 index 00000000..611a9894 --- /dev/null +++ b/src/telnyx/types/terms_of_service/agreement_list_response.py @@ -0,0 +1,30 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional +from datetime import datetime +from typing_extensions import Literal + +from ..._models import BaseModel + +__all__ = ["AgreementListResponse"] + + +class AgreementListResponse(BaseModel): + """A recorded user agreement to a product's Terms of Service. + + The `user_id` is intentionally NOT echoed back on this public surface — the caller already knows their own identity. + """ + + id: Optional[str] = None + + agreed_at: Optional[datetime] = None + + created_at: Optional[datetime] = None + + product_type: Optional[Literal["branded_calling", "number_reputation"]] = None + """Telnyx product the Terms of Service apply to.""" + + terms_version: Optional[str] = None + + 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/agreement_retrieve_response.py b/src/telnyx/types/terms_of_service/agreement_retrieve_response.py new file mode 100644 index 00000000..3d01ad90 --- /dev/null +++ b/src/telnyx/types/terms_of_service/agreement_retrieve_response.py @@ -0,0 +1,39 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional +from datetime import datetime +from typing_extensions import Literal + +from ..._models import BaseModel + +__all__ = ["AgreementRetrieveResponse", "Data"] + + +class Data(BaseModel): + """A recorded user agreement to a product's Terms of Service. + + The `user_id` is intentionally NOT echoed back on this public surface — the caller already knows their own identity. + """ + + id: Optional[str] = None + + agreed_at: Optional[datetime] = None + + created_at: Optional[datetime] = None + + product_type: Optional[Literal["branded_calling", "number_reputation"]] = None + """Telnyx product the Terms of Service apply to.""" + + terms_version: Optional[str] = None + + version: Optional[str] = None + """Convenience alias of `terms_version`. Both keys are present on every response.""" + + +class AgreementRetrieveResponse(BaseModel): + data: Data + """A recorded user agreement to a product's Terms of Service. + + The `user_id` is intentionally NOT echoed back on this public surface — the + caller already knows their own identity. + """ diff --git a/src/telnyx/types/terms_of_service/branded_calling_agree_response.py b/src/telnyx/types/terms_of_service/branded_calling_agree_response.py new file mode 100644 index 00000000..62dc120d --- /dev/null +++ b/src/telnyx/types/terms_of_service/branded_calling_agree_response.py @@ -0,0 +1,39 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional +from datetime import datetime +from typing_extensions import Literal + +from ..._models import BaseModel + +__all__ = ["BrandedCallingAgreeResponse", "Data"] + + +class Data(BaseModel): + """A recorded user agreement to a product's Terms of Service. + + The `user_id` is intentionally NOT echoed back on this public surface — the caller already knows their own identity. + """ + + id: Optional[str] = None + + agreed_at: Optional[datetime] = None + + created_at: Optional[datetime] = None + + product_type: Optional[Literal["branded_calling", "number_reputation"]] = None + """Telnyx product the Terms of Service apply to.""" + + terms_version: Optional[str] = None + + version: Optional[str] = None + """Convenience alias of `terms_version`. Both keys are present on every response.""" + + +class BrandedCallingAgreeResponse(BaseModel): + data: Data + """A recorded user agreement to a product's Terms of Service. + + The `user_id` is intentionally NOT echoed back on this public surface — the + caller already knows their own identity. + """ diff --git a/src/telnyx/types/terms_of_service/number_reputation_agree_response.py b/src/telnyx/types/terms_of_service/number_reputation_agree_response.py new file mode 100644 index 00000000..c6d38ce8 --- /dev/null +++ b/src/telnyx/types/terms_of_service/number_reputation_agree_response.py @@ -0,0 +1,39 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional +from datetime import datetime +from typing_extensions import Literal + +from ..._models import BaseModel + +__all__ = ["NumberReputationAgreeResponse", "Data"] + + +class Data(BaseModel): + """A recorded user agreement to a product's Terms of Service. + + The `user_id` is intentionally NOT echoed back on this public surface — the caller already knows their own identity. + """ + + id: Optional[str] = None + + agreed_at: Optional[datetime] = None + + created_at: Optional[datetime] = None + + product_type: Optional[Literal["branded_calling", "number_reputation"]] = None + """Telnyx product the Terms of Service apply to.""" + + terms_version: Optional[str] = None + + version: Optional[str] = None + """Convenience alias of `terms_version`. Both keys are present on every response.""" + + +class NumberReputationAgreeResponse(BaseModel): + data: Data + """A recorded user agreement to a product's Terms of Service. + + The `user_id` is intentionally NOT echoed back on this public surface — the + caller already knows their own identity. + """ diff --git a/src/telnyx/types/terms_of_service_status_params.py b/src/telnyx/types/terms_of_service_status_params.py new file mode 100644 index 00000000..25fe5ccb --- /dev/null +++ b/src/telnyx/types/terms_of_service_status_params.py @@ -0,0 +1,16 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Literal, TypedDict + +__all__ = ["TermsOfServiceStatusParams"] + + +class TermsOfServiceStatusParams(TypedDict, total=False): + product_type: Literal["branded_calling", "number_reputation"] + """Which product's ToS to check. + + Defaults to `branded_calling`; pass `number_reputation` to check the Number + Reputation Terms of Service. + """ diff --git a/src/telnyx/types/terms_of_service_status_response.py b/src/telnyx/types/terms_of_service_status_response.py new file mode 100644 index 00000000..7e0d1eff --- /dev/null +++ b/src/telnyx/types/terms_of_service_status_response.py @@ -0,0 +1,47 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional +from datetime import datetime +from typing_extensions import Literal + +from .._models import BaseModel + +__all__ = ["TermsOfServiceStatusResponse", "Data"] + + +class Data(BaseModel): + """Whether the calling user has agreed to a product's current Terms of Service. + + The `user_id` is intentionally omitted on this public surface. + """ + + agreement_required: bool + """`true` when the user must agree to the latest version before using the product. + + Equivalent to `!has_agreed`. + """ + + current_terms_version: str + """Latest published version of the ToS for this product.""" + + has_agreed: bool + """`true` if the user has agreed to the latest version.""" + + product_type: Literal["branded_calling", "number_reputation"] + """Telnyx product the Terms of Service apply to.""" + + agreed_at: Optional[datetime] = None + + agreed_version: Optional[str] = None + """ + Version the user previously agreed to (may be older than + `current_terms_version`). `null` if the user has never agreed. + """ + + +class TermsOfServiceStatusResponse(BaseModel): + data: Data + """Whether the calling user has agreed to a product's current Terms of Service. + + The `user_id` is intentionally omitted on this public surface. + """ diff --git a/src/telnyx/types/uac_connection.py b/src/telnyx/types/uac_connection.py deleted file mode 100644 index 65a32656..00000000 --- a/src/telnyx/types/uac_connection.py +++ /dev/null @@ -1,196 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import List, Optional -from typing_extensions import Literal - -from .fqdn import Fqdn -from .._models import BaseModel -from .dtmf_type import DtmfType -from .uac_inbound import UacInbound -from .uac_outbound import UacOutbound -from .encrypted_media import EncryptedMedia -from .anchorsite_override import AnchorsiteOverride -from .uac_external_settings import UacExternalSettings -from .uac_internal_settings import UacInternalSettings -from .connection_rtcp_settings import ConnectionRtcpSettings -from .shared.connection_jitter_buffer import ConnectionJitterBuffer -from .shared.connection_noise_suppression_details import ConnectionNoiseSuppressionDetails - -__all__ = ["UacConnection"] - - -class UacConnection(BaseModel): - """ - A UAC (User Agent Client) Connection registers Telnyx to your PBX — the opposite of a standard SIP trunk, where the PBX registers to Telnyx. Use UAC when your PBX doesn’t support outbound SIP registration or you need Telnyx to maintain the registration. - """ - - id: Optional[str] = None - """Identifies the type of resource.""" - - active: Optional[bool] = None - """Defaults to true""" - - anchorsite_override: Optional[AnchorsiteOverride] = None - """ - `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 - ping messages. This can be disabled by specifying a site to handle all media. - """ - - android_push_credential_id: Optional[str] = None - """The uuid of the push credential for Android""" - - authentication: Optional[Literal["uac-authentication"]] = None - """The authentication strategy used by this connection.""" - - call_cost_in_webhooks: Optional[bool] = None - """Specifies if call cost webhooks should be sent for this connection.""" - - connection_name: Optional[str] = None - - created_at: Optional[str] = None - """ISO-8601 formatted date indicating when the resource was created.""" - - default_on_hold_comfort_noise_enabled: Optional[bool] = None - """When enabled, Telnyx will generate comfort noise when you place the call on - hold. - - If disabled, you will need to generate comfort noise or on hold music to avoid - RTP timeout. - """ - - dtmf_type: Optional[DtmfType] = None - """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. - """ - - encode_contact_header_enabled: Optional[bool] = None - """ - Encode the SIP contact header sent by Telnyx to avoid issues for NAT or ALG - scenarios. - """ - - encrypted_media: Optional[EncryptedMedia] = None - """Enable use of SRTP for encryption. - - Cannot be set if the transport_portocol is TLS. - """ - - external_uac_settings: Optional[UacExternalSettings] = None - """ - External SIP peer settings used by Telnyx when registering to your PBX and - routing outbound calls. - """ - - fqdn: Optional[str] = None - """The Telnyx-managed FQDN generated for the UAC connection.""" - - fqdn_outbound_authentication: Optional[Literal["credential-authentication"]] = None - """The fixed outbound authentication mode used by UAC FQDN records.""" - - fqdns: Optional[List[Fqdn]] = None - """FQDN records managed automatically by the UAC connection lifecycle.""" - - inbound: Optional[UacInbound] = None - - internal_uac_settings: Optional[UacInternalSettings] = None - """Internal Telnyx-side settings for a UAC connection.""" - - ios_push_credential_id: Optional[str] = None - """The uuid of the push credential for Ios""" - - jitter_buffer: Optional[ConnectionJitterBuffer] = None - """Configuration options for Jitter Buffer. - - Enables Jitter Buffer for RTP streams of SIP Trunking calls. The feature is off - unless enabled. You may define min and max values in msec for customized - buffering behaviors. Larger values add latency but tolerate more jitter, while - smaller values reduce latency but are more sensitive to jitter and reordering. - """ - - noise_suppression: Optional[Literal["inbound", "outbound", "both", "disabled"]] = None - """Controls when noise suppression is applied to calls. - - When set to 'inbound', noise suppression is applied to incoming audio. When set - to 'outbound', it's applied to outgoing audio. When set to 'both', it's applied - in both directions. When set to 'disabled', noise suppression is turned off. - """ - - noise_suppression_details: Optional[ConnectionNoiseSuppressionDetails] = None - """Configuration options for noise suppression. - - These settings are stored regardless of the noise_suppression value, but only - take effect when noise_suppression is not 'disabled'. If you disable noise - suppression and later re-enable it, the previously configured settings will be - used. - """ - - onnet_t38_passthrough_enabled: Optional[bool] = None - """ - Enable on-net T38 if you prefer the sender and receiver negotiating T38 directly - if both are on the Telnyx network. If this is disabled, Telnyx will be able to - use T38 on just one leg of the call depending on each leg's settings. - """ - - outbound: Optional[UacOutbound] = None - - password: Optional[str] = None - """The password to be used as part of the credentials. - - Must be 8 to 128 characters long. - """ - - record_type: Optional[str] = None - """Identifies the type of the resource.""" - - registration_status: Optional[str] = None - """The most recently known SIP registration status for this UAC connection.""" - - registration_status_updated_at: Optional[str] = None - """ - ISO 8601 formatted date indicating when the registration status was last - updated. - """ - - rtcp_settings: Optional[ConnectionRtcpSettings] = None - - sip_uri_calling_preference: Optional[Literal["disabled", "unrestricted", "internal"]] = None - """This feature enables inbound SIP URI calls to your Credential Auth Connection. - - If enabled for all (unrestricted) then anyone who calls the SIP URI - @telnyx.com will be connected to your Connection. You can also - choose to allow only calls that are originated on any Connections under your - account (internal). - """ - - tags: Optional[List[str]] = None - """Tags associated with the connection.""" - - updated_at: Optional[str] = None - """ISO-8601 formatted date indicating when the resource was updated.""" - - user_name: Optional[str] = None - """The user name to be used as part of the credentials. - - Must be 4-32 characters long and alphanumeric values only (no spaces or special - characters). At least one of the first 5 characters must be a letter. - """ - - webhook_api_version: Optional[Literal["1", "2"]] = None - """Determines which webhook format will be used, Telnyx API v1 or v2.""" - - webhook_event_failover_url: Optional[str] = None - """ - The failover URL where webhooks related to this connection will be sent if - sending to the primary URL fails. Must include a scheme, such as 'https'. - """ - - webhook_event_url: Optional[str] = None - """The URL where webhooks related to this connection will be sent. - - Must include a scheme, such as 'https'. - """ - - webhook_timeout_secs: Optional[int] = None - """Specifies how many seconds to wait before timing out a webhook.""" diff --git a/src/telnyx/types/uac_connection_create_params.py b/src/telnyx/types/uac_connection_create_params.py index 60b9ee3d..527ec344 100644 --- a/src/telnyx/types/uac_connection_create_params.py +++ b/src/telnyx/types/uac_connection_create_params.py @@ -8,15 +8,12 @@ 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_external_settings_param import UacExternalSettingsParam -from .uac_internal_settings_param import UacInternalSettingsParam 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", "Inbound"] +__all__ = ["UacConnectionCreateParams", "ExternalUacSettings", "Inbound", "InternalUacSettings", "Outbound"] class UacConnectionCreateParams(TypedDict, total=False): @@ -65,7 +62,7 @@ class UacConnectionCreateParams(TypedDict, total=False): Cannot be set if the transport_portocol is TLS. """ - external_uac_settings: UacExternalSettingsParam + external_uac_settings: ExternalUacSettings """ External SIP peer settings used by Telnyx when registering to your PBX and routing outbound calls. @@ -79,7 +76,7 @@ class UacConnectionCreateParams(TypedDict, total=False): Telnyx and are not accepted as request parameters. """ - internal_uac_settings: UacInternalSettingsParam + internal_uac_settings: InternalUacSettings """Internal Telnyx-side settings for a UAC connection.""" ios_push_credential_id: Optional[str] @@ -118,7 +115,7 @@ class UacConnectionCreateParams(TypedDict, total=False): use T38 on just one leg of the call depending on each leg's settings. """ - outbound: UacOutboundParam + outbound: Outbound password: str """The password to be used as part of the credentials. @@ -170,6 +167,58 @@ class UacConnectionCreateParams(TypedDict, total=False): """Specifies how many seconds to wait before timing out a webhook.""" +class ExternalUacSettings(TypedDict, total=False): + """ + External SIP peer settings used by Telnyx when registering to your PBX and routing outbound calls. + """ + + auth_username: Optional[str] + """The authentication username used in SIP digest authentication. + + If not set, the Username value will be used. + """ + + expiration_sec: Optional[int] + """ + The registration interval, in seconds, indicating how often the system refreshes + the SIP registration with the external SIP peer. + """ + + from_user: Optional[str] + """The user portion of the SIP From header used in outbound requests. + + This controls the caller identity presented to the external SIP peer. + """ + + outbound_proxy: Optional[str] + """ + An optional SIP proxy used to route outbound requests before reaching the + external SIP peer. + """ + + password: str + """The SIP password used for digest authentication with the external SIP peer.""" + + proxy: str + """ + The SIP proxy address of the external SIP peer used for registrations and + outbound call routing. + """ + + transport: Optional[Literal["UDP", "TLS", "TCP"]] + """ + The transport protocol used for SIP signaling when communicating with the + external SIP peer. One of UDP, TLS, or TCP. + """ + + username: str + """ + The SIP username used to authenticate with the external SIP peer for + registrations and outbound calls. Must start with a letter or number and contain + only letters, numbers, hyphens, and underscores. + """ + + class Inbound(TypedDict, total=False): """Inbound settings that can be supplied when creating or updating a UAC connection. @@ -235,3 +284,72 @@ class Inbound(TypedDict, total=False): timeout_2xx_secs: int """Time(sec) before aborting if call is unanswered (min: 1, max: 600).""" + + +class InternalUacSettings(TypedDict, total=False): + """Internal Telnyx-side settings for a UAC connection.""" + + destination_uri: str + """ + The SIP URI that Telnyx will call when handling an inbound request from the + external peer. Do not include a `sip:` prefix. The value must be in the format + `userinfo@sip.telnyx.com` or + `userinfo@sipdev.telnyx.com`; the userinfo portion may contain only + letters, digits, hyphens, and underscores. + """ + + +class Outbound(TypedDict, total=False): + ani_override: str + """ + Set a phone number as the ani_override value to override caller id number on + outbound calls. + """ + + ani_override_type: Literal["always", "normal", "emergency"] + """Specifies when we apply your ani_override setting. + + Only applies when ani_override is not blank. + """ + + call_parking_enabled: Optional[bool] + """ + Forces all SIP calls originated on this connection to be "parked" instead of + "bridged" to the destination specified on the URI. Parked calls will return + ringback to the caller and will await for a Call Control command to define which + action will be taken next. + """ + + channel_limit: int + """ + When set, this will limit the total number of outbound calls to phone numbers + associated with this connection. + """ + + generate_ringback_tone: bool + """Generate ringback tone through 183 session progress message with early media.""" + + instant_ringback_enabled: bool + """ + When set, ringback will not wait for indication before sending ringback tone to + calling party. + """ + + localization: str + """ + A 2-character country code specifying the country whose national dialing rules + should be used. For example, if set to `US` then any US number can be dialed + without preprending +1 to the number. When left blank, Telnyx will try US and GB + dialing rules, in that order, by default. + """ + + outbound_voice_profile_id: str + """Identifies the associated outbound voice profile.""" + + t38_reinvite_source: Literal["telnyx", "customer", "disabled", "passthru", "caller-passthru", "callee-passthru"] + """This setting only affects connections with Fax-type Outbound Voice Profiles. + + The setting dictates whether or not Telnyx sends a t.38 reinvite.

By + default, Telnyx will send the re-invite. If set to `customer`, the caller is + expected to send the t.38 reinvite. + """ diff --git a/src/telnyx/types/uac_connection_create_response.py b/src/telnyx/types/uac_connection_create_response.py index 53442510..3b26c2e3 100644 --- a/src/telnyx/types/uac_connection_create_response.py +++ b/src/telnyx/types/uac_connection_create_response.py @@ -1,15 +1,397 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import Optional +from typing import List, Optional +from typing_extensions import Literal +from .fqdn import Fqdn from .._models import BaseModel -from .uac_connection import UacConnection +from .dtmf_type import DtmfType +from .encrypted_media import EncryptedMedia +from .anchorsite_override import AnchorsiteOverride +from .connection_rtcp_settings import ConnectionRtcpSettings +from .shared.connection_jitter_buffer import ConnectionJitterBuffer +from .shared.connection_noise_suppression_details import ConnectionNoiseSuppressionDetails -__all__ = ["UacConnectionCreateResponse"] +__all__ = [ + "UacConnectionCreateResponse", + "Data", + "DataExternalUacSettings", + "DataInbound", + "DataInternalUacSettings", + "DataOutbound", +] + + +class DataExternalUacSettings(BaseModel): + """ + External SIP peer settings used by Telnyx when registering to your PBX and routing outbound calls. + """ + + auth_username: Optional[str] = None + """The authentication username used in SIP digest authentication. + + If not set, the Username value will be used. + """ + + expiration_sec: Optional[int] = None + """ + The registration interval, in seconds, indicating how often the system refreshes + the SIP registration with the external SIP peer. + """ + + from_user: Optional[str] = None + """The user portion of the SIP From header used in outbound requests. + + This controls the caller identity presented to the external SIP peer. + """ + + outbound_proxy: Optional[str] = None + """ + An optional SIP proxy used to route outbound requests before reaching the + external SIP peer. + """ + + password: Optional[str] = None + """The SIP password used for digest authentication with the external SIP peer.""" + + proxy: Optional[str] = None + """ + The SIP proxy address of the external SIP peer used for registrations and + outbound call routing. + """ + + transport: Optional[Literal["UDP", "TLS", "TCP"]] = None + """ + The transport protocol used for SIP signaling when communicating with the + external SIP peer. One of UDP, TLS, or TCP. + """ + + username: Optional[str] = None + """ + The SIP username used to authenticate with the external SIP peer for + registrations and outbound calls. Must start with a letter or number and contain + only letters, numbers, hyphens, and underscores. + """ + + +class DataInbound(BaseModel): + ani_number_format: Optional[Literal["+E.164", "E.164", "+E.164-national", "E.164-national"]] = None + """ + This setting allows you to set the format with which the caller's number (ANI) + is sent for inbound phone calls. + """ + + channel_limit: Optional[int] = None + """ + When set, this will limit the total number of inbound calls to phone numbers + associated with this connection. + """ + + codecs: Optional[List[str]] = None + """ + Defines the list of codecs that Telnyx will send for inbound calls to a specific + number on your portal account, in priority order. This only works when the + Connection the number is assigned to uses Media Handling mode: default. OPUS and + H.264 codecs are available only when using TCP or TLS transport for SIP. + """ + + default_routing_method: Optional[Literal["sequential", "round-robin"]] = None + """ + Default routing method to be used when a number is associated with the + connection. Must be one of the routing method types or left blank, other values + are not allowed. + """ + + dnis_number_format: Optional[Literal["+e164", "e164", "national", "sip_username"]] = None + + generate_ringback_tone: Optional[bool] = None + """Generate ringback tone through 183 session progress message with early media.""" + + isup_headers_enabled: Optional[bool] = None + """When set, inbound phone calls will receive ISUP parameters via SIP headers. + + (Only when available and only when using TCP or TLS transport.) + """ + + prack_enabled: Optional[bool] = None + """Enable PRACK messages as defined in RFC3262.""" + + shaken_stir_enabled: Optional[bool] = None + """ + When enabled the SIP Connection will receive the Identity header with + Shaken/Stir data in the SIP INVITE message of inbound calls, even when using UDP + transport. + """ + + simultaneous_ringing: Optional[Literal["disabled", "enabled"]] = None + """When enabled, allows multiple devices to ring simultaneously on incoming calls.""" + + sip_compact_headers_enabled: Optional[bool] = None + """Defaults to true.""" + + sip_subdomain: Optional[str] = None + """The Telnyx-generated SIP subdomain for this UAC connection.""" + + sip_subdomain_receive_settings: Optional[Literal["only_my_connections", "from_anyone"]] = None + """Controls which SIP URI callers may reach this connection.""" + + timeout_1xx_secs: Optional[int] = None + """Time(sec) before aborting if connection is not made.""" + + timeout_2xx_secs: Optional[int] = None + """Time(sec) before aborting if call is unanswered (min: 1, max: 600).""" + + +class DataInternalUacSettings(BaseModel): + """Internal Telnyx-side settings for a UAC connection.""" + + destination_uri: Optional[str] = None + """ + The SIP URI that Telnyx will call when handling an inbound request from the + external peer. Do not include a `sip:` prefix. The value must be in the format + `userinfo@sip.telnyx.com` or + `userinfo@sipdev.telnyx.com`; the userinfo portion may contain only + letters, digits, hyphens, and underscores. + """ + + +class DataOutbound(BaseModel): + ani_override: Optional[str] = None + """ + Set a phone number as the ani_override value to override caller id number on + outbound calls. + """ + + ani_override_type: Optional[Literal["always", "normal", "emergency"]] = None + """Specifies when we apply your ani_override setting. + + Only applies when ani_override is not blank. + """ + + call_parking_enabled: Optional[bool] = None + """ + Forces all SIP calls originated on this connection to be "parked" instead of + "bridged" to the destination specified on the URI. Parked calls will return + ringback to the caller and will await for a Call Control command to define which + action will be taken next. + """ + + channel_limit: Optional[int] = None + """ + When set, this will limit the total number of outbound calls to phone numbers + associated with this connection. + """ + + generate_ringback_tone: Optional[bool] = None + """Generate ringback tone through 183 session progress message with early media.""" + + instant_ringback_enabled: Optional[bool] = None + """ + When set, ringback will not wait for indication before sending ringback tone to + calling party. + """ + + localization: Optional[str] = None + """ + A 2-character country code specifying the country whose national dialing rules + should be used. For example, if set to `US` then any US number can be dialed + without preprending +1 to the number. When left blank, Telnyx will try US and GB + dialing rules, in that order, by default. + """ + + outbound_voice_profile_id: Optional[str] = None + """Identifies the associated outbound voice profile.""" + + t38_reinvite_source: Optional[ + Literal["telnyx", "customer", "disabled", "passthru", "caller-passthru", "callee-passthru"] + ] = None + """This setting only affects connections with Fax-type Outbound Voice Profiles. + + The setting dictates whether or not Telnyx sends a t.38 reinvite.

By + default, Telnyx will send the re-invite. If set to `customer`, the caller is + expected to send the t.38 reinvite. + """ + + +class Data(BaseModel): + """ + A UAC (User Agent Client) Connection registers Telnyx to your PBX — the opposite of a standard SIP trunk, where the PBX registers to Telnyx. Use UAC when your PBX doesn’t support outbound SIP registration or you need Telnyx to maintain the registration. + """ + + id: Optional[str] = None + """Identifies the type of resource.""" + + active: Optional[bool] = None + """Defaults to true""" + + anchorsite_override: Optional[AnchorsiteOverride] = None + """ + `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 + ping messages. This can be disabled by specifying a site to handle all media. + """ + + android_push_credential_id: Optional[str] = None + """The uuid of the push credential for Android""" + + authentication: Optional[Literal["uac-authentication"]] = None + """The authentication strategy used by this connection.""" + + call_cost_in_webhooks: Optional[bool] = None + """Specifies if call cost webhooks should be sent for this connection.""" + + connection_name: Optional[str] = None + + created_at: Optional[str] = None + """ISO-8601 formatted date indicating when the resource was created.""" + + default_on_hold_comfort_noise_enabled: Optional[bool] = None + """When enabled, Telnyx will generate comfort noise when you place the call on + hold. + + If disabled, you will need to generate comfort noise or on hold music to avoid + RTP timeout. + """ + + dtmf_type: Optional[DtmfType] = None + """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. + """ + + encode_contact_header_enabled: Optional[bool] = None + """ + Encode the SIP contact header sent by Telnyx to avoid issues for NAT or ALG + scenarios. + """ + + encrypted_media: Optional[EncryptedMedia] = None + """Enable use of SRTP for encryption. + + Cannot be set if the transport_portocol is TLS. + """ + + external_uac_settings: Optional[DataExternalUacSettings] = None + """ + External SIP peer settings used by Telnyx when registering to your PBX and + routing outbound calls. + """ + + fqdn: Optional[str] = None + """The Telnyx-managed FQDN generated for the UAC connection.""" + + fqdn_outbound_authentication: Optional[Literal["credential-authentication"]] = None + """The fixed outbound authentication mode used by UAC FQDN records.""" + + fqdns: Optional[List[Fqdn]] = None + """FQDN records managed automatically by the UAC connection lifecycle.""" + + inbound: Optional[DataInbound] = None + + internal_uac_settings: Optional[DataInternalUacSettings] = None + """Internal Telnyx-side settings for a UAC connection.""" + + ios_push_credential_id: Optional[str] = None + """The uuid of the push credential for Ios""" + + jitter_buffer: Optional[ConnectionJitterBuffer] = None + """Configuration options for Jitter Buffer. + + Enables Jitter Buffer for RTP streams of SIP Trunking calls. The feature is off + unless enabled. You may define min and max values in msec for customized + buffering behaviors. Larger values add latency but tolerate more jitter, while + smaller values reduce latency but are more sensitive to jitter and reordering. + """ + + noise_suppression: Optional[Literal["inbound", "outbound", "both", "disabled"]] = None + """Controls when noise suppression is applied to calls. + + When set to 'inbound', noise suppression is applied to incoming audio. When set + to 'outbound', it's applied to outgoing audio. When set to 'both', it's applied + in both directions. When set to 'disabled', noise suppression is turned off. + """ + + noise_suppression_details: Optional[ConnectionNoiseSuppressionDetails] = None + """Configuration options for noise suppression. + + These settings are stored regardless of the noise_suppression value, but only + take effect when noise_suppression is not 'disabled'. If you disable noise + suppression and later re-enable it, the previously configured settings will be + used. + """ + + onnet_t38_passthrough_enabled: Optional[bool] = None + """ + Enable on-net T38 if you prefer the sender and receiver negotiating T38 directly + if both are on the Telnyx network. If this is disabled, Telnyx will be able to + use T38 on just one leg of the call depending on each leg's settings. + """ + + outbound: Optional[DataOutbound] = None + + password: Optional[str] = None + """The password to be used as part of the credentials. + + Must be 8 to 128 characters long. + """ + + record_type: Optional[str] = None + """Identifies the type of the resource.""" + + registration_status: Optional[str] = None + """The most recently known SIP registration status for this UAC connection.""" + + registration_status_updated_at: Optional[str] = None + """ + ISO 8601 formatted date indicating when the registration status was last + updated. + """ + + rtcp_settings: Optional[ConnectionRtcpSettings] = None + + sip_uri_calling_preference: Optional[Literal["disabled", "unrestricted", "internal"]] = None + """This feature enables inbound SIP URI calls to your Credential Auth Connection. + + If enabled for all (unrestricted) then anyone who calls the SIP URI + @telnyx.com will be connected to your Connection. You can also + choose to allow only calls that are originated on any Connections under your + account (internal). + """ + + tags: Optional[List[str]] = None + """Tags associated with the connection.""" + + updated_at: Optional[str] = None + """ISO-8601 formatted date indicating when the resource was updated.""" + + user_name: Optional[str] = None + """The user name to be used as part of the credentials. + + Must be 4-32 characters long and alphanumeric values only (no spaces or special + characters). At least one of the first 5 characters must be a letter. + """ + + webhook_api_version: Optional[Literal["1", "2"]] = None + """Determines which webhook format will be used, Telnyx API v1 or v2.""" + + webhook_event_failover_url: Optional[str] = None + """ + The failover URL where webhooks related to this connection will be sent if + sending to the primary URL fails. Must include a scheme, such as 'https'. + """ + + webhook_event_url: Optional[str] = None + """The URL where webhooks related to this connection will be sent. + + Must include a scheme, such as 'https'. + """ + + webhook_timeout_secs: Optional[int] = None + """Specifies how many seconds to wait before timing out a webhook.""" class UacConnectionCreateResponse(BaseModel): - data: Optional[UacConnection] = None + data: Optional[Data] = None """ A UAC (User Agent Client) Connection registers Telnyx to your PBX — the opposite of a standard SIP trunk, where the PBX registers to Telnyx. Use UAC when your diff --git a/src/telnyx/types/uac_connection_delete_response.py b/src/telnyx/types/uac_connection_delete_response.py index f21476d0..48377528 100644 --- a/src/telnyx/types/uac_connection_delete_response.py +++ b/src/telnyx/types/uac_connection_delete_response.py @@ -1,15 +1,397 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import Optional +from typing import List, Optional +from typing_extensions import Literal +from .fqdn import Fqdn from .._models import BaseModel -from .uac_connection import UacConnection +from .dtmf_type import DtmfType +from .encrypted_media import EncryptedMedia +from .anchorsite_override import AnchorsiteOverride +from .connection_rtcp_settings import ConnectionRtcpSettings +from .shared.connection_jitter_buffer import ConnectionJitterBuffer +from .shared.connection_noise_suppression_details import ConnectionNoiseSuppressionDetails -__all__ = ["UacConnectionDeleteResponse"] +__all__ = [ + "UacConnectionDeleteResponse", + "Data", + "DataExternalUacSettings", + "DataInbound", + "DataInternalUacSettings", + "DataOutbound", +] + + +class DataExternalUacSettings(BaseModel): + """ + External SIP peer settings used by Telnyx when registering to your PBX and routing outbound calls. + """ + + auth_username: Optional[str] = None + """The authentication username used in SIP digest authentication. + + If not set, the Username value will be used. + """ + + expiration_sec: Optional[int] = None + """ + The registration interval, in seconds, indicating how often the system refreshes + the SIP registration with the external SIP peer. + """ + + from_user: Optional[str] = None + """The user portion of the SIP From header used in outbound requests. + + This controls the caller identity presented to the external SIP peer. + """ + + outbound_proxy: Optional[str] = None + """ + An optional SIP proxy used to route outbound requests before reaching the + external SIP peer. + """ + + password: Optional[str] = None + """The SIP password used for digest authentication with the external SIP peer.""" + + proxy: Optional[str] = None + """ + The SIP proxy address of the external SIP peer used for registrations and + outbound call routing. + """ + + transport: Optional[Literal["UDP", "TLS", "TCP"]] = None + """ + The transport protocol used for SIP signaling when communicating with the + external SIP peer. One of UDP, TLS, or TCP. + """ + + username: Optional[str] = None + """ + The SIP username used to authenticate with the external SIP peer for + registrations and outbound calls. Must start with a letter or number and contain + only letters, numbers, hyphens, and underscores. + """ + + +class DataInbound(BaseModel): + ani_number_format: Optional[Literal["+E.164", "E.164", "+E.164-national", "E.164-national"]] = None + """ + This setting allows you to set the format with which the caller's number (ANI) + is sent for inbound phone calls. + """ + + channel_limit: Optional[int] = None + """ + When set, this will limit the total number of inbound calls to phone numbers + associated with this connection. + """ + + codecs: Optional[List[str]] = None + """ + Defines the list of codecs that Telnyx will send for inbound calls to a specific + number on your portal account, in priority order. This only works when the + Connection the number is assigned to uses Media Handling mode: default. OPUS and + H.264 codecs are available only when using TCP or TLS transport for SIP. + """ + + default_routing_method: Optional[Literal["sequential", "round-robin"]] = None + """ + Default routing method to be used when a number is associated with the + connection. Must be one of the routing method types or left blank, other values + are not allowed. + """ + + dnis_number_format: Optional[Literal["+e164", "e164", "national", "sip_username"]] = None + + generate_ringback_tone: Optional[bool] = None + """Generate ringback tone through 183 session progress message with early media.""" + + isup_headers_enabled: Optional[bool] = None + """When set, inbound phone calls will receive ISUP parameters via SIP headers. + + (Only when available and only when using TCP or TLS transport.) + """ + + prack_enabled: Optional[bool] = None + """Enable PRACK messages as defined in RFC3262.""" + + shaken_stir_enabled: Optional[bool] = None + """ + When enabled the SIP Connection will receive the Identity header with + Shaken/Stir data in the SIP INVITE message of inbound calls, even when using UDP + transport. + """ + + simultaneous_ringing: Optional[Literal["disabled", "enabled"]] = None + """When enabled, allows multiple devices to ring simultaneously on incoming calls.""" + + sip_compact_headers_enabled: Optional[bool] = None + """Defaults to true.""" + + sip_subdomain: Optional[str] = None + """The Telnyx-generated SIP subdomain for this UAC connection.""" + + sip_subdomain_receive_settings: Optional[Literal["only_my_connections", "from_anyone"]] = None + """Controls which SIP URI callers may reach this connection.""" + + timeout_1xx_secs: Optional[int] = None + """Time(sec) before aborting if connection is not made.""" + + timeout_2xx_secs: Optional[int] = None + """Time(sec) before aborting if call is unanswered (min: 1, max: 600).""" + + +class DataInternalUacSettings(BaseModel): + """Internal Telnyx-side settings for a UAC connection.""" + + destination_uri: Optional[str] = None + """ + The SIP URI that Telnyx will call when handling an inbound request from the + external peer. Do not include a `sip:` prefix. The value must be in the format + `userinfo@sip.telnyx.com` or + `userinfo@sipdev.telnyx.com`; the userinfo portion may contain only + letters, digits, hyphens, and underscores. + """ + + +class DataOutbound(BaseModel): + ani_override: Optional[str] = None + """ + Set a phone number as the ani_override value to override caller id number on + outbound calls. + """ + + ani_override_type: Optional[Literal["always", "normal", "emergency"]] = None + """Specifies when we apply your ani_override setting. + + Only applies when ani_override is not blank. + """ + + call_parking_enabled: Optional[bool] = None + """ + Forces all SIP calls originated on this connection to be "parked" instead of + "bridged" to the destination specified on the URI. Parked calls will return + ringback to the caller and will await for a Call Control command to define which + action will be taken next. + """ + + channel_limit: Optional[int] = None + """ + When set, this will limit the total number of outbound calls to phone numbers + associated with this connection. + """ + + generate_ringback_tone: Optional[bool] = None + """Generate ringback tone through 183 session progress message with early media.""" + + instant_ringback_enabled: Optional[bool] = None + """ + When set, ringback will not wait for indication before sending ringback tone to + calling party. + """ + + localization: Optional[str] = None + """ + A 2-character country code specifying the country whose national dialing rules + should be used. For example, if set to `US` then any US number can be dialed + without preprending +1 to the number. When left blank, Telnyx will try US and GB + dialing rules, in that order, by default. + """ + + outbound_voice_profile_id: Optional[str] = None + """Identifies the associated outbound voice profile.""" + + t38_reinvite_source: Optional[ + Literal["telnyx", "customer", "disabled", "passthru", "caller-passthru", "callee-passthru"] + ] = None + """This setting only affects connections with Fax-type Outbound Voice Profiles. + + The setting dictates whether or not Telnyx sends a t.38 reinvite.

By + default, Telnyx will send the re-invite. If set to `customer`, the caller is + expected to send the t.38 reinvite. + """ + + +class Data(BaseModel): + """ + A UAC (User Agent Client) Connection registers Telnyx to your PBX — the opposite of a standard SIP trunk, where the PBX registers to Telnyx. Use UAC when your PBX doesn’t support outbound SIP registration or you need Telnyx to maintain the registration. + """ + + id: Optional[str] = None + """Identifies the type of resource.""" + + active: Optional[bool] = None + """Defaults to true""" + + anchorsite_override: Optional[AnchorsiteOverride] = None + """ + `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 + ping messages. This can be disabled by specifying a site to handle all media. + """ + + android_push_credential_id: Optional[str] = None + """The uuid of the push credential for Android""" + + authentication: Optional[Literal["uac-authentication"]] = None + """The authentication strategy used by this connection.""" + + call_cost_in_webhooks: Optional[bool] = None + """Specifies if call cost webhooks should be sent for this connection.""" + + connection_name: Optional[str] = None + + created_at: Optional[str] = None + """ISO-8601 formatted date indicating when the resource was created.""" + + default_on_hold_comfort_noise_enabled: Optional[bool] = None + """When enabled, Telnyx will generate comfort noise when you place the call on + hold. + + If disabled, you will need to generate comfort noise or on hold music to avoid + RTP timeout. + """ + + dtmf_type: Optional[DtmfType] = None + """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. + """ + + encode_contact_header_enabled: Optional[bool] = None + """ + Encode the SIP contact header sent by Telnyx to avoid issues for NAT or ALG + scenarios. + """ + + encrypted_media: Optional[EncryptedMedia] = None + """Enable use of SRTP for encryption. + + Cannot be set if the transport_portocol is TLS. + """ + + external_uac_settings: Optional[DataExternalUacSettings] = None + """ + External SIP peer settings used by Telnyx when registering to your PBX and + routing outbound calls. + """ + + fqdn: Optional[str] = None + """The Telnyx-managed FQDN generated for the UAC connection.""" + + fqdn_outbound_authentication: Optional[Literal["credential-authentication"]] = None + """The fixed outbound authentication mode used by UAC FQDN records.""" + + fqdns: Optional[List[Fqdn]] = None + """FQDN records managed automatically by the UAC connection lifecycle.""" + + inbound: Optional[DataInbound] = None + + internal_uac_settings: Optional[DataInternalUacSettings] = None + """Internal Telnyx-side settings for a UAC connection.""" + + ios_push_credential_id: Optional[str] = None + """The uuid of the push credential for Ios""" + + jitter_buffer: Optional[ConnectionJitterBuffer] = None + """Configuration options for Jitter Buffer. + + Enables Jitter Buffer for RTP streams of SIP Trunking calls. The feature is off + unless enabled. You may define min and max values in msec for customized + buffering behaviors. Larger values add latency but tolerate more jitter, while + smaller values reduce latency but are more sensitive to jitter and reordering. + """ + + noise_suppression: Optional[Literal["inbound", "outbound", "both", "disabled"]] = None + """Controls when noise suppression is applied to calls. + + When set to 'inbound', noise suppression is applied to incoming audio. When set + to 'outbound', it's applied to outgoing audio. When set to 'both', it's applied + in both directions. When set to 'disabled', noise suppression is turned off. + """ + + noise_suppression_details: Optional[ConnectionNoiseSuppressionDetails] = None + """Configuration options for noise suppression. + + These settings are stored regardless of the noise_suppression value, but only + take effect when noise_suppression is not 'disabled'. If you disable noise + suppression and later re-enable it, the previously configured settings will be + used. + """ + + onnet_t38_passthrough_enabled: Optional[bool] = None + """ + Enable on-net T38 if you prefer the sender and receiver negotiating T38 directly + if both are on the Telnyx network. If this is disabled, Telnyx will be able to + use T38 on just one leg of the call depending on each leg's settings. + """ + + outbound: Optional[DataOutbound] = None + + password: Optional[str] = None + """The password to be used as part of the credentials. + + Must be 8 to 128 characters long. + """ + + record_type: Optional[str] = None + """Identifies the type of the resource.""" + + registration_status: Optional[str] = None + """The most recently known SIP registration status for this UAC connection.""" + + registration_status_updated_at: Optional[str] = None + """ + ISO 8601 formatted date indicating when the registration status was last + updated. + """ + + rtcp_settings: Optional[ConnectionRtcpSettings] = None + + sip_uri_calling_preference: Optional[Literal["disabled", "unrestricted", "internal"]] = None + """This feature enables inbound SIP URI calls to your Credential Auth Connection. + + If enabled for all (unrestricted) then anyone who calls the SIP URI + @telnyx.com will be connected to your Connection. You can also + choose to allow only calls that are originated on any Connections under your + account (internal). + """ + + tags: Optional[List[str]] = None + """Tags associated with the connection.""" + + updated_at: Optional[str] = None + """ISO-8601 formatted date indicating when the resource was updated.""" + + user_name: Optional[str] = None + """The user name to be used as part of the credentials. + + Must be 4-32 characters long and alphanumeric values only (no spaces or special + characters). At least one of the first 5 characters must be a letter. + """ + + webhook_api_version: Optional[Literal["1", "2"]] = None + """Determines which webhook format will be used, Telnyx API v1 or v2.""" + + webhook_event_failover_url: Optional[str] = None + """ + The failover URL where webhooks related to this connection will be sent if + sending to the primary URL fails. Must include a scheme, such as 'https'. + """ + + webhook_event_url: Optional[str] = None + """The URL where webhooks related to this connection will be sent. + + Must include a scheme, such as 'https'. + """ + + webhook_timeout_secs: Optional[int] = None + """Specifies how many seconds to wait before timing out a webhook.""" class UacConnectionDeleteResponse(BaseModel): - data: Optional[UacConnection] = None + data: Optional[Data] = None """ A UAC (User Agent Client) Connection registers Telnyx to your PBX — the opposite of a standard SIP trunk, where the PBX registers to Telnyx. Use UAC when your diff --git a/src/telnyx/types/uac_connection_list_response.py b/src/telnyx/types/uac_connection_list_response.py new file mode 100644 index 00000000..cc6ef7d0 --- /dev/null +++ b/src/telnyx/types/uac_connection_list_response.py @@ -0,0 +1,383 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional +from typing_extensions import Literal + +from .fqdn import Fqdn +from .._models import BaseModel +from .dtmf_type import DtmfType +from .encrypted_media import EncryptedMedia +from .anchorsite_override import AnchorsiteOverride +from .connection_rtcp_settings import ConnectionRtcpSettings +from .shared.connection_jitter_buffer import ConnectionJitterBuffer +from .shared.connection_noise_suppression_details import ConnectionNoiseSuppressionDetails + +__all__ = ["UacConnectionListResponse", "ExternalUacSettings", "Inbound", "InternalUacSettings", "Outbound"] + + +class ExternalUacSettings(BaseModel): + """ + External SIP peer settings used by Telnyx when registering to your PBX and routing outbound calls. + """ + + auth_username: Optional[str] = None + """The authentication username used in SIP digest authentication. + + If not set, the Username value will be used. + """ + + expiration_sec: Optional[int] = None + """ + The registration interval, in seconds, indicating how often the system refreshes + the SIP registration with the external SIP peer. + """ + + from_user: Optional[str] = None + """The user portion of the SIP From header used in outbound requests. + + This controls the caller identity presented to the external SIP peer. + """ + + outbound_proxy: Optional[str] = None + """ + An optional SIP proxy used to route outbound requests before reaching the + external SIP peer. + """ + + password: Optional[str] = None + """The SIP password used for digest authentication with the external SIP peer.""" + + proxy: Optional[str] = None + """ + The SIP proxy address of the external SIP peer used for registrations and + outbound call routing. + """ + + transport: Optional[Literal["UDP", "TLS", "TCP"]] = None + """ + The transport protocol used for SIP signaling when communicating with the + external SIP peer. One of UDP, TLS, or TCP. + """ + + username: Optional[str] = None + """ + The SIP username used to authenticate with the external SIP peer for + registrations and outbound calls. Must start with a letter or number and contain + only letters, numbers, hyphens, and underscores. + """ + + +class Inbound(BaseModel): + ani_number_format: Optional[Literal["+E.164", "E.164", "+E.164-national", "E.164-national"]] = None + """ + This setting allows you to set the format with which the caller's number (ANI) + is sent for inbound phone calls. + """ + + channel_limit: Optional[int] = None + """ + When set, this will limit the total number of inbound calls to phone numbers + associated with this connection. + """ + + codecs: Optional[List[str]] = None + """ + Defines the list of codecs that Telnyx will send for inbound calls to a specific + number on your portal account, in priority order. This only works when the + Connection the number is assigned to uses Media Handling mode: default. OPUS and + H.264 codecs are available only when using TCP or TLS transport for SIP. + """ + + default_routing_method: Optional[Literal["sequential", "round-robin"]] = None + """ + Default routing method to be used when a number is associated with the + connection. Must be one of the routing method types or left blank, other values + are not allowed. + """ + + dnis_number_format: Optional[Literal["+e164", "e164", "national", "sip_username"]] = None + + generate_ringback_tone: Optional[bool] = None + """Generate ringback tone through 183 session progress message with early media.""" + + isup_headers_enabled: Optional[bool] = None + """When set, inbound phone calls will receive ISUP parameters via SIP headers. + + (Only when available and only when using TCP or TLS transport.) + """ + + prack_enabled: Optional[bool] = None + """Enable PRACK messages as defined in RFC3262.""" + + shaken_stir_enabled: Optional[bool] = None + """ + When enabled the SIP Connection will receive the Identity header with + Shaken/Stir data in the SIP INVITE message of inbound calls, even when using UDP + transport. + """ + + simultaneous_ringing: Optional[Literal["disabled", "enabled"]] = None + """When enabled, allows multiple devices to ring simultaneously on incoming calls.""" + + sip_compact_headers_enabled: Optional[bool] = None + """Defaults to true.""" + + sip_subdomain: Optional[str] = None + """The Telnyx-generated SIP subdomain for this UAC connection.""" + + sip_subdomain_receive_settings: Optional[Literal["only_my_connections", "from_anyone"]] = None + """Controls which SIP URI callers may reach this connection.""" + + timeout_1xx_secs: Optional[int] = None + """Time(sec) before aborting if connection is not made.""" + + timeout_2xx_secs: Optional[int] = None + """Time(sec) before aborting if call is unanswered (min: 1, max: 600).""" + + +class InternalUacSettings(BaseModel): + """Internal Telnyx-side settings for a UAC connection.""" + + destination_uri: Optional[str] = None + """ + The SIP URI that Telnyx will call when handling an inbound request from the + external peer. Do not include a `sip:` prefix. The value must be in the format + `userinfo@sip.telnyx.com` or + `userinfo@sipdev.telnyx.com`; the userinfo portion may contain only + letters, digits, hyphens, and underscores. + """ + + +class Outbound(BaseModel): + ani_override: Optional[str] = None + """ + Set a phone number as the ani_override value to override caller id number on + outbound calls. + """ + + ani_override_type: Optional[Literal["always", "normal", "emergency"]] = None + """Specifies when we apply your ani_override setting. + + Only applies when ani_override is not blank. + """ + + call_parking_enabled: Optional[bool] = None + """ + Forces all SIP calls originated on this connection to be "parked" instead of + "bridged" to the destination specified on the URI. Parked calls will return + ringback to the caller and will await for a Call Control command to define which + action will be taken next. + """ + + channel_limit: Optional[int] = None + """ + When set, this will limit the total number of outbound calls to phone numbers + associated with this connection. + """ + + generate_ringback_tone: Optional[bool] = None + """Generate ringback tone through 183 session progress message with early media.""" + + instant_ringback_enabled: Optional[bool] = None + """ + When set, ringback will not wait for indication before sending ringback tone to + calling party. + """ + + localization: Optional[str] = None + """ + A 2-character country code specifying the country whose national dialing rules + should be used. For example, if set to `US` then any US number can be dialed + without preprending +1 to the number. When left blank, Telnyx will try US and GB + dialing rules, in that order, by default. + """ + + outbound_voice_profile_id: Optional[str] = None + """Identifies the associated outbound voice profile.""" + + t38_reinvite_source: Optional[ + Literal["telnyx", "customer", "disabled", "passthru", "caller-passthru", "callee-passthru"] + ] = None + """This setting only affects connections with Fax-type Outbound Voice Profiles. + + The setting dictates whether or not Telnyx sends a t.38 reinvite.

By + default, Telnyx will send the re-invite. If set to `customer`, the caller is + expected to send the t.38 reinvite. + """ + + +class UacConnectionListResponse(BaseModel): + """ + A UAC (User Agent Client) Connection registers Telnyx to your PBX — the opposite of a standard SIP trunk, where the PBX registers to Telnyx. Use UAC when your PBX doesn’t support outbound SIP registration or you need Telnyx to maintain the registration. + """ + + id: Optional[str] = None + """Identifies the type of resource.""" + + active: Optional[bool] = None + """Defaults to true""" + + anchorsite_override: Optional[AnchorsiteOverride] = None + """ + `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 + ping messages. This can be disabled by specifying a site to handle all media. + """ + + android_push_credential_id: Optional[str] = None + """The uuid of the push credential for Android""" + + authentication: Optional[Literal["uac-authentication"]] = None + """The authentication strategy used by this connection.""" + + call_cost_in_webhooks: Optional[bool] = None + """Specifies if call cost webhooks should be sent for this connection.""" + + connection_name: Optional[str] = None + + created_at: Optional[str] = None + """ISO-8601 formatted date indicating when the resource was created.""" + + default_on_hold_comfort_noise_enabled: Optional[bool] = None + """When enabled, Telnyx will generate comfort noise when you place the call on + hold. + + If disabled, you will need to generate comfort noise or on hold music to avoid + RTP timeout. + """ + + dtmf_type: Optional[DtmfType] = None + """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. + """ + + encode_contact_header_enabled: Optional[bool] = None + """ + Encode the SIP contact header sent by Telnyx to avoid issues for NAT or ALG + scenarios. + """ + + encrypted_media: Optional[EncryptedMedia] = None + """Enable use of SRTP for encryption. + + Cannot be set if the transport_portocol is TLS. + """ + + external_uac_settings: Optional[ExternalUacSettings] = None + """ + External SIP peer settings used by Telnyx when registering to your PBX and + routing outbound calls. + """ + + fqdn: Optional[str] = None + """The Telnyx-managed FQDN generated for the UAC connection.""" + + fqdn_outbound_authentication: Optional[Literal["credential-authentication"]] = None + """The fixed outbound authentication mode used by UAC FQDN records.""" + + fqdns: Optional[List[Fqdn]] = None + """FQDN records managed automatically by the UAC connection lifecycle.""" + + inbound: Optional[Inbound] = None + + internal_uac_settings: Optional[InternalUacSettings] = None + """Internal Telnyx-side settings for a UAC connection.""" + + ios_push_credential_id: Optional[str] = None + """The uuid of the push credential for Ios""" + + jitter_buffer: Optional[ConnectionJitterBuffer] = None + """Configuration options for Jitter Buffer. + + Enables Jitter Buffer for RTP streams of SIP Trunking calls. The feature is off + unless enabled. You may define min and max values in msec for customized + buffering behaviors. Larger values add latency but tolerate more jitter, while + smaller values reduce latency but are more sensitive to jitter and reordering. + """ + + noise_suppression: Optional[Literal["inbound", "outbound", "both", "disabled"]] = None + """Controls when noise suppression is applied to calls. + + When set to 'inbound', noise suppression is applied to incoming audio. When set + to 'outbound', it's applied to outgoing audio. When set to 'both', it's applied + in both directions. When set to 'disabled', noise suppression is turned off. + """ + + noise_suppression_details: Optional[ConnectionNoiseSuppressionDetails] = None + """Configuration options for noise suppression. + + These settings are stored regardless of the noise_suppression value, but only + take effect when noise_suppression is not 'disabled'. If you disable noise + suppression and later re-enable it, the previously configured settings will be + used. + """ + + onnet_t38_passthrough_enabled: Optional[bool] = None + """ + Enable on-net T38 if you prefer the sender and receiver negotiating T38 directly + if both are on the Telnyx network. If this is disabled, Telnyx will be able to + use T38 on just one leg of the call depending on each leg's settings. + """ + + outbound: Optional[Outbound] = None + + password: Optional[str] = None + """The password to be used as part of the credentials. + + Must be 8 to 128 characters long. + """ + + record_type: Optional[str] = None + """Identifies the type of the resource.""" + + registration_status: Optional[str] = None + """The most recently known SIP registration status for this UAC connection.""" + + registration_status_updated_at: Optional[str] = None + """ + ISO 8601 formatted date indicating when the registration status was last + updated. + """ + + rtcp_settings: Optional[ConnectionRtcpSettings] = None + + sip_uri_calling_preference: Optional[Literal["disabled", "unrestricted", "internal"]] = None + """This feature enables inbound SIP URI calls to your Credential Auth Connection. + + If enabled for all (unrestricted) then anyone who calls the SIP URI + @telnyx.com will be connected to your Connection. You can also + choose to allow only calls that are originated on any Connections under your + account (internal). + """ + + tags: Optional[List[str]] = None + """Tags associated with the connection.""" + + updated_at: Optional[str] = None + """ISO-8601 formatted date indicating when the resource was updated.""" + + user_name: Optional[str] = None + """The user name to be used as part of the credentials. + + Must be 4-32 characters long and alphanumeric values only (no spaces or special + characters). At least one of the first 5 characters must be a letter. + """ + + webhook_api_version: Optional[Literal["1", "2"]] = None + """Determines which webhook format will be used, Telnyx API v1 or v2.""" + + webhook_event_failover_url: Optional[str] = None + """ + The failover URL where webhooks related to this connection will be sent if + sending to the primary URL fails. Must include a scheme, such as 'https'. + """ + + webhook_event_url: Optional[str] = None + """The URL where webhooks related to this connection will be sent. + + Must include a scheme, such as 'https'. + """ + + webhook_timeout_secs: Optional[int] = None + """Specifies how many seconds to wait before timing out a webhook.""" diff --git a/src/telnyx/types/uac_connection_retrieve_response.py b/src/telnyx/types/uac_connection_retrieve_response.py index f48bcb8f..59e49d50 100644 --- a/src/telnyx/types/uac_connection_retrieve_response.py +++ b/src/telnyx/types/uac_connection_retrieve_response.py @@ -1,15 +1,397 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import Optional +from typing import List, Optional +from typing_extensions import Literal +from .fqdn import Fqdn from .._models import BaseModel -from .uac_connection import UacConnection +from .dtmf_type import DtmfType +from .encrypted_media import EncryptedMedia +from .anchorsite_override import AnchorsiteOverride +from .connection_rtcp_settings import ConnectionRtcpSettings +from .shared.connection_jitter_buffer import ConnectionJitterBuffer +from .shared.connection_noise_suppression_details import ConnectionNoiseSuppressionDetails -__all__ = ["UacConnectionRetrieveResponse"] +__all__ = [ + "UacConnectionRetrieveResponse", + "Data", + "DataExternalUacSettings", + "DataInbound", + "DataInternalUacSettings", + "DataOutbound", +] + + +class DataExternalUacSettings(BaseModel): + """ + External SIP peer settings used by Telnyx when registering to your PBX and routing outbound calls. + """ + + auth_username: Optional[str] = None + """The authentication username used in SIP digest authentication. + + If not set, the Username value will be used. + """ + + expiration_sec: Optional[int] = None + """ + The registration interval, in seconds, indicating how often the system refreshes + the SIP registration with the external SIP peer. + """ + + from_user: Optional[str] = None + """The user portion of the SIP From header used in outbound requests. + + This controls the caller identity presented to the external SIP peer. + """ + + outbound_proxy: Optional[str] = None + """ + An optional SIP proxy used to route outbound requests before reaching the + external SIP peer. + """ + + password: Optional[str] = None + """The SIP password used for digest authentication with the external SIP peer.""" + + proxy: Optional[str] = None + """ + The SIP proxy address of the external SIP peer used for registrations and + outbound call routing. + """ + + transport: Optional[Literal["UDP", "TLS", "TCP"]] = None + """ + The transport protocol used for SIP signaling when communicating with the + external SIP peer. One of UDP, TLS, or TCP. + """ + + username: Optional[str] = None + """ + The SIP username used to authenticate with the external SIP peer for + registrations and outbound calls. Must start with a letter or number and contain + only letters, numbers, hyphens, and underscores. + """ + + +class DataInbound(BaseModel): + ani_number_format: Optional[Literal["+E.164", "E.164", "+E.164-national", "E.164-national"]] = None + """ + This setting allows you to set the format with which the caller's number (ANI) + is sent for inbound phone calls. + """ + + channel_limit: Optional[int] = None + """ + When set, this will limit the total number of inbound calls to phone numbers + associated with this connection. + """ + + codecs: Optional[List[str]] = None + """ + Defines the list of codecs that Telnyx will send for inbound calls to a specific + number on your portal account, in priority order. This only works when the + Connection the number is assigned to uses Media Handling mode: default. OPUS and + H.264 codecs are available only when using TCP or TLS transport for SIP. + """ + + default_routing_method: Optional[Literal["sequential", "round-robin"]] = None + """ + Default routing method to be used when a number is associated with the + connection. Must be one of the routing method types or left blank, other values + are not allowed. + """ + + dnis_number_format: Optional[Literal["+e164", "e164", "national", "sip_username"]] = None + + generate_ringback_tone: Optional[bool] = None + """Generate ringback tone through 183 session progress message with early media.""" + + isup_headers_enabled: Optional[bool] = None + """When set, inbound phone calls will receive ISUP parameters via SIP headers. + + (Only when available and only when using TCP or TLS transport.) + """ + + prack_enabled: Optional[bool] = None + """Enable PRACK messages as defined in RFC3262.""" + + shaken_stir_enabled: Optional[bool] = None + """ + When enabled the SIP Connection will receive the Identity header with + Shaken/Stir data in the SIP INVITE message of inbound calls, even when using UDP + transport. + """ + + simultaneous_ringing: Optional[Literal["disabled", "enabled"]] = None + """When enabled, allows multiple devices to ring simultaneously on incoming calls.""" + + sip_compact_headers_enabled: Optional[bool] = None + """Defaults to true.""" + + sip_subdomain: Optional[str] = None + """The Telnyx-generated SIP subdomain for this UAC connection.""" + + sip_subdomain_receive_settings: Optional[Literal["only_my_connections", "from_anyone"]] = None + """Controls which SIP URI callers may reach this connection.""" + + timeout_1xx_secs: Optional[int] = None + """Time(sec) before aborting if connection is not made.""" + + timeout_2xx_secs: Optional[int] = None + """Time(sec) before aborting if call is unanswered (min: 1, max: 600).""" + + +class DataInternalUacSettings(BaseModel): + """Internal Telnyx-side settings for a UAC connection.""" + + destination_uri: Optional[str] = None + """ + The SIP URI that Telnyx will call when handling an inbound request from the + external peer. Do not include a `sip:` prefix. The value must be in the format + `userinfo@sip.telnyx.com` or + `userinfo@sipdev.telnyx.com`; the userinfo portion may contain only + letters, digits, hyphens, and underscores. + """ + + +class DataOutbound(BaseModel): + ani_override: Optional[str] = None + """ + Set a phone number as the ani_override value to override caller id number on + outbound calls. + """ + + ani_override_type: Optional[Literal["always", "normal", "emergency"]] = None + """Specifies when we apply your ani_override setting. + + Only applies when ani_override is not blank. + """ + + call_parking_enabled: Optional[bool] = None + """ + Forces all SIP calls originated on this connection to be "parked" instead of + "bridged" to the destination specified on the URI. Parked calls will return + ringback to the caller and will await for a Call Control command to define which + action will be taken next. + """ + + channel_limit: Optional[int] = None + """ + When set, this will limit the total number of outbound calls to phone numbers + associated with this connection. + """ + + generate_ringback_tone: Optional[bool] = None + """Generate ringback tone through 183 session progress message with early media.""" + + instant_ringback_enabled: Optional[bool] = None + """ + When set, ringback will not wait for indication before sending ringback tone to + calling party. + """ + + localization: Optional[str] = None + """ + A 2-character country code specifying the country whose national dialing rules + should be used. For example, if set to `US` then any US number can be dialed + without preprending +1 to the number. When left blank, Telnyx will try US and GB + dialing rules, in that order, by default. + """ + + outbound_voice_profile_id: Optional[str] = None + """Identifies the associated outbound voice profile.""" + + t38_reinvite_source: Optional[ + Literal["telnyx", "customer", "disabled", "passthru", "caller-passthru", "callee-passthru"] + ] = None + """This setting only affects connections with Fax-type Outbound Voice Profiles. + + The setting dictates whether or not Telnyx sends a t.38 reinvite.

By + default, Telnyx will send the re-invite. If set to `customer`, the caller is + expected to send the t.38 reinvite. + """ + + +class Data(BaseModel): + """ + A UAC (User Agent Client) Connection registers Telnyx to your PBX — the opposite of a standard SIP trunk, where the PBX registers to Telnyx. Use UAC when your PBX doesn’t support outbound SIP registration or you need Telnyx to maintain the registration. + """ + + id: Optional[str] = None + """Identifies the type of resource.""" + + active: Optional[bool] = None + """Defaults to true""" + + anchorsite_override: Optional[AnchorsiteOverride] = None + """ + `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 + ping messages. This can be disabled by specifying a site to handle all media. + """ + + android_push_credential_id: Optional[str] = None + """The uuid of the push credential for Android""" + + authentication: Optional[Literal["uac-authentication"]] = None + """The authentication strategy used by this connection.""" + + call_cost_in_webhooks: Optional[bool] = None + """Specifies if call cost webhooks should be sent for this connection.""" + + connection_name: Optional[str] = None + + created_at: Optional[str] = None + """ISO-8601 formatted date indicating when the resource was created.""" + + default_on_hold_comfort_noise_enabled: Optional[bool] = None + """When enabled, Telnyx will generate comfort noise when you place the call on + hold. + + If disabled, you will need to generate comfort noise or on hold music to avoid + RTP timeout. + """ + + dtmf_type: Optional[DtmfType] = None + """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. + """ + + encode_contact_header_enabled: Optional[bool] = None + """ + Encode the SIP contact header sent by Telnyx to avoid issues for NAT or ALG + scenarios. + """ + + encrypted_media: Optional[EncryptedMedia] = None + """Enable use of SRTP for encryption. + + Cannot be set if the transport_portocol is TLS. + """ + + external_uac_settings: Optional[DataExternalUacSettings] = None + """ + External SIP peer settings used by Telnyx when registering to your PBX and + routing outbound calls. + """ + + fqdn: Optional[str] = None + """The Telnyx-managed FQDN generated for the UAC connection.""" + + fqdn_outbound_authentication: Optional[Literal["credential-authentication"]] = None + """The fixed outbound authentication mode used by UAC FQDN records.""" + + fqdns: Optional[List[Fqdn]] = None + """FQDN records managed automatically by the UAC connection lifecycle.""" + + inbound: Optional[DataInbound] = None + + internal_uac_settings: Optional[DataInternalUacSettings] = None + """Internal Telnyx-side settings for a UAC connection.""" + + ios_push_credential_id: Optional[str] = None + """The uuid of the push credential for Ios""" + + jitter_buffer: Optional[ConnectionJitterBuffer] = None + """Configuration options for Jitter Buffer. + + Enables Jitter Buffer for RTP streams of SIP Trunking calls. The feature is off + unless enabled. You may define min and max values in msec for customized + buffering behaviors. Larger values add latency but tolerate more jitter, while + smaller values reduce latency but are more sensitive to jitter and reordering. + """ + + noise_suppression: Optional[Literal["inbound", "outbound", "both", "disabled"]] = None + """Controls when noise suppression is applied to calls. + + When set to 'inbound', noise suppression is applied to incoming audio. When set + to 'outbound', it's applied to outgoing audio. When set to 'both', it's applied + in both directions. When set to 'disabled', noise suppression is turned off. + """ + + noise_suppression_details: Optional[ConnectionNoiseSuppressionDetails] = None + """Configuration options for noise suppression. + + These settings are stored regardless of the noise_suppression value, but only + take effect when noise_suppression is not 'disabled'. If you disable noise + suppression and later re-enable it, the previously configured settings will be + used. + """ + + onnet_t38_passthrough_enabled: Optional[bool] = None + """ + Enable on-net T38 if you prefer the sender and receiver negotiating T38 directly + if both are on the Telnyx network. If this is disabled, Telnyx will be able to + use T38 on just one leg of the call depending on each leg's settings. + """ + + outbound: Optional[DataOutbound] = None + + password: Optional[str] = None + """The password to be used as part of the credentials. + + Must be 8 to 128 characters long. + """ + + record_type: Optional[str] = None + """Identifies the type of the resource.""" + + registration_status: Optional[str] = None + """The most recently known SIP registration status for this UAC connection.""" + + registration_status_updated_at: Optional[str] = None + """ + ISO 8601 formatted date indicating when the registration status was last + updated. + """ + + rtcp_settings: Optional[ConnectionRtcpSettings] = None + + sip_uri_calling_preference: Optional[Literal["disabled", "unrestricted", "internal"]] = None + """This feature enables inbound SIP URI calls to your Credential Auth Connection. + + If enabled for all (unrestricted) then anyone who calls the SIP URI + @telnyx.com will be connected to your Connection. You can also + choose to allow only calls that are originated on any Connections under your + account (internal). + """ + + tags: Optional[List[str]] = None + """Tags associated with the connection.""" + + updated_at: Optional[str] = None + """ISO-8601 formatted date indicating when the resource was updated.""" + + user_name: Optional[str] = None + """The user name to be used as part of the credentials. + + Must be 4-32 characters long and alphanumeric values only (no spaces or special + characters). At least one of the first 5 characters must be a letter. + """ + + webhook_api_version: Optional[Literal["1", "2"]] = None + """Determines which webhook format will be used, Telnyx API v1 or v2.""" + + webhook_event_failover_url: Optional[str] = None + """ + The failover URL where webhooks related to this connection will be sent if + sending to the primary URL fails. Must include a scheme, such as 'https'. + """ + + webhook_event_url: Optional[str] = None + """The URL where webhooks related to this connection will be sent. + + Must include a scheme, such as 'https'. + """ + + webhook_timeout_secs: Optional[int] = None + """Specifies how many seconds to wait before timing out a webhook.""" class UacConnectionRetrieveResponse(BaseModel): - data: Optional[UacConnection] = None + data: Optional[Data] = None """ A UAC (User Agent Client) Connection registers Telnyx to your PBX — the opposite of a standard SIP trunk, where the PBX registers to Telnyx. Use UAC when your diff --git a/src/telnyx/types/uac_connection_update_params.py b/src/telnyx/types/uac_connection_update_params.py index affb7b5b..222838d2 100644 --- a/src/telnyx/types/uac_connection_update_params.py +++ b/src/telnyx/types/uac_connection_update_params.py @@ -8,15 +8,12 @@ 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_external_settings_param import UacExternalSettingsParam -from .uac_internal_settings_param import UacInternalSettingsParam 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", "Inbound"] +__all__ = ["UacConnectionUpdateParams", "ExternalUacSettings", "Inbound", "InternalUacSettings", "Outbound"] class UacConnectionUpdateParams(TypedDict, total=False): @@ -65,7 +62,7 @@ class UacConnectionUpdateParams(TypedDict, total=False): Cannot be set if the transport_portocol is TLS. """ - external_uac_settings: UacExternalSettingsParam + external_uac_settings: ExternalUacSettings """ External SIP peer settings used by Telnyx when registering to your PBX and routing outbound calls. @@ -79,7 +76,7 @@ class UacConnectionUpdateParams(TypedDict, total=False): Telnyx and are not accepted as request parameters. """ - internal_uac_settings: UacInternalSettingsParam + internal_uac_settings: InternalUacSettings """Internal Telnyx-side settings for a UAC connection.""" ios_push_credential_id: Optional[str] @@ -118,7 +115,7 @@ class UacConnectionUpdateParams(TypedDict, total=False): use T38 on just one leg of the call depending on each leg's settings. """ - outbound: UacOutboundParam + outbound: Outbound password: str """The password to be used as part of the credentials. @@ -166,6 +163,58 @@ class UacConnectionUpdateParams(TypedDict, total=False): """Specifies how many seconds to wait before timing out a webhook.""" +class ExternalUacSettings(TypedDict, total=False): + """ + External SIP peer settings used by Telnyx when registering to your PBX and routing outbound calls. + """ + + auth_username: Optional[str] + """The authentication username used in SIP digest authentication. + + If not set, the Username value will be used. + """ + + expiration_sec: Optional[int] + """ + The registration interval, in seconds, indicating how often the system refreshes + the SIP registration with the external SIP peer. + """ + + from_user: Optional[str] + """The user portion of the SIP From header used in outbound requests. + + This controls the caller identity presented to the external SIP peer. + """ + + outbound_proxy: Optional[str] + """ + An optional SIP proxy used to route outbound requests before reaching the + external SIP peer. + """ + + password: str + """The SIP password used for digest authentication with the external SIP peer.""" + + proxy: str + """ + The SIP proxy address of the external SIP peer used for registrations and + outbound call routing. + """ + + transport: Optional[Literal["UDP", "TLS", "TCP"]] + """ + The transport protocol used for SIP signaling when communicating with the + external SIP peer. One of UDP, TLS, or TCP. + """ + + username: str + """ + The SIP username used to authenticate with the external SIP peer for + registrations and outbound calls. Must start with a letter or number and contain + only letters, numbers, hyphens, and underscores. + """ + + class Inbound(TypedDict, total=False): """Inbound settings that can be supplied when creating or updating a UAC connection. @@ -231,3 +280,72 @@ class Inbound(TypedDict, total=False): timeout_2xx_secs: int """Time(sec) before aborting if call is unanswered (min: 1, max: 600).""" + + +class InternalUacSettings(TypedDict, total=False): + """Internal Telnyx-side settings for a UAC connection.""" + + destination_uri: str + """ + The SIP URI that Telnyx will call when handling an inbound request from the + external peer. Do not include a `sip:` prefix. The value must be in the format + `userinfo@sip.telnyx.com` or + `userinfo@sipdev.telnyx.com`; the userinfo portion may contain only + letters, digits, hyphens, and underscores. + """ + + +class Outbound(TypedDict, total=False): + ani_override: str + """ + Set a phone number as the ani_override value to override caller id number on + outbound calls. + """ + + ani_override_type: Literal["always", "normal", "emergency"] + """Specifies when we apply your ani_override setting. + + Only applies when ani_override is not blank. + """ + + call_parking_enabled: Optional[bool] + """ + Forces all SIP calls originated on this connection to be "parked" instead of + "bridged" to the destination specified on the URI. Parked calls will return + ringback to the caller and will await for a Call Control command to define which + action will be taken next. + """ + + channel_limit: int + """ + When set, this will limit the total number of outbound calls to phone numbers + associated with this connection. + """ + + generate_ringback_tone: bool + """Generate ringback tone through 183 session progress message with early media.""" + + instant_ringback_enabled: bool + """ + When set, ringback will not wait for indication before sending ringback tone to + calling party. + """ + + localization: str + """ + A 2-character country code specifying the country whose national dialing rules + should be used. For example, if set to `US` then any US number can be dialed + without preprending +1 to the number. When left blank, Telnyx will try US and GB + dialing rules, in that order, by default. + """ + + outbound_voice_profile_id: str + """Identifies the associated outbound voice profile.""" + + t38_reinvite_source: Literal["telnyx", "customer", "disabled", "passthru", "caller-passthru", "callee-passthru"] + """This setting only affects connections with Fax-type Outbound Voice Profiles. + + The setting dictates whether or not Telnyx sends a t.38 reinvite.

By + default, Telnyx will send the re-invite. If set to `customer`, the caller is + expected to send the t.38 reinvite. + """ diff --git a/src/telnyx/types/uac_connection_update_response.py b/src/telnyx/types/uac_connection_update_response.py index 24090ac8..58e44a1b 100644 --- a/src/telnyx/types/uac_connection_update_response.py +++ b/src/telnyx/types/uac_connection_update_response.py @@ -1,15 +1,397 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import Optional +from typing import List, Optional +from typing_extensions import Literal +from .fqdn import Fqdn from .._models import BaseModel -from .uac_connection import UacConnection +from .dtmf_type import DtmfType +from .encrypted_media import EncryptedMedia +from .anchorsite_override import AnchorsiteOverride +from .connection_rtcp_settings import ConnectionRtcpSettings +from .shared.connection_jitter_buffer import ConnectionJitterBuffer +from .shared.connection_noise_suppression_details import ConnectionNoiseSuppressionDetails -__all__ = ["UacConnectionUpdateResponse"] +__all__ = [ + "UacConnectionUpdateResponse", + "Data", + "DataExternalUacSettings", + "DataInbound", + "DataInternalUacSettings", + "DataOutbound", +] + + +class DataExternalUacSettings(BaseModel): + """ + External SIP peer settings used by Telnyx when registering to your PBX and routing outbound calls. + """ + + auth_username: Optional[str] = None + """The authentication username used in SIP digest authentication. + + If not set, the Username value will be used. + """ + + expiration_sec: Optional[int] = None + """ + The registration interval, in seconds, indicating how often the system refreshes + the SIP registration with the external SIP peer. + """ + + from_user: Optional[str] = None + """The user portion of the SIP From header used in outbound requests. + + This controls the caller identity presented to the external SIP peer. + """ + + outbound_proxy: Optional[str] = None + """ + An optional SIP proxy used to route outbound requests before reaching the + external SIP peer. + """ + + password: Optional[str] = None + """The SIP password used for digest authentication with the external SIP peer.""" + + proxy: Optional[str] = None + """ + The SIP proxy address of the external SIP peer used for registrations and + outbound call routing. + """ + + transport: Optional[Literal["UDP", "TLS", "TCP"]] = None + """ + The transport protocol used for SIP signaling when communicating with the + external SIP peer. One of UDP, TLS, or TCP. + """ + + username: Optional[str] = None + """ + The SIP username used to authenticate with the external SIP peer for + registrations and outbound calls. Must start with a letter or number and contain + only letters, numbers, hyphens, and underscores. + """ + + +class DataInbound(BaseModel): + ani_number_format: Optional[Literal["+E.164", "E.164", "+E.164-national", "E.164-national"]] = None + """ + This setting allows you to set the format with which the caller's number (ANI) + is sent for inbound phone calls. + """ + + channel_limit: Optional[int] = None + """ + When set, this will limit the total number of inbound calls to phone numbers + associated with this connection. + """ + + codecs: Optional[List[str]] = None + """ + Defines the list of codecs that Telnyx will send for inbound calls to a specific + number on your portal account, in priority order. This only works when the + Connection the number is assigned to uses Media Handling mode: default. OPUS and + H.264 codecs are available only when using TCP or TLS transport for SIP. + """ + + default_routing_method: Optional[Literal["sequential", "round-robin"]] = None + """ + Default routing method to be used when a number is associated with the + connection. Must be one of the routing method types or left blank, other values + are not allowed. + """ + + dnis_number_format: Optional[Literal["+e164", "e164", "national", "sip_username"]] = None + + generate_ringback_tone: Optional[bool] = None + """Generate ringback tone through 183 session progress message with early media.""" + + isup_headers_enabled: Optional[bool] = None + """When set, inbound phone calls will receive ISUP parameters via SIP headers. + + (Only when available and only when using TCP or TLS transport.) + """ + + prack_enabled: Optional[bool] = None + """Enable PRACK messages as defined in RFC3262.""" + + shaken_stir_enabled: Optional[bool] = None + """ + When enabled the SIP Connection will receive the Identity header with + Shaken/Stir data in the SIP INVITE message of inbound calls, even when using UDP + transport. + """ + + simultaneous_ringing: Optional[Literal["disabled", "enabled"]] = None + """When enabled, allows multiple devices to ring simultaneously on incoming calls.""" + + sip_compact_headers_enabled: Optional[bool] = None + """Defaults to true.""" + + sip_subdomain: Optional[str] = None + """The Telnyx-generated SIP subdomain for this UAC connection.""" + + sip_subdomain_receive_settings: Optional[Literal["only_my_connections", "from_anyone"]] = None + """Controls which SIP URI callers may reach this connection.""" + + timeout_1xx_secs: Optional[int] = None + """Time(sec) before aborting if connection is not made.""" + + timeout_2xx_secs: Optional[int] = None + """Time(sec) before aborting if call is unanswered (min: 1, max: 600).""" + + +class DataInternalUacSettings(BaseModel): + """Internal Telnyx-side settings for a UAC connection.""" + + destination_uri: Optional[str] = None + """ + The SIP URI that Telnyx will call when handling an inbound request from the + external peer. Do not include a `sip:` prefix. The value must be in the format + `userinfo@sip.telnyx.com` or + `userinfo@sipdev.telnyx.com`; the userinfo portion may contain only + letters, digits, hyphens, and underscores. + """ + + +class DataOutbound(BaseModel): + ani_override: Optional[str] = None + """ + Set a phone number as the ani_override value to override caller id number on + outbound calls. + """ + + ani_override_type: Optional[Literal["always", "normal", "emergency"]] = None + """Specifies when we apply your ani_override setting. + + Only applies when ani_override is not blank. + """ + + call_parking_enabled: Optional[bool] = None + """ + Forces all SIP calls originated on this connection to be "parked" instead of + "bridged" to the destination specified on the URI. Parked calls will return + ringback to the caller and will await for a Call Control command to define which + action will be taken next. + """ + + channel_limit: Optional[int] = None + """ + When set, this will limit the total number of outbound calls to phone numbers + associated with this connection. + """ + + generate_ringback_tone: Optional[bool] = None + """Generate ringback tone through 183 session progress message with early media.""" + + instant_ringback_enabled: Optional[bool] = None + """ + When set, ringback will not wait for indication before sending ringback tone to + calling party. + """ + + localization: Optional[str] = None + """ + A 2-character country code specifying the country whose national dialing rules + should be used. For example, if set to `US` then any US number can be dialed + without preprending +1 to the number. When left blank, Telnyx will try US and GB + dialing rules, in that order, by default. + """ + + outbound_voice_profile_id: Optional[str] = None + """Identifies the associated outbound voice profile.""" + + t38_reinvite_source: Optional[ + Literal["telnyx", "customer", "disabled", "passthru", "caller-passthru", "callee-passthru"] + ] = None + """This setting only affects connections with Fax-type Outbound Voice Profiles. + + The setting dictates whether or not Telnyx sends a t.38 reinvite.

By + default, Telnyx will send the re-invite. If set to `customer`, the caller is + expected to send the t.38 reinvite. + """ + + +class Data(BaseModel): + """ + A UAC (User Agent Client) Connection registers Telnyx to your PBX — the opposite of a standard SIP trunk, where the PBX registers to Telnyx. Use UAC when your PBX doesn’t support outbound SIP registration or you need Telnyx to maintain the registration. + """ + + id: Optional[str] = None + """Identifies the type of resource.""" + + active: Optional[bool] = None + """Defaults to true""" + + anchorsite_override: Optional[AnchorsiteOverride] = None + """ + `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 + ping messages. This can be disabled by specifying a site to handle all media. + """ + + android_push_credential_id: Optional[str] = None + """The uuid of the push credential for Android""" + + authentication: Optional[Literal["uac-authentication"]] = None + """The authentication strategy used by this connection.""" + + call_cost_in_webhooks: Optional[bool] = None + """Specifies if call cost webhooks should be sent for this connection.""" + + connection_name: Optional[str] = None + + created_at: Optional[str] = None + """ISO-8601 formatted date indicating when the resource was created.""" + + default_on_hold_comfort_noise_enabled: Optional[bool] = None + """When enabled, Telnyx will generate comfort noise when you place the call on + hold. + + If disabled, you will need to generate comfort noise or on hold music to avoid + RTP timeout. + """ + + dtmf_type: Optional[DtmfType] = None + """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. + """ + + encode_contact_header_enabled: Optional[bool] = None + """ + Encode the SIP contact header sent by Telnyx to avoid issues for NAT or ALG + scenarios. + """ + + encrypted_media: Optional[EncryptedMedia] = None + """Enable use of SRTP for encryption. + + Cannot be set if the transport_portocol is TLS. + """ + + external_uac_settings: Optional[DataExternalUacSettings] = None + """ + External SIP peer settings used by Telnyx when registering to your PBX and + routing outbound calls. + """ + + fqdn: Optional[str] = None + """The Telnyx-managed FQDN generated for the UAC connection.""" + + fqdn_outbound_authentication: Optional[Literal["credential-authentication"]] = None + """The fixed outbound authentication mode used by UAC FQDN records.""" + + fqdns: Optional[List[Fqdn]] = None + """FQDN records managed automatically by the UAC connection lifecycle.""" + + inbound: Optional[DataInbound] = None + + internal_uac_settings: Optional[DataInternalUacSettings] = None + """Internal Telnyx-side settings for a UAC connection.""" + + ios_push_credential_id: Optional[str] = None + """The uuid of the push credential for Ios""" + + jitter_buffer: Optional[ConnectionJitterBuffer] = None + """Configuration options for Jitter Buffer. + + Enables Jitter Buffer for RTP streams of SIP Trunking calls. The feature is off + unless enabled. You may define min and max values in msec for customized + buffering behaviors. Larger values add latency but tolerate more jitter, while + smaller values reduce latency but are more sensitive to jitter and reordering. + """ + + noise_suppression: Optional[Literal["inbound", "outbound", "both", "disabled"]] = None + """Controls when noise suppression is applied to calls. + + When set to 'inbound', noise suppression is applied to incoming audio. When set + to 'outbound', it's applied to outgoing audio. When set to 'both', it's applied + in both directions. When set to 'disabled', noise suppression is turned off. + """ + + noise_suppression_details: Optional[ConnectionNoiseSuppressionDetails] = None + """Configuration options for noise suppression. + + These settings are stored regardless of the noise_suppression value, but only + take effect when noise_suppression is not 'disabled'. If you disable noise + suppression and later re-enable it, the previously configured settings will be + used. + """ + + onnet_t38_passthrough_enabled: Optional[bool] = None + """ + Enable on-net T38 if you prefer the sender and receiver negotiating T38 directly + if both are on the Telnyx network. If this is disabled, Telnyx will be able to + use T38 on just one leg of the call depending on each leg's settings. + """ + + outbound: Optional[DataOutbound] = None + + password: Optional[str] = None + """The password to be used as part of the credentials. + + Must be 8 to 128 characters long. + """ + + record_type: Optional[str] = None + """Identifies the type of the resource.""" + + registration_status: Optional[str] = None + """The most recently known SIP registration status for this UAC connection.""" + + registration_status_updated_at: Optional[str] = None + """ + ISO 8601 formatted date indicating when the registration status was last + updated. + """ + + rtcp_settings: Optional[ConnectionRtcpSettings] = None + + sip_uri_calling_preference: Optional[Literal["disabled", "unrestricted", "internal"]] = None + """This feature enables inbound SIP URI calls to your Credential Auth Connection. + + If enabled for all (unrestricted) then anyone who calls the SIP URI + @telnyx.com will be connected to your Connection. You can also + choose to allow only calls that are originated on any Connections under your + account (internal). + """ + + tags: Optional[List[str]] = None + """Tags associated with the connection.""" + + updated_at: Optional[str] = None + """ISO-8601 formatted date indicating when the resource was updated.""" + + user_name: Optional[str] = None + """The user name to be used as part of the credentials. + + Must be 4-32 characters long and alphanumeric values only (no spaces or special + characters). At least one of the first 5 characters must be a letter. + """ + + webhook_api_version: Optional[Literal["1", "2"]] = None + """Determines which webhook format will be used, Telnyx API v1 or v2.""" + + webhook_event_failover_url: Optional[str] = None + """ + The failover URL where webhooks related to this connection will be sent if + sending to the primary URL fails. Must include a scheme, such as 'https'. + """ + + webhook_event_url: Optional[str] = None + """The URL where webhooks related to this connection will be sent. + + Must include a scheme, such as 'https'. + """ + + webhook_timeout_secs: Optional[int] = None + """Specifies how many seconds to wait before timing out a webhook.""" class UacConnectionUpdateResponse(BaseModel): - data: Optional[UacConnection] = None + data: Optional[Data] = None """ A UAC (User Agent Client) Connection registers Telnyx to your PBX — the opposite of a standard SIP trunk, where the PBX registers to Telnyx. Use UAC when your diff --git a/src/telnyx/types/uac_external_settings.py b/src/telnyx/types/uac_external_settings.py deleted file mode 100644 index e0c5feba..00000000 --- a/src/telnyx/types/uac_external_settings.py +++ /dev/null @@ -1,60 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Optional -from typing_extensions import Literal - -from .._models import BaseModel - -__all__ = ["UacExternalSettings"] - - -class UacExternalSettings(BaseModel): - """ - External SIP peer settings used by Telnyx when registering to your PBX and routing outbound calls. - """ - - auth_username: Optional[str] = None - """The authentication username used in SIP digest authentication. - - If not set, the Username value will be used. - """ - - expiration_sec: Optional[int] = None - """ - The registration interval, in seconds, indicating how often the system refreshes - the SIP registration with the external SIP peer. - """ - - from_user: Optional[str] = None - """The user portion of the SIP From header used in outbound requests. - - This controls the caller identity presented to the external SIP peer. - """ - - outbound_proxy: Optional[str] = None - """ - An optional SIP proxy used to route outbound requests before reaching the - external SIP peer. - """ - - password: Optional[str] = None - """The SIP password used for digest authentication with the external SIP peer.""" - - proxy: Optional[str] = None - """ - The SIP proxy address of the external SIP peer used for registrations and - outbound call routing. - """ - - transport: Optional[Literal["UDP", "TLS", "TCP"]] = None - """ - The transport protocol used for SIP signaling when communicating with the - external SIP peer. One of UDP, TLS, or TCP. - """ - - username: Optional[str] = None - """ - The SIP username used to authenticate with the external SIP peer for - registrations and outbound calls. Must start with a letter or number and contain - only letters, numbers, hyphens, and underscores. - """ diff --git a/src/telnyx/types/uac_external_settings_param.py b/src/telnyx/types/uac_external_settings_param.py deleted file mode 100644 index e544ffdf..00000000 --- a/src/telnyx/types/uac_external_settings_param.py +++ /dev/null @@ -1,60 +0,0 @@ -# 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, TypedDict - -__all__ = ["UacExternalSettingsParam"] - - -class UacExternalSettingsParam(TypedDict, total=False): - """ - External SIP peer settings used by Telnyx when registering to your PBX and routing outbound calls. - """ - - auth_username: Optional[str] - """The authentication username used in SIP digest authentication. - - If not set, the Username value will be used. - """ - - expiration_sec: Optional[int] - """ - The registration interval, in seconds, indicating how often the system refreshes - the SIP registration with the external SIP peer. - """ - - from_user: Optional[str] - """The user portion of the SIP From header used in outbound requests. - - This controls the caller identity presented to the external SIP peer. - """ - - outbound_proxy: Optional[str] - """ - An optional SIP proxy used to route outbound requests before reaching the - external SIP peer. - """ - - password: str - """The SIP password used for digest authentication with the external SIP peer.""" - - proxy: str - """ - The SIP proxy address of the external SIP peer used for registrations and - outbound call routing. - """ - - transport: Optional[Literal["UDP", "TLS", "TCP"]] - """ - The transport protocol used for SIP signaling when communicating with the - external SIP peer. One of UDP, TLS, or TCP. - """ - - username: str - """ - The SIP username used to authenticate with the external SIP peer for - registrations and outbound calls. Must start with a letter or number and contain - only letters, numbers, hyphens, and underscores. - """ diff --git a/src/telnyx/types/uac_inbound.py b/src/telnyx/types/uac_inbound.py deleted file mode 100644 index 8266455b..00000000 --- a/src/telnyx/types/uac_inbound.py +++ /dev/null @@ -1,76 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import List, Optional -from typing_extensions import Literal - -from .._models import BaseModel - -__all__ = ["UacInbound"] - - -class UacInbound(BaseModel): - ani_number_format: Optional[Literal["+E.164", "E.164", "+E.164-national", "E.164-national"]] = None - """ - This setting allows you to set the format with which the caller's number (ANI) - is sent for inbound phone calls. - """ - - channel_limit: Optional[int] = None - """ - When set, this will limit the total number of inbound calls to phone numbers - associated with this connection. - """ - - codecs: Optional[List[str]] = None - """ - Defines the list of codecs that Telnyx will send for inbound calls to a specific - number on your portal account, in priority order. This only works when the - Connection the number is assigned to uses Media Handling mode: default. OPUS and - H.264 codecs are available only when using TCP or TLS transport for SIP. - """ - - default_routing_method: Optional[Literal["sequential", "round-robin"]] = None - """ - Default routing method to be used when a number is associated with the - connection. Must be one of the routing method types or left blank, other values - are not allowed. - """ - - dnis_number_format: Optional[Literal["+e164", "e164", "national", "sip_username"]] = None - - generate_ringback_tone: Optional[bool] = None - """Generate ringback tone through 183 session progress message with early media.""" - - isup_headers_enabled: Optional[bool] = None - """When set, inbound phone calls will receive ISUP parameters via SIP headers. - - (Only when available and only when using TCP or TLS transport.) - """ - - prack_enabled: Optional[bool] = None - """Enable PRACK messages as defined in RFC3262.""" - - shaken_stir_enabled: Optional[bool] = None - """ - When enabled the SIP Connection will receive the Identity header with - Shaken/Stir data in the SIP INVITE message of inbound calls, even when using UDP - transport. - """ - - simultaneous_ringing: Optional[Literal["disabled", "enabled"]] = None - """When enabled, allows multiple devices to ring simultaneously on incoming calls.""" - - sip_compact_headers_enabled: Optional[bool] = None - """Defaults to true.""" - - sip_subdomain: Optional[str] = None - """The Telnyx-generated SIP subdomain for this UAC connection.""" - - sip_subdomain_receive_settings: Optional[Literal["only_my_connections", "from_anyone"]] = None - """Controls which SIP URI callers may reach this connection.""" - - timeout_1xx_secs: Optional[int] = None - """Time(sec) before aborting if connection is not made.""" - - timeout_2xx_secs: Optional[int] = None - """Time(sec) before aborting if call is unanswered (min: 1, max: 600).""" diff --git a/src/telnyx/types/uac_internal_settings.py b/src/telnyx/types/uac_internal_settings.py deleted file mode 100644 index 799d1494..00000000 --- a/src/telnyx/types/uac_internal_settings.py +++ /dev/null @@ -1,20 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Optional - -from .._models import BaseModel - -__all__ = ["UacInternalSettings"] - - -class UacInternalSettings(BaseModel): - """Internal Telnyx-side settings for a UAC connection.""" - - destination_uri: Optional[str] = None - """ - The SIP URI that Telnyx will call when handling an inbound request from the - external peer. Do not include a `sip:` prefix. The value must be in the format - `userinfo@sip.telnyx.com` or - `userinfo@sipdev.telnyx.com`; the userinfo portion may contain only - letters, digits, hyphens, and underscores. - """ diff --git a/src/telnyx/types/uac_internal_settings_param.py b/src/telnyx/types/uac_internal_settings_param.py deleted file mode 100644 index 68ab4289..00000000 --- a/src/telnyx/types/uac_internal_settings_param.py +++ /dev/null @@ -1,20 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing_extensions import TypedDict - -__all__ = ["UacInternalSettingsParam"] - - -class UacInternalSettingsParam(TypedDict, total=False): - """Internal Telnyx-side settings for a UAC connection.""" - - destination_uri: str - """ - The SIP URI that Telnyx will call when handling an inbound request from the - external peer. Do not include a `sip:` prefix. The value must be in the format - `userinfo@sip.telnyx.com` or - `userinfo@sipdev.telnyx.com`; the userinfo portion may contain only - letters, digits, hyphens, and underscores. - """ diff --git a/src/telnyx/types/uac_outbound.py b/src/telnyx/types/uac_outbound.py deleted file mode 100644 index 81dcae6d..00000000 --- a/src/telnyx/types/uac_outbound.py +++ /dev/null @@ -1,66 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Optional -from typing_extensions import Literal - -from .._models import BaseModel - -__all__ = ["UacOutbound"] - - -class UacOutbound(BaseModel): - ani_override: Optional[str] = None - """ - Set a phone number as the ani_override value to override caller id number on - outbound calls. - """ - - ani_override_type: Optional[Literal["always", "normal", "emergency"]] = None - """Specifies when we apply your ani_override setting. - - Only applies when ani_override is not blank. - """ - - call_parking_enabled: Optional[bool] = None - """ - Forces all SIP calls originated on this connection to be "parked" instead of - "bridged" to the destination specified on the URI. Parked calls will return - ringback to the caller and will await for a Call Control command to define which - action will be taken next. - """ - - channel_limit: Optional[int] = None - """ - When set, this will limit the total number of outbound calls to phone numbers - associated with this connection. - """ - - generate_ringback_tone: Optional[bool] = None - """Generate ringback tone through 183 session progress message with early media.""" - - instant_ringback_enabled: Optional[bool] = None - """ - When set, ringback will not wait for indication before sending ringback tone to - calling party. - """ - - localization: Optional[str] = None - """ - A 2-character country code specifying the country whose national dialing rules - should be used. For example, if set to `US` then any US number can be dialed - without preprending +1 to the number. When left blank, Telnyx will try US and GB - dialing rules, in that order, by default. - """ - - outbound_voice_profile_id: Optional[str] = None - """Identifies the associated outbound voice profile.""" - - t38_reinvite_source: Optional[ - Literal["telnyx", "customer", "disabled", "passthru", "caller-passthru", "callee-passthru"] - ] = None - """This setting only affects connections with Fax-type Outbound Voice Profiles. - - The setting dictates whether or not Telnyx sends a t.38 reinvite.

By - default, Telnyx will send the re-invite. If set to `customer`, the caller is - expected to send the t.38 reinvite. - """ diff --git a/src/telnyx/types/uac_outbound_param.py b/src/telnyx/types/uac_outbound_param.py deleted file mode 100644 index c170e350..00000000 --- a/src/telnyx/types/uac_outbound_param.py +++ /dev/null @@ -1,64 +0,0 @@ -# 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, TypedDict - -__all__ = ["UacOutboundParam"] - - -class UacOutboundParam(TypedDict, total=False): - ani_override: str - """ - Set a phone number as the ani_override value to override caller id number on - outbound calls. - """ - - ani_override_type: Literal["always", "normal", "emergency"] - """Specifies when we apply your ani_override setting. - - Only applies when ani_override is not blank. - """ - - call_parking_enabled: Optional[bool] - """ - Forces all SIP calls originated on this connection to be "parked" instead of - "bridged" to the destination specified on the URI. Parked calls will return - ringback to the caller and will await for a Call Control command to define which - action will be taken next. - """ - - channel_limit: int - """ - When set, this will limit the total number of outbound calls to phone numbers - associated with this connection. - """ - - generate_ringback_tone: bool - """Generate ringback tone through 183 session progress message with early media.""" - - instant_ringback_enabled: bool - """ - When set, ringback will not wait for indication before sending ringback tone to - calling party. - """ - - localization: str - """ - A 2-character country code specifying the country whose national dialing rules - should be used. For example, if set to `US` then any US number can be dialed - without preprending +1 to the number. When left blank, Telnyx will try US and GB - dialing rules, in that order, by default. - """ - - outbound_voice_profile_id: str - """Identifies the associated outbound voice profile.""" - - t38_reinvite_source: Literal["telnyx", "customer", "disabled", "passthru", "caller-passthru", "callee-passthru"] - """This setting only affects connections with Fax-type Outbound Voice Profiles. - - The setting dictates whether or not Telnyx sends a t.38 reinvite.

By - default, Telnyx will send the re-invite. If set to `customer`, the caller is - expected to send the t.38 reinvite. - """ diff --git a/src/telnyx/types/virtual_cross_connect_combined.py b/src/telnyx/types/virtual_cross_connect_combined.py deleted file mode 100644 index 595a3fb3..00000000 --- a/src/telnyx/types/virtual_cross_connect_combined.py +++ /dev/null @@ -1,84 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Optional -from typing_extensions import Literal - -from .._models import BaseModel -from .interface_status import InterfaceStatus - -__all__ = ["VirtualCrossConnectCombined", "Region"] - - -class Region(BaseModel): - code: Optional[str] = None - """Region code of the interface.""" - - name: Optional[str] = None - """Region name of the interface.""" - - record_type: Optional[str] = None - """Identifies the type of the resource.""" - - -class VirtualCrossConnectCombined(BaseModel): - id: Optional[str] = None - """Identifies the resource.""" - - bandwidth_mbps: Optional[float] = None - """ - The desired throughput in Megabits per Second (Mbps) for your Virtual Cross - Connect. - """ - - bgp_asn: Optional[float] = None - """The Border Gateway Protocol (BGP) Autonomous System Number (ASN).""" - - cloud_provider: Optional[Literal["aws", "azure", "gce"]] = None - """ - The Virtual Private Cloud with which you would like to establish a cross - connect. - """ - - cloud_provider_region: Optional[str] = None - """The region where your Virtual Private Cloud hosts are located.""" - - created_at: Optional[str] = None - """ISO 8601 formatted date-time indicating when the resource was created.""" - - name: Optional[str] = None - """A user specified name for the interface.""" - - network_id: Optional[str] = None - """The id of the network associated with the interface.""" - - primary_bgp_key: Optional[str] = None - """The authentication key for BGP peer configuration.""" - - primary_cloud_account_id: Optional[str] = None - """The identifier for your Virtual Private Cloud.""" - - primary_cloud_ip: Optional[str] = None - """The IP address assigned for your side of the Virtual Cross Connect.""" - - primary_enabled: Optional[bool] = None - """Indicates whether the primary circuit is enabled.""" - - primary_routing_announcement: Optional[bool] = None - """Whether""" - - primary_telnyx_ip: Optional[str] = None - """The IP address assigned to the Telnyx side of the Virtual Cross Connect.""" - - record_type: Optional[str] = None - """Identifies the type of the resource.""" - - region: Optional[Region] = None - - region_code: Optional[str] = None - """The region interface is deployed to.""" - - status: Optional[InterfaceStatus] = None - """The current status of the interface deployment.""" - - updated_at: Optional[str] = None - """ISO 8601 formatted date-time indicating when the resource was updated.""" diff --git a/src/telnyx/types/virtual_cross_connect_create_response.py b/src/telnyx/types/virtual_cross_connect_create_response.py index 283ab4eb..31e99a85 100644 --- a/src/telnyx/types/virtual_cross_connect_create_response.py +++ b/src/telnyx/types/virtual_cross_connect_create_response.py @@ -1,12 +1,125 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional +from typing_extensions import Literal +from .record import Record from .._models import BaseModel -from .virtual_cross_connect_combined import VirtualCrossConnectCombined +from .network_interface import NetworkInterface -__all__ = ["VirtualCrossConnectCreateResponse"] +__all__ = ["VirtualCrossConnectCreateResponse", "Data", "DataRegion"] + + +class DataRegion(BaseModel): + code: Optional[str] = None + """Region code of the interface.""" + + name: Optional[str] = None + """Region name of the interface.""" + + record_type: Optional[str] = None + """Identifies the type of the resource.""" + + +class Data(Record, NetworkInterface): + region_code: str + """The region interface is deployed to.""" + + bandwidth_mbps: Optional[float] = None + """ + The desired throughput in Megabits per Second (Mbps) for your Virtual Cross + Connect.

The available bandwidths can be found using the + /virtual_cross_connect_regions endpoint. + """ + + bgp_asn: Optional[float] = None + """The Border Gateway Protocol (BGP) Autonomous System Number (ASN). + + If null, value will be assigned by Telnyx. + """ + + cloud_provider: Optional[Literal["aws", "azure", "gce"]] = None + """ + The Virtual Private Cloud with which you would like to establish a cross + connect. + """ + + cloud_provider_region: Optional[str] = None + """ + The region where your Virtual Private Cloud hosts are located.

The + available regions can be found using the /virtual_cross_connect_regions + endpoint. + """ + + primary_bgp_key: Optional[str] = None + """The authentication key for BGP peer configuration.""" + + primary_cloud_account_id: Optional[str] = None + """The identifier for your Virtual Private Cloud. + + The number will be different based upon your Cloud provider. + """ + + primary_cloud_ip: Optional[str] = None + """ + The IP address assigned for your side of the Virtual Cross + Connect.

If none is provided, one will be generated for + you.

This value can not be patched once the VXC has bene provisioned. + """ + + primary_enabled: Optional[bool] = None + """Indicates whether the primary circuit is enabled. + + Setting this to `false` will disable the circuit. + """ + + primary_routing_announcement: Optional[bool] = None + """Whether the primary BGP route is being announced.""" + + primary_telnyx_ip: Optional[str] = None + """ + The IP address assigned to the Telnyx side of the Virtual Cross + Connect.

If none is provided, one will be generated for + you.

This value should be null for GCE as Google will only inform you + of your assigned IP once the connection has been accepted. + """ + + region: Optional[DataRegion] = None + + secondary_bgp_key: Optional[str] = None + """The authentication key for BGP peer configuration.""" + + secondary_cloud_account_id: Optional[str] = None + """The identifier for your Virtual Private Cloud. + + The number will be different based upon your Cloud provider.

This + attribute is only necessary for GCE. + """ + + secondary_cloud_ip: Optional[str] = None + """ + The IP address assigned for your side of the Virtual Cross + Connect.

If none is provided, one will be generated for + you.

This value can not be patched once the VXC has bene provisioned. + """ + + secondary_enabled: Optional[bool] = None + """Indicates whether the secondary circuit is enabled. + + Setting this to `false` will disable the circuit. + """ + + secondary_routing_announcement: Optional[bool] = None + """Whether the secondary BGP route is being announced.""" + + secondary_telnyx_ip: Optional[str] = None + """ + The IP address assigned to the Telnyx side of the Virtual Cross + Connect.

If none is provided, one will be generated for + you.

This value should be null for GCE as Google will only inform you + of your assigned IP once the connection has been accepted. + """ class VirtualCrossConnectCreateResponse(BaseModel): - data: Optional[VirtualCrossConnectCombined] = None + data: Optional[Data] = None diff --git a/src/telnyx/types/virtual_cross_connect_delete_response.py b/src/telnyx/types/virtual_cross_connect_delete_response.py index 44177acf..3ade9098 100644 --- a/src/telnyx/types/virtual_cross_connect_delete_response.py +++ b/src/telnyx/types/virtual_cross_connect_delete_response.py @@ -1,12 +1,125 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional +from typing_extensions import Literal +from .record import Record from .._models import BaseModel -from .virtual_cross_connect_combined import VirtualCrossConnectCombined +from .network_interface import NetworkInterface -__all__ = ["VirtualCrossConnectDeleteResponse"] +__all__ = ["VirtualCrossConnectDeleteResponse", "Data", "DataRegion"] + + +class DataRegion(BaseModel): + code: Optional[str] = None + """Region code of the interface.""" + + name: Optional[str] = None + """Region name of the interface.""" + + record_type: Optional[str] = None + """Identifies the type of the resource.""" + + +class Data(Record, NetworkInterface): + region_code: str + """The region interface is deployed to.""" + + bandwidth_mbps: Optional[float] = None + """ + The desired throughput in Megabits per Second (Mbps) for your Virtual Cross + Connect.

The available bandwidths can be found using the + /virtual_cross_connect_regions endpoint. + """ + + bgp_asn: Optional[float] = None + """The Border Gateway Protocol (BGP) Autonomous System Number (ASN). + + If null, value will be assigned by Telnyx. + """ + + cloud_provider: Optional[Literal["aws", "azure", "gce"]] = None + """ + The Virtual Private Cloud with which you would like to establish a cross + connect. + """ + + cloud_provider_region: Optional[str] = None + """ + The region where your Virtual Private Cloud hosts are located.

The + available regions can be found using the /virtual_cross_connect_regions + endpoint. + """ + + primary_bgp_key: Optional[str] = None + """The authentication key for BGP peer configuration.""" + + primary_cloud_account_id: Optional[str] = None + """The identifier for your Virtual Private Cloud. + + The number will be different based upon your Cloud provider. + """ + + primary_cloud_ip: Optional[str] = None + """ + The IP address assigned for your side of the Virtual Cross + Connect.

If none is provided, one will be generated for + you.

This value can not be patched once the VXC has bene provisioned. + """ + + primary_enabled: Optional[bool] = None + """Indicates whether the primary circuit is enabled. + + Setting this to `false` will disable the circuit. + """ + + primary_routing_announcement: Optional[bool] = None + """Whether the primary BGP route is being announced.""" + + primary_telnyx_ip: Optional[str] = None + """ + The IP address assigned to the Telnyx side of the Virtual Cross + Connect.

If none is provided, one will be generated for + you.

This value should be null for GCE as Google will only inform you + of your assigned IP once the connection has been accepted. + """ + + region: Optional[DataRegion] = None + + secondary_bgp_key: Optional[str] = None + """The authentication key for BGP peer configuration.""" + + secondary_cloud_account_id: Optional[str] = None + """The identifier for your Virtual Private Cloud. + + The number will be different based upon your Cloud provider.

This + attribute is only necessary for GCE. + """ + + secondary_cloud_ip: Optional[str] = None + """ + The IP address assigned for your side of the Virtual Cross + Connect.

If none is provided, one will be generated for + you.

This value can not be patched once the VXC has bene provisioned. + """ + + secondary_enabled: Optional[bool] = None + """Indicates whether the secondary circuit is enabled. + + Setting this to `false` will disable the circuit. + """ + + secondary_routing_announcement: Optional[bool] = None + """Whether the secondary BGP route is being announced.""" + + secondary_telnyx_ip: Optional[str] = None + """ + The IP address assigned to the Telnyx side of the Virtual Cross + Connect.

If none is provided, one will be generated for + you.

This value should be null for GCE as Google will only inform you + of your assigned IP once the connection has been accepted. + """ class VirtualCrossConnectDeleteResponse(BaseModel): - data: Optional[VirtualCrossConnectCombined] = None + data: Optional[Data] = None diff --git a/src/telnyx/types/virtual_cross_connect_list_response.py b/src/telnyx/types/virtual_cross_connect_list_response.py new file mode 100644 index 00000000..68688e1b --- /dev/null +++ b/src/telnyx/types/virtual_cross_connect_list_response.py @@ -0,0 +1,121 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional +from typing_extensions import Literal + +from .record import Record +from .._models import BaseModel +from .network_interface import NetworkInterface + +__all__ = ["VirtualCrossConnectListResponse", "VirtualCrossConnectListResponseRegion"] + + +class VirtualCrossConnectListResponseRegion(BaseModel): + code: Optional[str] = None + """Region code of the interface.""" + + name: Optional[str] = None + """Region name of the interface.""" + + record_type: Optional[str] = None + """Identifies the type of the resource.""" + + +class VirtualCrossConnectListResponse(Record, NetworkInterface): + region_code: str + """The region interface is deployed to.""" + + bandwidth_mbps: Optional[float] = None + """ + The desired throughput in Megabits per Second (Mbps) for your Virtual Cross + Connect.

The available bandwidths can be found using the + /virtual_cross_connect_regions endpoint. + """ + + bgp_asn: Optional[float] = None + """The Border Gateway Protocol (BGP) Autonomous System Number (ASN). + + If null, value will be assigned by Telnyx. + """ + + cloud_provider: Optional[Literal["aws", "azure", "gce"]] = None + """ + The Virtual Private Cloud with which you would like to establish a cross + connect. + """ + + cloud_provider_region: Optional[str] = None + """ + The region where your Virtual Private Cloud hosts are located.

The + available regions can be found using the /virtual_cross_connect_regions + endpoint. + """ + + primary_bgp_key: Optional[str] = None + """The authentication key for BGP peer configuration.""" + + primary_cloud_account_id: Optional[str] = None + """The identifier for your Virtual Private Cloud. + + The number will be different based upon your Cloud provider. + """ + + primary_cloud_ip: Optional[str] = None + """ + The IP address assigned for your side of the Virtual Cross + Connect.

If none is provided, one will be generated for + you.

This value can not be patched once the VXC has bene provisioned. + """ + + primary_enabled: Optional[bool] = None + """Indicates whether the primary circuit is enabled. + + Setting this to `false` will disable the circuit. + """ + + primary_routing_announcement: Optional[bool] = None + """Whether the primary BGP route is being announced.""" + + primary_telnyx_ip: Optional[str] = None + """ + The IP address assigned to the Telnyx side of the Virtual Cross + Connect.

If none is provided, one will be generated for + you.

This value should be null for GCE as Google will only inform you + of your assigned IP once the connection has been accepted. + """ + + region: Optional[VirtualCrossConnectListResponseRegion] = None + + secondary_bgp_key: Optional[str] = None + """The authentication key for BGP peer configuration.""" + + secondary_cloud_account_id: Optional[str] = None + """The identifier for your Virtual Private Cloud. + + The number will be different based upon your Cloud provider.

This + attribute is only necessary for GCE. + """ + + secondary_cloud_ip: Optional[str] = None + """ + The IP address assigned for your side of the Virtual Cross + Connect.

If none is provided, one will be generated for + you.

This value can not be patched once the VXC has bene provisioned. + """ + + secondary_enabled: Optional[bool] = None + """Indicates whether the secondary circuit is enabled. + + Setting this to `false` will disable the circuit. + """ + + secondary_routing_announcement: Optional[bool] = None + """Whether the secondary BGP route is being announced.""" + + secondary_telnyx_ip: Optional[str] = None + """ + The IP address assigned to the Telnyx side of the Virtual Cross + Connect.

If none is provided, one will be generated for + you.

This value should be null for GCE as Google will only inform you + of your assigned IP once the connection has been accepted. + """ diff --git a/src/telnyx/types/virtual_cross_connect_retrieve_response.py b/src/telnyx/types/virtual_cross_connect_retrieve_response.py index 7a327afa..913747e3 100644 --- a/src/telnyx/types/virtual_cross_connect_retrieve_response.py +++ b/src/telnyx/types/virtual_cross_connect_retrieve_response.py @@ -1,12 +1,125 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional +from typing_extensions import Literal +from .record import Record from .._models import BaseModel -from .virtual_cross_connect_combined import VirtualCrossConnectCombined +from .network_interface import NetworkInterface -__all__ = ["VirtualCrossConnectRetrieveResponse"] +__all__ = ["VirtualCrossConnectRetrieveResponse", "Data", "DataRegion"] + + +class DataRegion(BaseModel): + code: Optional[str] = None + """Region code of the interface.""" + + name: Optional[str] = None + """Region name of the interface.""" + + record_type: Optional[str] = None + """Identifies the type of the resource.""" + + +class Data(Record, NetworkInterface): + region_code: str + """The region interface is deployed to.""" + + bandwidth_mbps: Optional[float] = None + """ + The desired throughput in Megabits per Second (Mbps) for your Virtual Cross + Connect.

The available bandwidths can be found using the + /virtual_cross_connect_regions endpoint. + """ + + bgp_asn: Optional[float] = None + """The Border Gateway Protocol (BGP) Autonomous System Number (ASN). + + If null, value will be assigned by Telnyx. + """ + + cloud_provider: Optional[Literal["aws", "azure", "gce"]] = None + """ + The Virtual Private Cloud with which you would like to establish a cross + connect. + """ + + cloud_provider_region: Optional[str] = None + """ + The region where your Virtual Private Cloud hosts are located.

The + available regions can be found using the /virtual_cross_connect_regions + endpoint. + """ + + primary_bgp_key: Optional[str] = None + """The authentication key for BGP peer configuration.""" + + primary_cloud_account_id: Optional[str] = None + """The identifier for your Virtual Private Cloud. + + The number will be different based upon your Cloud provider. + """ + + primary_cloud_ip: Optional[str] = None + """ + The IP address assigned for your side of the Virtual Cross + Connect.

If none is provided, one will be generated for + you.

This value can not be patched once the VXC has bene provisioned. + """ + + primary_enabled: Optional[bool] = None + """Indicates whether the primary circuit is enabled. + + Setting this to `false` will disable the circuit. + """ + + primary_routing_announcement: Optional[bool] = None + """Whether the primary BGP route is being announced.""" + + primary_telnyx_ip: Optional[str] = None + """ + The IP address assigned to the Telnyx side of the Virtual Cross + Connect.

If none is provided, one will be generated for + you.

This value should be null for GCE as Google will only inform you + of your assigned IP once the connection has been accepted. + """ + + region: Optional[DataRegion] = None + + secondary_bgp_key: Optional[str] = None + """The authentication key for BGP peer configuration.""" + + secondary_cloud_account_id: Optional[str] = None + """The identifier for your Virtual Private Cloud. + + The number will be different based upon your Cloud provider.

This + attribute is only necessary for GCE. + """ + + secondary_cloud_ip: Optional[str] = None + """ + The IP address assigned for your side of the Virtual Cross + Connect.

If none is provided, one will be generated for + you.

This value can not be patched once the VXC has bene provisioned. + """ + + secondary_enabled: Optional[bool] = None + """Indicates whether the secondary circuit is enabled. + + Setting this to `false` will disable the circuit. + """ + + secondary_routing_announcement: Optional[bool] = None + """Whether the secondary BGP route is being announced.""" + + secondary_telnyx_ip: Optional[str] = None + """ + The IP address assigned to the Telnyx side of the Virtual Cross + Connect.

If none is provided, one will be generated for + you.

This value should be null for GCE as Google will only inform you + of your assigned IP once the connection has been accepted. + """ class VirtualCrossConnectRetrieveResponse(BaseModel): - data: Optional[VirtualCrossConnectCombined] = None + data: Optional[Data] = None diff --git a/src/telnyx/types/virtual_cross_connect_update_response.py b/src/telnyx/types/virtual_cross_connect_update_response.py index 63532bf5..de0085e4 100644 --- a/src/telnyx/types/virtual_cross_connect_update_response.py +++ b/src/telnyx/types/virtual_cross_connect_update_response.py @@ -1,12 +1,125 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. from typing import Optional +from typing_extensions import Literal +from .record import Record from .._models import BaseModel -from .virtual_cross_connect_combined import VirtualCrossConnectCombined +from .network_interface import NetworkInterface -__all__ = ["VirtualCrossConnectUpdateResponse"] +__all__ = ["VirtualCrossConnectUpdateResponse", "Data", "DataRegion"] + + +class DataRegion(BaseModel): + code: Optional[str] = None + """Region code of the interface.""" + + name: Optional[str] = None + """Region name of the interface.""" + + record_type: Optional[str] = None + """Identifies the type of the resource.""" + + +class Data(Record, NetworkInterface): + region_code: str + """The region interface is deployed to.""" + + bandwidth_mbps: Optional[float] = None + """ + The desired throughput in Megabits per Second (Mbps) for your Virtual Cross + Connect.

The available bandwidths can be found using the + /virtual_cross_connect_regions endpoint. + """ + + bgp_asn: Optional[float] = None + """The Border Gateway Protocol (BGP) Autonomous System Number (ASN). + + If null, value will be assigned by Telnyx. + """ + + cloud_provider: Optional[Literal["aws", "azure", "gce"]] = None + """ + The Virtual Private Cloud with which you would like to establish a cross + connect. + """ + + cloud_provider_region: Optional[str] = None + """ + The region where your Virtual Private Cloud hosts are located.

The + available regions can be found using the /virtual_cross_connect_regions + endpoint. + """ + + primary_bgp_key: Optional[str] = None + """The authentication key for BGP peer configuration.""" + + primary_cloud_account_id: Optional[str] = None + """The identifier for your Virtual Private Cloud. + + The number will be different based upon your Cloud provider. + """ + + primary_cloud_ip: Optional[str] = None + """ + The IP address assigned for your side of the Virtual Cross + Connect.

If none is provided, one will be generated for + you.

This value can not be patched once the VXC has bene provisioned. + """ + + primary_enabled: Optional[bool] = None + """Indicates whether the primary circuit is enabled. + + Setting this to `false` will disable the circuit. + """ + + primary_routing_announcement: Optional[bool] = None + """Whether the primary BGP route is being announced.""" + + primary_telnyx_ip: Optional[str] = None + """ + The IP address assigned to the Telnyx side of the Virtual Cross + Connect.

If none is provided, one will be generated for + you.

This value should be null for GCE as Google will only inform you + of your assigned IP once the connection has been accepted. + """ + + region: Optional[DataRegion] = None + + secondary_bgp_key: Optional[str] = None + """The authentication key for BGP peer configuration.""" + + secondary_cloud_account_id: Optional[str] = None + """The identifier for your Virtual Private Cloud. + + The number will be different based upon your Cloud provider.

This + attribute is only necessary for GCE. + """ + + secondary_cloud_ip: Optional[str] = None + """ + The IP address assigned for your side of the Virtual Cross + Connect.

If none is provided, one will be generated for + you.

This value can not be patched once the VXC has bene provisioned. + """ + + secondary_enabled: Optional[bool] = None + """Indicates whether the secondary circuit is enabled. + + Setting this to `false` will disable the circuit. + """ + + secondary_routing_announcement: Optional[bool] = None + """Whether the secondary BGP route is being announced.""" + + secondary_telnyx_ip: Optional[str] = None + """ + The IP address assigned to the Telnyx side of the Virtual Cross + Connect.

If none is provided, one will be generated for + you.

This value should be null for GCE as Google will only inform you + of your assigned IP once the connection has been accepted. + """ class VirtualCrossConnectUpdateResponse(BaseModel): - data: Optional[VirtualCrossConnectCombined] = None + data: Optional[Data] = None diff --git a/src/telnyx/types/wireguard_interface_create_response.py b/src/telnyx/types/wireguard_interface_create_response.py index 73f8bd7f..458ea75d 100644 --- a/src/telnyx/types/wireguard_interface_create_response.py +++ b/src/telnyx/types/wireguard_interface_create_response.py @@ -2,11 +2,39 @@ from typing import Optional +from .record import Record from .._models import BaseModel -from .wireguard_interface_read import WireguardInterfaceRead +from .network_interface import NetworkInterface -__all__ = ["WireguardInterfaceCreateResponse"] +__all__ = ["WireguardInterfaceCreateResponse", "Data", "DataRegion"] + + +class DataRegion(BaseModel): + code: Optional[str] = None + """Region code of the interface.""" + + name: Optional[str] = None + """Region name of the interface.""" + + record_type: Optional[str] = None + """Identifies the type of the resource.""" + + +class Data(Record, NetworkInterface): + enable_sip_trunking: Optional[bool] = None + """Enable SIP traffic forwarding over VPN interface.""" + + endpoint: Optional[str] = None + """The Telnyx WireGuard peers `Peer.endpoint` value.""" + + public_key: Optional[str] = None + """The Telnyx WireGuard peers `Peer.PublicKey`.""" + + region: Optional[DataRegion] = None + + region_code: Optional[str] = None + """The region interface is deployed to.""" class WireguardInterfaceCreateResponse(BaseModel): - data: Optional[WireguardInterfaceRead] = None + data: Optional[Data] = None diff --git a/src/telnyx/types/wireguard_interface_delete_response.py b/src/telnyx/types/wireguard_interface_delete_response.py index d6638859..519a9b74 100644 --- a/src/telnyx/types/wireguard_interface_delete_response.py +++ b/src/telnyx/types/wireguard_interface_delete_response.py @@ -2,11 +2,39 @@ from typing import Optional +from .record import Record from .._models import BaseModel -from .wireguard_interface_read import WireguardInterfaceRead +from .network_interface import NetworkInterface -__all__ = ["WireguardInterfaceDeleteResponse"] +__all__ = ["WireguardInterfaceDeleteResponse", "Data", "DataRegion"] + + +class DataRegion(BaseModel): + code: Optional[str] = None + """Region code of the interface.""" + + name: Optional[str] = None + """Region name of the interface.""" + + record_type: Optional[str] = None + """Identifies the type of the resource.""" + + +class Data(Record, NetworkInterface): + enable_sip_trunking: Optional[bool] = None + """Enable SIP traffic forwarding over VPN interface.""" + + endpoint: Optional[str] = None + """The Telnyx WireGuard peers `Peer.endpoint` value.""" + + public_key: Optional[str] = None + """The Telnyx WireGuard peers `Peer.PublicKey`.""" + + region: Optional[DataRegion] = None + + region_code: Optional[str] = None + """The region interface is deployed to.""" class WireguardInterfaceDeleteResponse(BaseModel): - data: Optional[WireguardInterfaceRead] = None + data: Optional[Data] = None diff --git a/src/telnyx/types/wireguard_interface_list_response.py b/src/telnyx/types/wireguard_interface_list_response.py new file mode 100644 index 00000000..77fb1d5d --- /dev/null +++ b/src/telnyx/types/wireguard_interface_list_response.py @@ -0,0 +1,36 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional + +from .record import Record +from .._models import BaseModel +from .network_interface import NetworkInterface + +__all__ = ["WireguardInterfaceListResponse", "WireguardInterfaceListResponseRegion"] + + +class WireguardInterfaceListResponseRegion(BaseModel): + code: Optional[str] = None + """Region code of the interface.""" + + name: Optional[str] = None + """Region name of the interface.""" + + record_type: Optional[str] = None + """Identifies the type of the resource.""" + + +class WireguardInterfaceListResponse(Record, NetworkInterface): + enable_sip_trunking: Optional[bool] = None + """Enable SIP traffic forwarding over VPN interface.""" + + endpoint: Optional[str] = None + """The Telnyx WireGuard peers `Peer.endpoint` value.""" + + public_key: Optional[str] = None + """The Telnyx WireGuard peers `Peer.PublicKey`.""" + + region: Optional[WireguardInterfaceListResponseRegion] = None + + region_code: Optional[str] = None + """The region interface is deployed to.""" diff --git a/src/telnyx/types/wireguard_interface_read.py b/src/telnyx/types/wireguard_interface_read.py deleted file mode 100644 index 424ffc20..00000000 --- a/src/telnyx/types/wireguard_interface_read.py +++ /dev/null @@ -1,56 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import Optional - -from .._models import BaseModel -from .interface_status import InterfaceStatus - -__all__ = ["WireguardInterfaceRead", "Region"] - - -class Region(BaseModel): - code: Optional[str] = None - """Region code of the interface.""" - - name: Optional[str] = None - """Region name of the interface.""" - - record_type: Optional[str] = None - """Identifies the type of the resource.""" - - -class WireguardInterfaceRead(BaseModel): - id: Optional[str] = None - """Identifies the resource.""" - - created_at: Optional[str] = None - """ISO 8601 formatted date-time indicating when the resource was created.""" - - enable_sip_trunking: Optional[bool] = None - """Enable SIP traffic forwarding over VPN interface.""" - - endpoint: Optional[str] = None - """The Telnyx WireGuard peers `Peer.endpoint` value.""" - - name: Optional[str] = None - """A user specified name for the interface.""" - - network_id: Optional[str] = None - """The id of the network associated with the interface.""" - - public_key: Optional[str] = None - """The Telnyx WireGuard peers `Peer.PublicKey`.""" - - record_type: Optional[str] = None - """Identifies the type of the resource.""" - - region: Optional[Region] = None - - region_code: Optional[str] = None - """The region interface is deployed to.""" - - status: Optional[InterfaceStatus] = None - """The current status of the interface deployment.""" - - updated_at: Optional[str] = None - """ISO 8601 formatted date-time indicating when the resource was updated.""" diff --git a/src/telnyx/types/wireguard_interface_retrieve_response.py b/src/telnyx/types/wireguard_interface_retrieve_response.py index d4dced88..9816c28f 100644 --- a/src/telnyx/types/wireguard_interface_retrieve_response.py +++ b/src/telnyx/types/wireguard_interface_retrieve_response.py @@ -2,11 +2,39 @@ from typing import Optional +from .record import Record from .._models import BaseModel -from .wireguard_interface_read import WireguardInterfaceRead +from .network_interface import NetworkInterface -__all__ = ["WireguardInterfaceRetrieveResponse"] +__all__ = ["WireguardInterfaceRetrieveResponse", "Data", "DataRegion"] + + +class DataRegion(BaseModel): + code: Optional[str] = None + """Region code of the interface.""" + + name: Optional[str] = None + """Region name of the interface.""" + + record_type: Optional[str] = None + """Identifies the type of the resource.""" + + +class Data(Record, NetworkInterface): + enable_sip_trunking: Optional[bool] = None + """Enable SIP traffic forwarding over VPN interface.""" + + endpoint: Optional[str] = None + """The Telnyx WireGuard peers `Peer.endpoint` value.""" + + public_key: Optional[str] = None + """The Telnyx WireGuard peers `Peer.PublicKey`.""" + + region: Optional[DataRegion] = None + + region_code: Optional[str] = None + """The region interface is deployed to.""" class WireguardInterfaceRetrieveResponse(BaseModel): - data: Optional[WireguardInterfaceRead] = None + data: Optional[Data] = None diff --git a/tests/api_resources/dir/__init__.py b/tests/api_resources/dir/__init__.py new file mode 100644 index 00000000..fd8019a9 --- /dev/null +++ b/tests/api_resources/dir/__init__.py @@ -0,0 +1 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. diff --git a/tests/api_resources/dir/test_comments.py b/tests/api_resources/dir/test_comments.py new file mode 100644 index 00000000..c66d908e --- /dev/null +++ b/tests/api_resources/dir/test_comments.py @@ -0,0 +1,243 @@ +# 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.dir import CommentListResponse, CommentCreateResponse +from telnyx.pagination import SyncDefaultFlatPagination, AsyncDefaultFlatPagination + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestComments: + 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: + comment = client.dir.comments.create( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + content="Re-uploaded the certificate. New document_id: 89450109-ee35-411c-b5bb-14f1d806fca2.", + ) + assert_matches_type(CommentCreateResponse, comment, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_create_with_all_params(self, client: Telnyx) -> None: + comment = client.dir.comments.create( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + content="Re-uploaded the certificate. New document_id: 89450109-ee35-411c-b5bb-14f1d806fca2.", + parent_comment_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert_matches_type(CommentCreateResponse, comment, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_create(self, client: Telnyx) -> None: + response = client.dir.comments.with_raw_response.create( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + content="Re-uploaded the certificate. New document_id: 89450109-ee35-411c-b5bb-14f1d806fca2.", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + comment = response.parse() + assert_matches_type(CommentCreateResponse, comment, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_create(self, client: Telnyx) -> None: + with client.dir.comments.with_streaming_response.create( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + content="Re-uploaded the certificate. New document_id: 89450109-ee35-411c-b5bb-14f1d806fca2.", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + comment = response.parse() + assert_matches_type(CommentCreateResponse, comment, 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 `dir_id` but received ''"): + client.dir.comments.with_raw_response.create( + dir_id="", + content="Re-uploaded the certificate. New document_id: 89450109-ee35-411c-b5bb-14f1d806fca2.", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_list(self, client: Telnyx) -> None: + comment = client.dir.comments.list( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + ) + assert_matches_type(SyncDefaultFlatPagination[CommentListResponse], comment, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_list_with_all_params(self, client: Telnyx) -> None: + comment = client.dir.comments.list( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + comment_type="vetting_comment", + page_number=1, + page_size=20, + ) + assert_matches_type(SyncDefaultFlatPagination[CommentListResponse], comment, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_list(self, client: Telnyx) -> None: + response = client.dir.comments.with_raw_response.list( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + comment = response.parse() + assert_matches_type(SyncDefaultFlatPagination[CommentListResponse], comment, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_list(self, client: Telnyx) -> None: + with client.dir.comments.with_streaming_response.list( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + comment = response.parse() + assert_matches_type(SyncDefaultFlatPagination[CommentListResponse], comment, 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 `dir_id` but received ''"): + client.dir.comments.with_raw_response.list( + dir_id="", + ) + + +class TestAsyncComments: + 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: + comment = await async_client.dir.comments.create( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + content="Re-uploaded the certificate. New document_id: 89450109-ee35-411c-b5bb-14f1d806fca2.", + ) + assert_matches_type(CommentCreateResponse, comment, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_create_with_all_params(self, async_client: AsyncTelnyx) -> None: + comment = await async_client.dir.comments.create( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + content="Re-uploaded the certificate. New document_id: 89450109-ee35-411c-b5bb-14f1d806fca2.", + parent_comment_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert_matches_type(CommentCreateResponse, comment, 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.dir.comments.with_raw_response.create( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + content="Re-uploaded the certificate. New document_id: 89450109-ee35-411c-b5bb-14f1d806fca2.", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + comment = await response.parse() + assert_matches_type(CommentCreateResponse, comment, 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.dir.comments.with_streaming_response.create( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + content="Re-uploaded the certificate. New document_id: 89450109-ee35-411c-b5bb-14f1d806fca2.", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + comment = await response.parse() + assert_matches_type(CommentCreateResponse, comment, 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 `dir_id` but received ''"): + await async_client.dir.comments.with_raw_response.create( + dir_id="", + content="Re-uploaded the certificate. New document_id: 89450109-ee35-411c-b5bb-14f1d806fca2.", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_list(self, async_client: AsyncTelnyx) -> None: + comment = await async_client.dir.comments.list( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + ) + assert_matches_type(AsyncDefaultFlatPagination[CommentListResponse], comment, 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: + comment = await async_client.dir.comments.list( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + comment_type="vetting_comment", + page_number=1, + page_size=20, + ) + assert_matches_type(AsyncDefaultFlatPagination[CommentListResponse], comment, 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.dir.comments.with_raw_response.list( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + comment = await response.parse() + assert_matches_type(AsyncDefaultFlatPagination[CommentListResponse], comment, 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.dir.comments.with_streaming_response.list( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + comment = await response.parse() + assert_matches_type(AsyncDefaultFlatPagination[CommentListResponse], comment, 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 `dir_id` but received ''"): + await async_client.dir.comments.with_raw_response.list( + dir_id="", + ) diff --git a/tests/api_resources/dir/test_phone_number_batches.py b/tests/api_resources/dir/test_phone_number_batches.py new file mode 100644 index 00000000..10c3e3ce --- /dev/null +++ b/tests/api_resources/dir/test_phone_number_batches.py @@ -0,0 +1,254 @@ +# 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.dir import ( + PhoneNumberBatchListResponse, + PhoneNumberBatchRetrieveResponse, +) +from telnyx.pagination import SyncDefaultFlatPagination, AsyncDefaultFlatPagination + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestPhoneNumberBatches: + 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(self, client: Telnyx) -> None: + phone_number_batch = client.dir.phone_number_batches.retrieve( + batch_id="0a4b1f5e-2f12-4c0c-9a98-9b3a7d8b8e62", + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + ) + assert_matches_type(PhoneNumberBatchRetrieveResponse, phone_number_batch, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_retrieve(self, client: Telnyx) -> None: + response = client.dir.phone_number_batches.with_raw_response.retrieve( + batch_id="0a4b1f5e-2f12-4c0c-9a98-9b3a7d8b8e62", + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + phone_number_batch = response.parse() + assert_matches_type(PhoneNumberBatchRetrieveResponse, phone_number_batch, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_retrieve(self, client: Telnyx) -> None: + with client.dir.phone_number_batches.with_streaming_response.retrieve( + batch_id="0a4b1f5e-2f12-4c0c-9a98-9b3a7d8b8e62", + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + phone_number_batch = response.parse() + assert_matches_type(PhoneNumberBatchRetrieveResponse, phone_number_batch, 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(self, client: Telnyx) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `dir_id` but received ''"): + client.dir.phone_number_batches.with_raw_response.retrieve( + batch_id="0a4b1f5e-2f12-4c0c-9a98-9b3a7d8b8e62", + dir_id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `batch_id` but received ''"): + client.dir.phone_number_batches.with_raw_response.retrieve( + batch_id="", + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_list(self, client: Telnyx) -> None: + phone_number_batch = client.dir.phone_number_batches.list( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + ) + assert_matches_type( + SyncDefaultFlatPagination[PhoneNumberBatchListResponse], phone_number_batch, path=["response"] + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_list_with_all_params(self, client: Telnyx) -> None: + phone_number_batch = client.dir.phone_number_batches.list( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + filter_status="submitted", + page_number=1, + page_size=20, + ) + assert_matches_type( + SyncDefaultFlatPagination[PhoneNumberBatchListResponse], phone_number_batch, path=["response"] + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_list(self, client: Telnyx) -> None: + response = client.dir.phone_number_batches.with_raw_response.list( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + phone_number_batch = response.parse() + assert_matches_type( + SyncDefaultFlatPagination[PhoneNumberBatchListResponse], phone_number_batch, path=["response"] + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_list(self, client: Telnyx) -> None: + with client.dir.phone_number_batches.with_streaming_response.list( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + phone_number_batch = response.parse() + assert_matches_type( + SyncDefaultFlatPagination[PhoneNumberBatchListResponse], phone_number_batch, 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 `dir_id` but received ''"): + client.dir.phone_number_batches.with_raw_response.list( + dir_id="", + ) + + +class TestAsyncPhoneNumberBatches: + 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(self, async_client: AsyncTelnyx) -> None: + phone_number_batch = await async_client.dir.phone_number_batches.retrieve( + batch_id="0a4b1f5e-2f12-4c0c-9a98-9b3a7d8b8e62", + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + ) + assert_matches_type(PhoneNumberBatchRetrieveResponse, phone_number_batch, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_retrieve(self, async_client: AsyncTelnyx) -> None: + response = await async_client.dir.phone_number_batches.with_raw_response.retrieve( + batch_id="0a4b1f5e-2f12-4c0c-9a98-9b3a7d8b8e62", + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + phone_number_batch = await response.parse() + assert_matches_type(PhoneNumberBatchRetrieveResponse, phone_number_batch, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_retrieve(self, async_client: AsyncTelnyx) -> None: + async with async_client.dir.phone_number_batches.with_streaming_response.retrieve( + batch_id="0a4b1f5e-2f12-4c0c-9a98-9b3a7d8b8e62", + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + phone_number_batch = await response.parse() + assert_matches_type(PhoneNumberBatchRetrieveResponse, phone_number_batch, 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(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.phone_number_batches.with_raw_response.retrieve( + batch_id="0a4b1f5e-2f12-4c0c-9a98-9b3a7d8b8e62", + dir_id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `batch_id` but received ''"): + await async_client.dir.phone_number_batches.with_raw_response.retrieve( + batch_id="", + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_list(self, async_client: AsyncTelnyx) -> None: + phone_number_batch = await async_client.dir.phone_number_batches.list( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + ) + assert_matches_type( + AsyncDefaultFlatPagination[PhoneNumberBatchListResponse], phone_number_batch, 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: + phone_number_batch = await async_client.dir.phone_number_batches.list( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + filter_status="submitted", + page_number=1, + page_size=20, + ) + assert_matches_type( + AsyncDefaultFlatPagination[PhoneNumberBatchListResponse], phone_number_batch, 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.dir.phone_number_batches.with_raw_response.list( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + phone_number_batch = await response.parse() + assert_matches_type( + AsyncDefaultFlatPagination[PhoneNumberBatchListResponse], phone_number_batch, 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.dir.phone_number_batches.with_streaming_response.list( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + phone_number_batch = await response.parse() + assert_matches_type( + AsyncDefaultFlatPagination[PhoneNumberBatchListResponse], phone_number_batch, 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 `dir_id` but received ''"): + await async_client.dir.phone_number_batches.with_raw_response.list( + dir_id="", + ) diff --git a/tests/api_resources/dir/test_phone_numbers.py b/tests/api_resources/dir/test_phone_numbers.py new file mode 100644 index 00000000..9a384f12 --- /dev/null +++ b/tests/api_resources/dir/test_phone_numbers.py @@ -0,0 +1,367 @@ +# 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.dir import ( + PhoneNumberAddResponse, + PhoneNumberListResponse, + PhoneNumberRemoveResponse, +) +from telnyx.pagination import SyncDefaultFlatPagination, AsyncDefaultFlatPagination + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestPhoneNumbers: + 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: + phone_number = client.dir.phone_numbers.list( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + ) + assert_matches_type(SyncDefaultFlatPagination[PhoneNumberListResponse], phone_number, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_list_with_all_params(self, client: Telnyx) -> None: + phone_number = client.dir.phone_numbers.list( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + page_number=1, + page_size=20, + status="submitted", + ) + assert_matches_type(SyncDefaultFlatPagination[PhoneNumberListResponse], phone_number, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_list(self, client: Telnyx) -> None: + response = client.dir.phone_numbers.with_raw_response.list( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + phone_number = response.parse() + assert_matches_type(SyncDefaultFlatPagination[PhoneNumberListResponse], phone_number, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_list(self, client: Telnyx) -> None: + with client.dir.phone_numbers.with_streaming_response.list( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + phone_number = response.parse() + assert_matches_type(SyncDefaultFlatPagination[PhoneNumberListResponse], phone_number, 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 `dir_id` but received ''"): + client.dir.phone_numbers.with_raw_response.list( + dir_id="", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_add(self, client: Telnyx) -> None: + phone_number = client.dir.phone_numbers.add( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + documents=[ + { + "document_id": "2a7e8337-e803-4057-a4ae-26c40eb0bc6c", + "document_type": "letter_of_authorization", + } + ], + phone_numbers=["+19493253498", "+12134445566"], + ) + assert_matches_type(PhoneNumberAddResponse, phone_number, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_add(self, client: Telnyx) -> None: + response = client.dir.phone_numbers.with_raw_response.add( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + documents=[ + { + "document_id": "2a7e8337-e803-4057-a4ae-26c40eb0bc6c", + "document_type": "letter_of_authorization", + } + ], + phone_numbers=["+19493253498", "+12134445566"], + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + phone_number = response.parse() + assert_matches_type(PhoneNumberAddResponse, phone_number, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_add(self, client: Telnyx) -> None: + with client.dir.phone_numbers.with_streaming_response.add( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + documents=[ + { + "document_id": "2a7e8337-e803-4057-a4ae-26c40eb0bc6c", + "document_type": "letter_of_authorization", + } + ], + phone_numbers=["+19493253498", "+12134445566"], + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + phone_number = response.parse() + assert_matches_type(PhoneNumberAddResponse, phone_number, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_path_params_add(self, client: Telnyx) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `dir_id` but received ''"): + client.dir.phone_numbers.with_raw_response.add( + dir_id="", + documents=[ + { + "document_id": "2a7e8337-e803-4057-a4ae-26c40eb0bc6c", + "document_type": "letter_of_authorization", + } + ], + phone_numbers=["+19493253498", "+12134445566"], + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_remove(self, client: Telnyx) -> None: + phone_number = client.dir.phone_numbers.remove( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + phone_numbers=["+19493253498"], + ) + assert_matches_type(PhoneNumberRemoveResponse, phone_number, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_remove(self, client: Telnyx) -> None: + response = client.dir.phone_numbers.with_raw_response.remove( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + phone_numbers=["+19493253498"], + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + phone_number = response.parse() + assert_matches_type(PhoneNumberRemoveResponse, phone_number, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_remove(self, client: Telnyx) -> None: + with client.dir.phone_numbers.with_streaming_response.remove( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + phone_numbers=["+19493253498"], + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + phone_number = response.parse() + assert_matches_type(PhoneNumberRemoveResponse, phone_number, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_path_params_remove(self, client: Telnyx) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `dir_id` but received ''"): + client.dir.phone_numbers.with_raw_response.remove( + dir_id="", + phone_numbers=["+19493253498"], + ) + + +class TestAsyncPhoneNumbers: + 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: + phone_number = await async_client.dir.phone_numbers.list( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + ) + assert_matches_type(AsyncDefaultFlatPagination[PhoneNumberListResponse], phone_number, 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: + phone_number = await async_client.dir.phone_numbers.list( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + page_number=1, + page_size=20, + status="submitted", + ) + assert_matches_type(AsyncDefaultFlatPagination[PhoneNumberListResponse], phone_number, 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.dir.phone_numbers.with_raw_response.list( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + phone_number = await response.parse() + assert_matches_type(AsyncDefaultFlatPagination[PhoneNumberListResponse], phone_number, 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.dir.phone_numbers.with_streaming_response.list( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + phone_number = await response.parse() + assert_matches_type(AsyncDefaultFlatPagination[PhoneNumberListResponse], phone_number, 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 `dir_id` but received ''"): + await async_client.dir.phone_numbers.with_raw_response.list( + dir_id="", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_add(self, async_client: AsyncTelnyx) -> None: + phone_number = await async_client.dir.phone_numbers.add( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + documents=[ + { + "document_id": "2a7e8337-e803-4057-a4ae-26c40eb0bc6c", + "document_type": "letter_of_authorization", + } + ], + phone_numbers=["+19493253498", "+12134445566"], + ) + assert_matches_type(PhoneNumberAddResponse, phone_number, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_add(self, async_client: AsyncTelnyx) -> None: + response = await async_client.dir.phone_numbers.with_raw_response.add( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + documents=[ + { + "document_id": "2a7e8337-e803-4057-a4ae-26c40eb0bc6c", + "document_type": "letter_of_authorization", + } + ], + phone_numbers=["+19493253498", "+12134445566"], + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + phone_number = await response.parse() + assert_matches_type(PhoneNumberAddResponse, phone_number, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_add(self, async_client: AsyncTelnyx) -> None: + async with async_client.dir.phone_numbers.with_streaming_response.add( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + documents=[ + { + "document_id": "2a7e8337-e803-4057-a4ae-26c40eb0bc6c", + "document_type": "letter_of_authorization", + } + ], + phone_numbers=["+19493253498", "+12134445566"], + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + phone_number = await response.parse() + assert_matches_type(PhoneNumberAddResponse, phone_number, 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_add(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.phone_numbers.with_raw_response.add( + dir_id="", + documents=[ + { + "document_id": "2a7e8337-e803-4057-a4ae-26c40eb0bc6c", + "document_type": "letter_of_authorization", + } + ], + phone_numbers=["+19493253498", "+12134445566"], + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_remove(self, async_client: AsyncTelnyx) -> None: + phone_number = await async_client.dir.phone_numbers.remove( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + phone_numbers=["+19493253498"], + ) + assert_matches_type(PhoneNumberRemoveResponse, phone_number, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_remove(self, async_client: AsyncTelnyx) -> None: + response = await async_client.dir.phone_numbers.with_raw_response.remove( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + phone_numbers=["+19493253498"], + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + phone_number = await response.parse() + assert_matches_type(PhoneNumberRemoveResponse, phone_number, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_remove(self, async_client: AsyncTelnyx) -> None: + async with async_client.dir.phone_numbers.with_streaming_response.remove( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + phone_numbers=["+19493253498"], + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + phone_number = await response.parse() + assert_matches_type(PhoneNumberRemoveResponse, phone_number, 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_remove(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.phone_numbers.with_raw_response.remove( + dir_id="", + phone_numbers=["+19493253498"], + ) diff --git a/tests/api_resources/enterprises/reputation/test_loa.py b/tests/api_resources/enterprises/reputation/test_loa.py new file mode 100644 index 00000000..2382dfc2 --- /dev/null +++ b/tests/api_resources/enterprises/reputation/test_loa.py @@ -0,0 +1,300 @@ +# 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 httpx +import pytest +from respx import MockRouter + +from telnyx import Telnyx, AsyncTelnyx +from tests.utils import assert_matches_type +from telnyx._response import ( + BinaryAPIResponse, + AsyncBinaryAPIResponse, + StreamedBinaryAPIResponse, + AsyncStreamedBinaryAPIResponse, +) +from telnyx.types.enterprises.reputation import LoaUpdateResponse + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestLoa: + 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_update(self, client: Telnyx) -> None: + loa = client.enterprises.reputation.loa.update( + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + loa_document_id="2a7e8337-e803-4057-a4ae-26c40eb0bc6c", + ) + assert_matches_type(LoaUpdateResponse, loa, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_update(self, client: Telnyx) -> None: + response = client.enterprises.reputation.loa.with_raw_response.update( + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + loa_document_id="2a7e8337-e803-4057-a4ae-26c40eb0bc6c", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + loa = response.parse() + assert_matches_type(LoaUpdateResponse, loa, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_update(self, client: Telnyx) -> None: + with client.enterprises.reputation.loa.with_streaming_response.update( + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + loa_document_id="2a7e8337-e803-4057-a4ae-26c40eb0bc6c", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + loa = response.parse() + assert_matches_type(LoaUpdateResponse, loa, 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(self, client: Telnyx) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `enterprise_id` but received ''"): + client.enterprises.reputation.loa.with_raw_response.update( + enterprise_id="", + loa_document_id="2a7e8337-e803-4057-a4ae-26c40eb0bc6c", + ) + + @parametrize + @pytest.mark.respx(base_url=base_url) + def test_method_render(self, client: Telnyx, respx_mock: MockRouter) -> None: + respx_mock.post("/enterprises/4a6192a4-573d-446d-b3ce-aff9117272a6/reputation/loa").mock( + return_value=httpx.Response(200, json={"foo": "bar"}) + ) + loa = client.enterprises.reputation.loa.render( + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + ) + assert loa.is_closed + assert loa.json() == {"foo": "bar"} + assert cast(Any, loa.is_closed) is True + assert isinstance(loa, BinaryAPIResponse) + + @parametrize + @pytest.mark.respx(base_url=base_url) + def test_method_render_with_all_params(self, client: Telnyx, respx_mock: MockRouter) -> None: + respx_mock.post("/enterprises/4a6192a4-573d-446d-b3ce-aff9117272a6/reputation/loa").mock( + return_value=httpx.Response(200, json={"foo": "bar"}) + ) + loa = client.enterprises.reputation.loa.render( + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + agent={ + "administrative_area": "administrative_area", + "city": "city", + "contact_email": "dev@stainless.com", + "contact_name": "contact_name", + "contact_phone": "+13125550000", + "contact_title": "contact_title", + "country": "US", + "legal_name": "legal_name", + "postal_code": "postal_code", + "street_address": "street_address", + "dba": "dba", + "extended_address": "extended_address", + }, + signature={ + "image_base64": "image_base64", + "signer_name": "signer_name", + }, + ) + assert loa.is_closed + assert loa.json() == {"foo": "bar"} + assert cast(Any, loa.is_closed) is True + assert isinstance(loa, BinaryAPIResponse) + + @parametrize + @pytest.mark.respx(base_url=base_url) + def test_raw_response_render(self, client: Telnyx, respx_mock: MockRouter) -> None: + respx_mock.post("/enterprises/4a6192a4-573d-446d-b3ce-aff9117272a6/reputation/loa").mock( + return_value=httpx.Response(200, json={"foo": "bar"}) + ) + + loa = client.enterprises.reputation.loa.with_raw_response.render( + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + ) + + assert loa.is_closed is True + assert loa.http_request.headers.get("X-Stainless-Lang") == "python" + assert loa.json() == {"foo": "bar"} + assert isinstance(loa, BinaryAPIResponse) + + @parametrize + @pytest.mark.respx(base_url=base_url) + def test_streaming_response_render(self, client: Telnyx, respx_mock: MockRouter) -> None: + respx_mock.post("/enterprises/4a6192a4-573d-446d-b3ce-aff9117272a6/reputation/loa").mock( + return_value=httpx.Response(200, json={"foo": "bar"}) + ) + with client.enterprises.reputation.loa.with_streaming_response.render( + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + ) as loa: + assert not loa.is_closed + assert loa.http_request.headers.get("X-Stainless-Lang") == "python" + + assert loa.json() == {"foo": "bar"} + assert cast(Any, loa.is_closed) is True + assert isinstance(loa, StreamedBinaryAPIResponse) + + assert cast(Any, loa.is_closed) is True + + @parametrize + @pytest.mark.respx(base_url=base_url) + def test_path_params_render(self, client: Telnyx) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `enterprise_id` but received ''"): + client.enterprises.reputation.loa.with_raw_response.render( + enterprise_id="", + ) + + +class TestAsyncLoa: + 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_update(self, async_client: AsyncTelnyx) -> None: + loa = await async_client.enterprises.reputation.loa.update( + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + loa_document_id="2a7e8337-e803-4057-a4ae-26c40eb0bc6c", + ) + assert_matches_type(LoaUpdateResponse, loa, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_update(self, async_client: AsyncTelnyx) -> None: + response = await async_client.enterprises.reputation.loa.with_raw_response.update( + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + loa_document_id="2a7e8337-e803-4057-a4ae-26c40eb0bc6c", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + loa = await response.parse() + assert_matches_type(LoaUpdateResponse, loa, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_update(self, async_client: AsyncTelnyx) -> None: + async with async_client.enterprises.reputation.loa.with_streaming_response.update( + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + loa_document_id="2a7e8337-e803-4057-a4ae-26c40eb0bc6c", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + loa = await response.parse() + assert_matches_type(LoaUpdateResponse, loa, 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(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.reputation.loa.with_raw_response.update( + enterprise_id="", + loa_document_id="2a7e8337-e803-4057-a4ae-26c40eb0bc6c", + ) + + @parametrize + @pytest.mark.respx(base_url=base_url) + async def test_method_render(self, async_client: AsyncTelnyx, respx_mock: MockRouter) -> None: + respx_mock.post("/enterprises/4a6192a4-573d-446d-b3ce-aff9117272a6/reputation/loa").mock( + return_value=httpx.Response(200, json={"foo": "bar"}) + ) + loa = await async_client.enterprises.reputation.loa.render( + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + ) + assert loa.is_closed + assert await loa.json() == {"foo": "bar"} + assert cast(Any, loa.is_closed) is True + assert isinstance(loa, AsyncBinaryAPIResponse) + + @parametrize + @pytest.mark.respx(base_url=base_url) + async def test_method_render_with_all_params(self, async_client: AsyncTelnyx, respx_mock: MockRouter) -> None: + respx_mock.post("/enterprises/4a6192a4-573d-446d-b3ce-aff9117272a6/reputation/loa").mock( + return_value=httpx.Response(200, json={"foo": "bar"}) + ) + loa = await async_client.enterprises.reputation.loa.render( + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + agent={ + "administrative_area": "administrative_area", + "city": "city", + "contact_email": "dev@stainless.com", + "contact_name": "contact_name", + "contact_phone": "+13125550000", + "contact_title": "contact_title", + "country": "US", + "legal_name": "legal_name", + "postal_code": "postal_code", + "street_address": "street_address", + "dba": "dba", + "extended_address": "extended_address", + }, + signature={ + "image_base64": "image_base64", + "signer_name": "signer_name", + }, + ) + assert loa.is_closed + assert await loa.json() == {"foo": "bar"} + assert cast(Any, loa.is_closed) is True + assert isinstance(loa, AsyncBinaryAPIResponse) + + @parametrize + @pytest.mark.respx(base_url=base_url) + async def test_raw_response_render(self, async_client: AsyncTelnyx, respx_mock: MockRouter) -> None: + respx_mock.post("/enterprises/4a6192a4-573d-446d-b3ce-aff9117272a6/reputation/loa").mock( + return_value=httpx.Response(200, json={"foo": "bar"}) + ) + + loa = await async_client.enterprises.reputation.loa.with_raw_response.render( + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + ) + + assert loa.is_closed is True + assert loa.http_request.headers.get("X-Stainless-Lang") == "python" + assert await loa.json() == {"foo": "bar"} + assert isinstance(loa, AsyncBinaryAPIResponse) + + @parametrize + @pytest.mark.respx(base_url=base_url) + async def test_streaming_response_render(self, async_client: AsyncTelnyx, respx_mock: MockRouter) -> None: + respx_mock.post("/enterprises/4a6192a4-573d-446d-b3ce-aff9117272a6/reputation/loa").mock( + return_value=httpx.Response(200, json={"foo": "bar"}) + ) + async with async_client.enterprises.reputation.loa.with_streaming_response.render( + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + ) as loa: + assert not loa.is_closed + assert loa.http_request.headers.get("X-Stainless-Lang") == "python" + + assert await loa.json() == {"foo": "bar"} + assert cast(Any, loa.is_closed) is True + assert isinstance(loa, AsyncStreamedBinaryAPIResponse) + + assert cast(Any, loa.is_closed) is True + + @parametrize + @pytest.mark.respx(base_url=base_url) + async def test_path_params_render(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.reputation.loa.with_raw_response.render( + enterprise_id="", + ) diff --git a/tests/api_resources/enterprises/reputation/test_numbers.py b/tests/api_resources/enterprises/reputation/test_numbers.py index 584bea8d..00193d55 100644 --- a/tests/api_resources/enterprises/reputation/test_numbers.py +++ b/tests/api_resources/enterprises/reputation/test_numbers.py @@ -10,8 +10,9 @@ from telnyx import Telnyx, AsyncTelnyx from tests.utils import assert_matches_type from telnyx.pagination import SyncDefaultFlatPagination, AsyncDefaultFlatPagination -from telnyx.types.shared import ReputationPhoneNumberWithReputationData from telnyx.types.enterprises.reputation import ( + NumberListResponse, + NumberRefreshResponse, NumberRetrieveResponse, NumberAssociateResponse, ) @@ -26,8 +27,8 @@ class TestNumbers: @parametrize def test_method_retrieve(self, client: Telnyx) -> None: number = client.enterprises.reputation.numbers.retrieve( - phone_number="+16035551234", - enterprise_id="6a09cdc3-8948-47f0-aa62-74ac943d6c58", + phone_number="+19493253498", + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", ) assert_matches_type(NumberRetrieveResponse, number, path=["response"]) @@ -35,8 +36,8 @@ def test_method_retrieve(self, client: Telnyx) -> None: @parametrize def test_method_retrieve_with_all_params(self, client: Telnyx) -> None: number = client.enterprises.reputation.numbers.retrieve( - phone_number="+16035551234", - enterprise_id="6a09cdc3-8948-47f0-aa62-74ac943d6c58", + phone_number="+19493253498", + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", fresh=True, ) assert_matches_type(NumberRetrieveResponse, number, path=["response"]) @@ -45,8 +46,8 @@ def test_method_retrieve_with_all_params(self, client: Telnyx) -> None: @parametrize def test_raw_response_retrieve(self, client: Telnyx) -> None: response = client.enterprises.reputation.numbers.with_raw_response.retrieve( - phone_number="+16035551234", - enterprise_id="6a09cdc3-8948-47f0-aa62-74ac943d6c58", + phone_number="+19493253498", + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", ) assert response.is_closed is True @@ -58,8 +59,8 @@ def test_raw_response_retrieve(self, client: Telnyx) -> None: @parametrize def test_streaming_response_retrieve(self, client: Telnyx) -> None: with client.enterprises.reputation.numbers.with_streaming_response.retrieve( - phone_number="+16035551234", - enterprise_id="6a09cdc3-8948-47f0-aa62-74ac943d6c58", + phone_number="+19493253498", + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -74,66 +75,58 @@ def test_streaming_response_retrieve(self, client: Telnyx) -> None: def test_path_params_retrieve(self, client: Telnyx) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `enterprise_id` but received ''"): client.enterprises.reputation.numbers.with_raw_response.retrieve( - phone_number="+16035551234", + phone_number="+19493253498", enterprise_id="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `phone_number` but received ''"): client.enterprises.reputation.numbers.with_raw_response.retrieve( phone_number="", - enterprise_id="6a09cdc3-8948-47f0-aa62-74ac943d6c58", + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_method_list(self, client: Telnyx) -> None: number = client.enterprises.reputation.numbers.list( - enterprise_id="6a09cdc3-8948-47f0-aa62-74ac943d6c58", - ) - assert_matches_type( - SyncDefaultFlatPagination[ReputationPhoneNumberWithReputationData], number, path=["response"] + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", ) + assert_matches_type(SyncDefaultFlatPagination[NumberListResponse], number, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_method_list_with_all_params(self, client: Telnyx) -> None: number = client.enterprises.reputation.numbers.list( - enterprise_id="6a09cdc3-8948-47f0-aa62-74ac943d6c58", + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", page_number=1, - page_size=1, + page_size=10, phone_number="+16035551234", ) - assert_matches_type( - SyncDefaultFlatPagination[ReputationPhoneNumberWithReputationData], number, path=["response"] - ) + assert_matches_type(SyncDefaultFlatPagination[NumberListResponse], number, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_list(self, client: Telnyx) -> None: response = client.enterprises.reputation.numbers.with_raw_response.list( - enterprise_id="6a09cdc3-8948-47f0-aa62-74ac943d6c58", + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" number = response.parse() - assert_matches_type( - SyncDefaultFlatPagination[ReputationPhoneNumberWithReputationData], number, path=["response"] - ) + assert_matches_type(SyncDefaultFlatPagination[NumberListResponse], number, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_streaming_response_list(self, client: Telnyx) -> None: with client.enterprises.reputation.numbers.with_streaming_response.list( - enterprise_id="6a09cdc3-8948-47f0-aa62-74ac943d6c58", + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" number = response.parse() - assert_matches_type( - SyncDefaultFlatPagination[ReputationPhoneNumberWithReputationData], number, path=["response"] - ) + assert_matches_type(SyncDefaultFlatPagination[NumberListResponse], number, path=["response"]) assert cast(Any, response.is_closed) is True @@ -149,8 +142,8 @@ def test_path_params_list(self, client: Telnyx) -> None: @parametrize def test_method_associate(self, client: Telnyx) -> None: number = client.enterprises.reputation.numbers.associate( - enterprise_id="6a09cdc3-8948-47f0-aa62-74ac943d6c58", - phone_numbers=["+16035551234"], + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + phone_numbers=["+19493253498", "+12134445566"], ) assert_matches_type(NumberAssociateResponse, number, path=["response"]) @@ -158,8 +151,8 @@ def test_method_associate(self, client: Telnyx) -> None: @parametrize def test_raw_response_associate(self, client: Telnyx) -> None: response = client.enterprises.reputation.numbers.with_raw_response.associate( - enterprise_id="6a09cdc3-8948-47f0-aa62-74ac943d6c58", - phone_numbers=["+16035551234"], + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + phone_numbers=["+19493253498", "+12134445566"], ) assert response.is_closed is True @@ -171,8 +164,8 @@ def test_raw_response_associate(self, client: Telnyx) -> None: @parametrize def test_streaming_response_associate(self, client: Telnyx) -> None: with client.enterprises.reputation.numbers.with_streaming_response.associate( - enterprise_id="6a09cdc3-8948-47f0-aa62-74ac943d6c58", - phone_numbers=["+16035551234"], + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + phone_numbers=["+19493253498", "+12134445566"], ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -188,15 +181,15 @@ def test_path_params_associate(self, client: Telnyx) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `enterprise_id` but received ''"): client.enterprises.reputation.numbers.with_raw_response.associate( enterprise_id="", - phone_numbers=["+16035551234"], + phone_numbers=["+19493253498", "+12134445566"], ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_method_disassociate(self, client: Telnyx) -> None: number = client.enterprises.reputation.numbers.disassociate( - phone_number="+16035551234", - enterprise_id="6a09cdc3-8948-47f0-aa62-74ac943d6c58", + phone_number="+19493253498", + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", ) assert number is None @@ -204,8 +197,8 @@ def test_method_disassociate(self, client: Telnyx) -> None: @parametrize def test_raw_response_disassociate(self, client: Telnyx) -> None: response = client.enterprises.reputation.numbers.with_raw_response.disassociate( - phone_number="+16035551234", - enterprise_id="6a09cdc3-8948-47f0-aa62-74ac943d6c58", + phone_number="+19493253498", + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", ) assert response.is_closed is True @@ -217,8 +210,8 @@ def test_raw_response_disassociate(self, client: Telnyx) -> None: @parametrize def test_streaming_response_disassociate(self, client: Telnyx) -> None: with client.enterprises.reputation.numbers.with_streaming_response.disassociate( - phone_number="+16035551234", - enterprise_id="6a09cdc3-8948-47f0-aa62-74ac943d6c58", + phone_number="+19493253498", + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -233,14 +226,60 @@ def test_streaming_response_disassociate(self, client: Telnyx) -> None: def test_path_params_disassociate(self, client: Telnyx) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `enterprise_id` but received ''"): client.enterprises.reputation.numbers.with_raw_response.disassociate( - phone_number="+16035551234", + phone_number="+19493253498", enterprise_id="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `phone_number` but received ''"): client.enterprises.reputation.numbers.with_raw_response.disassociate( phone_number="", - enterprise_id="6a09cdc3-8948-47f0-aa62-74ac943d6c58", + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_refresh(self, client: Telnyx) -> None: + number = client.enterprises.reputation.numbers.refresh( + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + phone_numbers=["+19493253498"], + ) + assert_matches_type(NumberRefreshResponse, number, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_refresh(self, client: Telnyx) -> None: + response = client.enterprises.reputation.numbers.with_raw_response.refresh( + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + phone_numbers=["+19493253498"], + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + number = response.parse() + assert_matches_type(NumberRefreshResponse, number, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_refresh(self, client: Telnyx) -> None: + with client.enterprises.reputation.numbers.with_streaming_response.refresh( + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + phone_numbers=["+19493253498"], + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + number = response.parse() + assert_matches_type(NumberRefreshResponse, number, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_path_params_refresh(self, client: Telnyx) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `enterprise_id` but received ''"): + client.enterprises.reputation.numbers.with_raw_response.refresh( + enterprise_id="", + phone_numbers=["+19493253498"], ) @@ -253,8 +292,8 @@ class TestAsyncNumbers: @parametrize async def test_method_retrieve(self, async_client: AsyncTelnyx) -> None: number = await async_client.enterprises.reputation.numbers.retrieve( - phone_number="+16035551234", - enterprise_id="6a09cdc3-8948-47f0-aa62-74ac943d6c58", + phone_number="+19493253498", + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", ) assert_matches_type(NumberRetrieveResponse, number, path=["response"]) @@ -262,8 +301,8 @@ async def test_method_retrieve(self, async_client: AsyncTelnyx) -> None: @parametrize async def test_method_retrieve_with_all_params(self, async_client: AsyncTelnyx) -> None: number = await async_client.enterprises.reputation.numbers.retrieve( - phone_number="+16035551234", - enterprise_id="6a09cdc3-8948-47f0-aa62-74ac943d6c58", + phone_number="+19493253498", + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", fresh=True, ) assert_matches_type(NumberRetrieveResponse, number, path=["response"]) @@ -272,8 +311,8 @@ async def test_method_retrieve_with_all_params(self, async_client: AsyncTelnyx) @parametrize async def test_raw_response_retrieve(self, async_client: AsyncTelnyx) -> None: response = await async_client.enterprises.reputation.numbers.with_raw_response.retrieve( - phone_number="+16035551234", - enterprise_id="6a09cdc3-8948-47f0-aa62-74ac943d6c58", + phone_number="+19493253498", + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", ) assert response.is_closed is True @@ -285,8 +324,8 @@ async def test_raw_response_retrieve(self, async_client: AsyncTelnyx) -> None: @parametrize async def test_streaming_response_retrieve(self, async_client: AsyncTelnyx) -> None: async with async_client.enterprises.reputation.numbers.with_streaming_response.retrieve( - phone_number="+16035551234", - enterprise_id="6a09cdc3-8948-47f0-aa62-74ac943d6c58", + phone_number="+19493253498", + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -301,66 +340,58 @@ async def test_streaming_response_retrieve(self, async_client: AsyncTelnyx) -> N async def test_path_params_retrieve(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.reputation.numbers.with_raw_response.retrieve( - phone_number="+16035551234", + phone_number="+19493253498", enterprise_id="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `phone_number` but received ''"): await async_client.enterprises.reputation.numbers.with_raw_response.retrieve( phone_number="", - enterprise_id="6a09cdc3-8948-47f0-aa62-74ac943d6c58", + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_method_list(self, async_client: AsyncTelnyx) -> None: number = await async_client.enterprises.reputation.numbers.list( - enterprise_id="6a09cdc3-8948-47f0-aa62-74ac943d6c58", - ) - assert_matches_type( - AsyncDefaultFlatPagination[ReputationPhoneNumberWithReputationData], number, path=["response"] + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", ) + assert_matches_type(AsyncDefaultFlatPagination[NumberListResponse], number, 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: number = await async_client.enterprises.reputation.numbers.list( - enterprise_id="6a09cdc3-8948-47f0-aa62-74ac943d6c58", + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", page_number=1, - page_size=1, + page_size=10, phone_number="+16035551234", ) - assert_matches_type( - AsyncDefaultFlatPagination[ReputationPhoneNumberWithReputationData], number, path=["response"] - ) + assert_matches_type(AsyncDefaultFlatPagination[NumberListResponse], number, 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.enterprises.reputation.numbers.with_raw_response.list( - enterprise_id="6a09cdc3-8948-47f0-aa62-74ac943d6c58", + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" number = await response.parse() - assert_matches_type( - AsyncDefaultFlatPagination[ReputationPhoneNumberWithReputationData], number, path=["response"] - ) + assert_matches_type(AsyncDefaultFlatPagination[NumberListResponse], number, 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.enterprises.reputation.numbers.with_streaming_response.list( - enterprise_id="6a09cdc3-8948-47f0-aa62-74ac943d6c58", + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" number = await response.parse() - assert_matches_type( - AsyncDefaultFlatPagination[ReputationPhoneNumberWithReputationData], number, path=["response"] - ) + assert_matches_type(AsyncDefaultFlatPagination[NumberListResponse], number, path=["response"]) assert cast(Any, response.is_closed) is True @@ -376,8 +407,8 @@ async def test_path_params_list(self, async_client: AsyncTelnyx) -> None: @parametrize async def test_method_associate(self, async_client: AsyncTelnyx) -> None: number = await async_client.enterprises.reputation.numbers.associate( - enterprise_id="6a09cdc3-8948-47f0-aa62-74ac943d6c58", - phone_numbers=["+16035551234"], + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + phone_numbers=["+19493253498", "+12134445566"], ) assert_matches_type(NumberAssociateResponse, number, path=["response"]) @@ -385,8 +416,8 @@ async def test_method_associate(self, async_client: AsyncTelnyx) -> None: @parametrize async def test_raw_response_associate(self, async_client: AsyncTelnyx) -> None: response = await async_client.enterprises.reputation.numbers.with_raw_response.associate( - enterprise_id="6a09cdc3-8948-47f0-aa62-74ac943d6c58", - phone_numbers=["+16035551234"], + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + phone_numbers=["+19493253498", "+12134445566"], ) assert response.is_closed is True @@ -398,8 +429,8 @@ async def test_raw_response_associate(self, async_client: AsyncTelnyx) -> None: @parametrize async def test_streaming_response_associate(self, async_client: AsyncTelnyx) -> None: async with async_client.enterprises.reputation.numbers.with_streaming_response.associate( - enterprise_id="6a09cdc3-8948-47f0-aa62-74ac943d6c58", - phone_numbers=["+16035551234"], + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + phone_numbers=["+19493253498", "+12134445566"], ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -415,15 +446,15 @@ async def test_path_params_associate(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.reputation.numbers.with_raw_response.associate( enterprise_id="", - phone_numbers=["+16035551234"], + phone_numbers=["+19493253498", "+12134445566"], ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_method_disassociate(self, async_client: AsyncTelnyx) -> None: number = await async_client.enterprises.reputation.numbers.disassociate( - phone_number="+16035551234", - enterprise_id="6a09cdc3-8948-47f0-aa62-74ac943d6c58", + phone_number="+19493253498", + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", ) assert number is None @@ -431,8 +462,8 @@ async def test_method_disassociate(self, async_client: AsyncTelnyx) -> None: @parametrize async def test_raw_response_disassociate(self, async_client: AsyncTelnyx) -> None: response = await async_client.enterprises.reputation.numbers.with_raw_response.disassociate( - phone_number="+16035551234", - enterprise_id="6a09cdc3-8948-47f0-aa62-74ac943d6c58", + phone_number="+19493253498", + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", ) assert response.is_closed is True @@ -444,8 +475,8 @@ async def test_raw_response_disassociate(self, async_client: AsyncTelnyx) -> Non @parametrize async def test_streaming_response_disassociate(self, async_client: AsyncTelnyx) -> None: async with async_client.enterprises.reputation.numbers.with_streaming_response.disassociate( - phone_number="+16035551234", - enterprise_id="6a09cdc3-8948-47f0-aa62-74ac943d6c58", + phone_number="+19493253498", + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -460,12 +491,58 @@ async def test_streaming_response_disassociate(self, async_client: AsyncTelnyx) async def test_path_params_disassociate(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.reputation.numbers.with_raw_response.disassociate( - phone_number="+16035551234", + phone_number="+19493253498", enterprise_id="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `phone_number` but received ''"): await async_client.enterprises.reputation.numbers.with_raw_response.disassociate( phone_number="", - enterprise_id="6a09cdc3-8948-47f0-aa62-74ac943d6c58", + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_refresh(self, async_client: AsyncTelnyx) -> None: + number = await async_client.enterprises.reputation.numbers.refresh( + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + phone_numbers=["+19493253498"], + ) + assert_matches_type(NumberRefreshResponse, number, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_refresh(self, async_client: AsyncTelnyx) -> None: + response = await async_client.enterprises.reputation.numbers.with_raw_response.refresh( + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + phone_numbers=["+19493253498"], + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + number = await response.parse() + assert_matches_type(NumberRefreshResponse, number, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_refresh(self, async_client: AsyncTelnyx) -> None: + async with async_client.enterprises.reputation.numbers.with_streaming_response.refresh( + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + phone_numbers=["+19493253498"], + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + number = await response.parse() + assert_matches_type(NumberRefreshResponse, number, 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_refresh(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.reputation.numbers.with_raw_response.refresh( + enterprise_id="", + phone_numbers=["+19493253498"], ) diff --git a/tests/api_resources/enterprises/test_dir.py b/tests/api_resources/enterprises/test_dir.py new file mode 100644 index 00000000..c0056cb6 --- /dev/null +++ b/tests/api_resources/enterprises/test_dir.py @@ -0,0 +1,322 @@ +# 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_datetime +from telnyx.pagination import SyncDefaultFlatPagination, AsyncDefaultFlatPagination +from telnyx.types.enterprises import DirListResponse, DirCreateResponse + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestDir: + 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: + dir = client.enterprises.dir.create( + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + authorizer_email="sam@acmeplumbing.example.com", + authorizer_name="Sam Owner", + certify_brand_is_accurate=True, + certify_ip_ownership=True, + certify_no_shaft_content=True, + display_name="Acme Plumbing", + ) + assert_matches_type(DirCreateResponse, dir, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_create_with_all_params(self, client: Telnyx) -> None: + dir = client.enterprises.dir.create( + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + authorizer_email="sam@acmeplumbing.example.com", + authorizer_name="Sam Owner", + certify_brand_is_accurate=True, + certify_ip_ownership=True, + certify_no_shaft_content=True, + display_name="Acme Plumbing", + call_reasons=["Appointment reminders", "Billing inquiries"], + documents=[ + { + "document_id": "2a7e8337-e803-4057-a4ae-26c40eb0bc6c", + "document_type": "business_registration", + "description": "Certificate of incorporation.", + } + ], + logo_url="https://acmeplumbing.example.com/logo-256.bmp", + reselling=False, + ) + assert_matches_type(DirCreateResponse, dir, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_create(self, client: Telnyx) -> None: + response = client.enterprises.dir.with_raw_response.create( + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + authorizer_email="sam@acmeplumbing.example.com", + authorizer_name="Sam Owner", + certify_brand_is_accurate=True, + certify_ip_ownership=True, + certify_no_shaft_content=True, + display_name="Acme Plumbing", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + dir = response.parse() + assert_matches_type(DirCreateResponse, dir, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_create(self, client: Telnyx) -> None: + with client.enterprises.dir.with_streaming_response.create( + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + authorizer_email="sam@acmeplumbing.example.com", + authorizer_name="Sam Owner", + certify_brand_is_accurate=True, + certify_ip_ownership=True, + certify_no_shaft_content=True, + display_name="Acme Plumbing", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + dir = response.parse() + assert_matches_type(DirCreateResponse, 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_create(self, client: Telnyx) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `enterprise_id` but received ''"): + client.enterprises.dir.with_raw_response.create( + enterprise_id="", + authorizer_email="sam@acmeplumbing.example.com", + authorizer_name="Sam Owner", + certify_brand_is_accurate=True, + certify_ip_ownership=True, + certify_no_shaft_content=True, + display_name="Acme Plumbing", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_list(self, client: Telnyx) -> None: + dir = client.enterprises.dir.list( + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + ) + assert_matches_type(SyncDefaultFlatPagination[DirListResponse], dir, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_list_with_all_params(self, client: Telnyx) -> None: + dir = client.enterprises.dir.list( + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + filter_expiring_at_gte=parse_datetime("2019-12-27T18:11:19.117Z"), + filter_expiring_at_lte=parse_datetime("2019-12-27T18:11:19.117Z"), + filter_expiring_within_days=1, + page_number=1, + page_size=20, + search="search", + sort="created_at", + status="draft", + ) + assert_matches_type(SyncDefaultFlatPagination[DirListResponse], dir, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_list(self, client: Telnyx) -> None: + response = client.enterprises.dir.with_raw_response.list( + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + dir = response.parse() + assert_matches_type(SyncDefaultFlatPagination[DirListResponse], dir, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_list(self, client: Telnyx) -> None: + with client.enterprises.dir.with_streaming_response.list( + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + dir = response.parse() + assert_matches_type(SyncDefaultFlatPagination[DirListResponse], 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_list(self, client: Telnyx) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `enterprise_id` but received ''"): + client.enterprises.dir.with_raw_response.list( + enterprise_id="", + ) + + +class TestAsyncDir: + 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: + dir = await async_client.enterprises.dir.create( + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + authorizer_email="sam@acmeplumbing.example.com", + authorizer_name="Sam Owner", + certify_brand_is_accurate=True, + certify_ip_ownership=True, + certify_no_shaft_content=True, + display_name="Acme Plumbing", + ) + assert_matches_type(DirCreateResponse, dir, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_create_with_all_params(self, async_client: AsyncTelnyx) -> None: + dir = await async_client.enterprises.dir.create( + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + authorizer_email="sam@acmeplumbing.example.com", + authorizer_name="Sam Owner", + certify_brand_is_accurate=True, + certify_ip_ownership=True, + certify_no_shaft_content=True, + display_name="Acme Plumbing", + call_reasons=["Appointment reminders", "Billing inquiries"], + documents=[ + { + "document_id": "2a7e8337-e803-4057-a4ae-26c40eb0bc6c", + "document_type": "business_registration", + "description": "Certificate of incorporation.", + } + ], + logo_url="https://acmeplumbing.example.com/logo-256.bmp", + reselling=False, + ) + assert_matches_type(DirCreateResponse, dir, 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.dir.with_raw_response.create( + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + authorizer_email="sam@acmeplumbing.example.com", + authorizer_name="Sam Owner", + certify_brand_is_accurate=True, + certify_ip_ownership=True, + certify_no_shaft_content=True, + display_name="Acme Plumbing", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + dir = await response.parse() + assert_matches_type(DirCreateResponse, dir, 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.dir.with_streaming_response.create( + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + authorizer_email="sam@acmeplumbing.example.com", + authorizer_name="Sam Owner", + certify_brand_is_accurate=True, + certify_ip_ownership=True, + certify_no_shaft_content=True, + display_name="Acme Plumbing", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + dir = await response.parse() + assert_matches_type(DirCreateResponse, 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_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.dir.with_raw_response.create( + enterprise_id="", + authorizer_email="sam@acmeplumbing.example.com", + authorizer_name="Sam Owner", + certify_brand_is_accurate=True, + certify_ip_ownership=True, + certify_no_shaft_content=True, + display_name="Acme Plumbing", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_list(self, async_client: AsyncTelnyx) -> None: + dir = await async_client.enterprises.dir.list( + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + ) + assert_matches_type(AsyncDefaultFlatPagination[DirListResponse], dir, 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: + dir = await async_client.enterprises.dir.list( + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + filter_expiring_at_gte=parse_datetime("2019-12-27T18:11:19.117Z"), + filter_expiring_at_lte=parse_datetime("2019-12-27T18:11:19.117Z"), + filter_expiring_within_days=1, + page_number=1, + page_size=20, + search="search", + sort="created_at", + status="draft", + ) + assert_matches_type(AsyncDefaultFlatPagination[DirListResponse], dir, 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.enterprises.dir.with_raw_response.list( + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + dir = await response.parse() + assert_matches_type(AsyncDefaultFlatPagination[DirListResponse], dir, 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.enterprises.dir.with_streaming_response.list( + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + dir = await response.parse() + assert_matches_type(AsyncDefaultFlatPagination[DirListResponse], 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_list(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.dir.with_raw_response.list( + enterprise_id="", + ) diff --git a/tests/api_resources/enterprises/test_reputation.py b/tests/api_resources/enterprises/test_reputation.py index 50b78d98..09254b23 100644 --- a/tests/api_resources/enterprises/test_reputation.py +++ b/tests/api_resources/enterprises/test_reputation.py @@ -25,7 +25,7 @@ class TestReputation: @parametrize def test_method_retrieve(self, client: Telnyx) -> None: reputation = client.enterprises.reputation.retrieve( - "6a09cdc3-8948-47f0-aa62-74ac943d6c58", + "4a6192a4-573d-446d-b3ce-aff9117272a6", ) assert_matches_type(ReputationRetrieveResponse, reputation, path=["response"]) @@ -33,7 +33,7 @@ def test_method_retrieve(self, client: Telnyx) -> None: @parametrize def test_raw_response_retrieve(self, client: Telnyx) -> None: response = client.enterprises.reputation.with_raw_response.retrieve( - "6a09cdc3-8948-47f0-aa62-74ac943d6c58", + "4a6192a4-573d-446d-b3ce-aff9117272a6", ) assert response.is_closed is True @@ -45,7 +45,7 @@ def test_raw_response_retrieve(self, client: Telnyx) -> None: @parametrize def test_streaming_response_retrieve(self, client: Telnyx) -> None: with client.enterprises.reputation.with_streaming_response.retrieve( - "6a09cdc3-8948-47f0-aa62-74ac943d6c58", + "4a6192a4-573d-446d-b3ce-aff9117272a6", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -67,7 +67,7 @@ def test_path_params_retrieve(self, client: Telnyx) -> None: @parametrize def test_method_disable(self, client: Telnyx) -> None: reputation = client.enterprises.reputation.disable( - "6a09cdc3-8948-47f0-aa62-74ac943d6c58", + "4a6192a4-573d-446d-b3ce-aff9117272a6", ) assert reputation is None @@ -75,7 +75,7 @@ def test_method_disable(self, client: Telnyx) -> None: @parametrize def test_raw_response_disable(self, client: Telnyx) -> None: response = client.enterprises.reputation.with_raw_response.disable( - "6a09cdc3-8948-47f0-aa62-74ac943d6c58", + "4a6192a4-573d-446d-b3ce-aff9117272a6", ) assert response.is_closed is True @@ -87,7 +87,7 @@ def test_raw_response_disable(self, client: Telnyx) -> None: @parametrize def test_streaming_response_disable(self, client: Telnyx) -> None: with client.enterprises.reputation.with_streaming_response.disable( - "6a09cdc3-8948-47f0-aa62-74ac943d6c58", + "4a6192a4-573d-446d-b3ce-aff9117272a6", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -109,8 +109,8 @@ def test_path_params_disable(self, client: Telnyx) -> None: @parametrize def test_method_enable(self, client: Telnyx) -> None: reputation = client.enterprises.reputation.enable( - enterprise_id="6a09cdc3-8948-47f0-aa62-74ac943d6c58", - loa_document_id="doc_01HXYZ1234ABCDEF", + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + loa_document_id="2a7e8337-e803-4057-a4ae-26c40eb0bc6c", ) assert_matches_type(ReputationEnableResponse, reputation, path=["response"]) @@ -118,8 +118,8 @@ def test_method_enable(self, client: Telnyx) -> None: @parametrize def test_method_enable_with_all_params(self, client: Telnyx) -> None: reputation = client.enterprises.reputation.enable( - enterprise_id="6a09cdc3-8948-47f0-aa62-74ac943d6c58", - loa_document_id="doc_01HXYZ1234ABCDEF", + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + loa_document_id="2a7e8337-e803-4057-a4ae-26c40eb0bc6c", check_frequency="business_daily", ) assert_matches_type(ReputationEnableResponse, reputation, path=["response"]) @@ -128,8 +128,8 @@ def test_method_enable_with_all_params(self, client: Telnyx) -> None: @parametrize def test_raw_response_enable(self, client: Telnyx) -> None: response = client.enterprises.reputation.with_raw_response.enable( - enterprise_id="6a09cdc3-8948-47f0-aa62-74ac943d6c58", - loa_document_id="doc_01HXYZ1234ABCDEF", + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + loa_document_id="2a7e8337-e803-4057-a4ae-26c40eb0bc6c", ) assert response.is_closed is True @@ -141,8 +141,8 @@ def test_raw_response_enable(self, client: Telnyx) -> None: @parametrize def test_streaming_response_enable(self, client: Telnyx) -> None: with client.enterprises.reputation.with_streaming_response.enable( - enterprise_id="6a09cdc3-8948-47f0-aa62-74ac943d6c58", - loa_document_id="doc_01HXYZ1234ABCDEF", + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + loa_document_id="2a7e8337-e803-4057-a4ae-26c40eb0bc6c", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -158,15 +158,15 @@ def test_path_params_enable(self, client: Telnyx) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `enterprise_id` but received ''"): client.enterprises.reputation.with_raw_response.enable( enterprise_id="", - loa_document_id="doc_01HXYZ1234ABCDEF", + loa_document_id="2a7e8337-e803-4057-a4ae-26c40eb0bc6c", ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_method_update_frequency(self, client: Telnyx) -> None: reputation = client.enterprises.reputation.update_frequency( - enterprise_id="6a09cdc3-8948-47f0-aa62-74ac943d6c58", - check_frequency="business_daily", + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + check_frequency="weekly", ) assert_matches_type(ReputationUpdateFrequencyResponse, reputation, path=["response"]) @@ -174,8 +174,8 @@ def test_method_update_frequency(self, client: Telnyx) -> None: @parametrize def test_raw_response_update_frequency(self, client: Telnyx) -> None: response = client.enterprises.reputation.with_raw_response.update_frequency( - enterprise_id="6a09cdc3-8948-47f0-aa62-74ac943d6c58", - check_frequency="business_daily", + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + check_frequency="weekly", ) assert response.is_closed is True @@ -187,8 +187,8 @@ def test_raw_response_update_frequency(self, client: Telnyx) -> None: @parametrize def test_streaming_response_update_frequency(self, client: Telnyx) -> None: with client.enterprises.reputation.with_streaming_response.update_frequency( - enterprise_id="6a09cdc3-8948-47f0-aa62-74ac943d6c58", - check_frequency="business_daily", + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + check_frequency="weekly", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -204,7 +204,7 @@ def test_path_params_update_frequency(self, client: Telnyx) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `enterprise_id` but received ''"): client.enterprises.reputation.with_raw_response.update_frequency( enterprise_id="", - check_frequency="business_daily", + check_frequency="weekly", ) @@ -217,7 +217,7 @@ class TestAsyncReputation: @parametrize async def test_method_retrieve(self, async_client: AsyncTelnyx) -> None: reputation = await async_client.enterprises.reputation.retrieve( - "6a09cdc3-8948-47f0-aa62-74ac943d6c58", + "4a6192a4-573d-446d-b3ce-aff9117272a6", ) assert_matches_type(ReputationRetrieveResponse, reputation, path=["response"]) @@ -225,7 +225,7 @@ async def test_method_retrieve(self, async_client: AsyncTelnyx) -> None: @parametrize async def test_raw_response_retrieve(self, async_client: AsyncTelnyx) -> None: response = await async_client.enterprises.reputation.with_raw_response.retrieve( - "6a09cdc3-8948-47f0-aa62-74ac943d6c58", + "4a6192a4-573d-446d-b3ce-aff9117272a6", ) assert response.is_closed is True @@ -237,7 +237,7 @@ async def test_raw_response_retrieve(self, async_client: AsyncTelnyx) -> None: @parametrize async def test_streaming_response_retrieve(self, async_client: AsyncTelnyx) -> None: async with async_client.enterprises.reputation.with_streaming_response.retrieve( - "6a09cdc3-8948-47f0-aa62-74ac943d6c58", + "4a6192a4-573d-446d-b3ce-aff9117272a6", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -259,7 +259,7 @@ async def test_path_params_retrieve(self, async_client: AsyncTelnyx) -> None: @parametrize async def test_method_disable(self, async_client: AsyncTelnyx) -> None: reputation = await async_client.enterprises.reputation.disable( - "6a09cdc3-8948-47f0-aa62-74ac943d6c58", + "4a6192a4-573d-446d-b3ce-aff9117272a6", ) assert reputation is None @@ -267,7 +267,7 @@ async def test_method_disable(self, async_client: AsyncTelnyx) -> None: @parametrize async def test_raw_response_disable(self, async_client: AsyncTelnyx) -> None: response = await async_client.enterprises.reputation.with_raw_response.disable( - "6a09cdc3-8948-47f0-aa62-74ac943d6c58", + "4a6192a4-573d-446d-b3ce-aff9117272a6", ) assert response.is_closed is True @@ -279,7 +279,7 @@ async def test_raw_response_disable(self, async_client: AsyncTelnyx) -> None: @parametrize async def test_streaming_response_disable(self, async_client: AsyncTelnyx) -> None: async with async_client.enterprises.reputation.with_streaming_response.disable( - "6a09cdc3-8948-47f0-aa62-74ac943d6c58", + "4a6192a4-573d-446d-b3ce-aff9117272a6", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -301,8 +301,8 @@ async def test_path_params_disable(self, async_client: AsyncTelnyx) -> None: @parametrize async def test_method_enable(self, async_client: AsyncTelnyx) -> None: reputation = await async_client.enterprises.reputation.enable( - enterprise_id="6a09cdc3-8948-47f0-aa62-74ac943d6c58", - loa_document_id="doc_01HXYZ1234ABCDEF", + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + loa_document_id="2a7e8337-e803-4057-a4ae-26c40eb0bc6c", ) assert_matches_type(ReputationEnableResponse, reputation, path=["response"]) @@ -310,8 +310,8 @@ async def test_method_enable(self, async_client: AsyncTelnyx) -> None: @parametrize async def test_method_enable_with_all_params(self, async_client: AsyncTelnyx) -> None: reputation = await async_client.enterprises.reputation.enable( - enterprise_id="6a09cdc3-8948-47f0-aa62-74ac943d6c58", - loa_document_id="doc_01HXYZ1234ABCDEF", + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + loa_document_id="2a7e8337-e803-4057-a4ae-26c40eb0bc6c", check_frequency="business_daily", ) assert_matches_type(ReputationEnableResponse, reputation, path=["response"]) @@ -320,8 +320,8 @@ async def test_method_enable_with_all_params(self, async_client: AsyncTelnyx) -> @parametrize async def test_raw_response_enable(self, async_client: AsyncTelnyx) -> None: response = await async_client.enterprises.reputation.with_raw_response.enable( - enterprise_id="6a09cdc3-8948-47f0-aa62-74ac943d6c58", - loa_document_id="doc_01HXYZ1234ABCDEF", + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + loa_document_id="2a7e8337-e803-4057-a4ae-26c40eb0bc6c", ) assert response.is_closed is True @@ -333,8 +333,8 @@ async def test_raw_response_enable(self, async_client: AsyncTelnyx) -> None: @parametrize async def test_streaming_response_enable(self, async_client: AsyncTelnyx) -> None: async with async_client.enterprises.reputation.with_streaming_response.enable( - enterprise_id="6a09cdc3-8948-47f0-aa62-74ac943d6c58", - loa_document_id="doc_01HXYZ1234ABCDEF", + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + loa_document_id="2a7e8337-e803-4057-a4ae-26c40eb0bc6c", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -350,15 +350,15 @@ async def test_path_params_enable(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.reputation.with_raw_response.enable( enterprise_id="", - loa_document_id="doc_01HXYZ1234ABCDEF", + loa_document_id="2a7e8337-e803-4057-a4ae-26c40eb0bc6c", ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_method_update_frequency(self, async_client: AsyncTelnyx) -> None: reputation = await async_client.enterprises.reputation.update_frequency( - enterprise_id="6a09cdc3-8948-47f0-aa62-74ac943d6c58", - check_frequency="business_daily", + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + check_frequency="weekly", ) assert_matches_type(ReputationUpdateFrequencyResponse, reputation, path=["response"]) @@ -366,8 +366,8 @@ async def test_method_update_frequency(self, async_client: AsyncTelnyx) -> None: @parametrize async def test_raw_response_update_frequency(self, async_client: AsyncTelnyx) -> None: response = await async_client.enterprises.reputation.with_raw_response.update_frequency( - enterprise_id="6a09cdc3-8948-47f0-aa62-74ac943d6c58", - check_frequency="business_daily", + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + check_frequency="weekly", ) assert response.is_closed is True @@ -379,8 +379,8 @@ async def test_raw_response_update_frequency(self, async_client: AsyncTelnyx) -> @parametrize async def test_streaming_response_update_frequency(self, async_client: AsyncTelnyx) -> None: async with async_client.enterprises.reputation.with_streaming_response.update_frequency( - enterprise_id="6a09cdc3-8948-47f0-aa62-74ac943d6c58", - check_frequency="business_daily", + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", + check_frequency="weekly", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -396,5 +396,5 @@ async def test_path_params_update_frequency(self, async_client: AsyncTelnyx) -> with pytest.raises(ValueError, match=r"Expected a non-empty value for `enterprise_id` but received ''"): await async_client.enterprises.reputation.with_raw_response.update_frequency( enterprise_id="", - check_frequency="business_daily", + check_frequency="weekly", ) diff --git a/tests/api_resources/reputation/test_numbers.py b/tests/api_resources/reputation/test_numbers.py index e94b9fc6..23c1bed3 100644 --- a/tests/api_resources/reputation/test_numbers.py +++ b/tests/api_resources/reputation/test_numbers.py @@ -10,8 +10,10 @@ from telnyx import Telnyx, AsyncTelnyx from tests.utils import assert_matches_type from telnyx.pagination import SyncDefaultFlatPagination, AsyncDefaultFlatPagination -from telnyx.types.shared import ReputationPhoneNumberWithReputationData -from telnyx.types.reputation import NumberRetrieveResponse +from telnyx.types.reputation import ( + NumberListResponse, + NumberRetrieveResponse, +) base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -23,7 +25,7 @@ class TestNumbers: @parametrize def test_method_retrieve(self, client: Telnyx) -> None: number = client.reputation.numbers.retrieve( - phone_number="+16035551234", + phone_number="+19493253498", ) assert_matches_type(NumberRetrieveResponse, number, path=["response"]) @@ -31,7 +33,7 @@ def test_method_retrieve(self, client: Telnyx) -> None: @parametrize def test_method_retrieve_with_all_params(self, client: Telnyx) -> None: number = client.reputation.numbers.retrieve( - phone_number="+16035551234", + phone_number="+19493253498", fresh=True, ) assert_matches_type(NumberRetrieveResponse, number, path=["response"]) @@ -40,7 +42,7 @@ def test_method_retrieve_with_all_params(self, client: Telnyx) -> None: @parametrize def test_raw_response_retrieve(self, client: Telnyx) -> None: response = client.reputation.numbers.with_raw_response.retrieve( - phone_number="+16035551234", + phone_number="+19493253498", ) assert response.is_closed is True @@ -52,7 +54,7 @@ def test_raw_response_retrieve(self, client: Telnyx) -> None: @parametrize def test_streaming_response_retrieve(self, client: Telnyx) -> None: with client.reputation.numbers.with_streaming_response.retrieve( - phone_number="+16035551234", + phone_number="+19493253498", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -74,21 +76,17 @@ def test_path_params_retrieve(self, client: Telnyx) -> None: @parametrize def test_method_list(self, client: Telnyx) -> None: number = client.reputation.numbers.list() - assert_matches_type( - SyncDefaultFlatPagination[ReputationPhoneNumberWithReputationData], number, path=["response"] - ) + assert_matches_type(SyncDefaultFlatPagination[NumberListResponse], number, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_method_list_with_all_params(self, client: Telnyx) -> None: number = client.reputation.numbers.list( page_number=1, - page_size=1, + page_size=20, phone_number="+16035551234", ) - assert_matches_type( - SyncDefaultFlatPagination[ReputationPhoneNumberWithReputationData], number, path=["response"] - ) + assert_matches_type(SyncDefaultFlatPagination[NumberListResponse], number, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -98,9 +96,7 @@ def test_raw_response_list(self, client: Telnyx) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" number = response.parse() - assert_matches_type( - SyncDefaultFlatPagination[ReputationPhoneNumberWithReputationData], number, path=["response"] - ) + assert_matches_type(SyncDefaultFlatPagination[NumberListResponse], number, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -110,9 +106,7 @@ def test_streaming_response_list(self, client: Telnyx) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" number = response.parse() - assert_matches_type( - SyncDefaultFlatPagination[ReputationPhoneNumberWithReputationData], number, path=["response"] - ) + assert_matches_type(SyncDefaultFlatPagination[NumberListResponse], number, path=["response"]) assert cast(Any, response.is_closed) is True @@ -120,7 +114,7 @@ def test_streaming_response_list(self, client: Telnyx) -> None: @parametrize def test_method_delete(self, client: Telnyx) -> None: number = client.reputation.numbers.delete( - "+16035551234", + "+19493253498", ) assert number is None @@ -128,7 +122,7 @@ def test_method_delete(self, client: Telnyx) -> None: @parametrize def test_raw_response_delete(self, client: Telnyx) -> None: response = client.reputation.numbers.with_raw_response.delete( - "+16035551234", + "+19493253498", ) assert response.is_closed is True @@ -140,7 +134,7 @@ def test_raw_response_delete(self, client: Telnyx) -> None: @parametrize def test_streaming_response_delete(self, client: Telnyx) -> None: with client.reputation.numbers.with_streaming_response.delete( - "+16035551234", + "+19493253498", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -168,7 +162,7 @@ class TestAsyncNumbers: @parametrize async def test_method_retrieve(self, async_client: AsyncTelnyx) -> None: number = await async_client.reputation.numbers.retrieve( - phone_number="+16035551234", + phone_number="+19493253498", ) assert_matches_type(NumberRetrieveResponse, number, path=["response"]) @@ -176,7 +170,7 @@ async def test_method_retrieve(self, async_client: AsyncTelnyx) -> None: @parametrize async def test_method_retrieve_with_all_params(self, async_client: AsyncTelnyx) -> None: number = await async_client.reputation.numbers.retrieve( - phone_number="+16035551234", + phone_number="+19493253498", fresh=True, ) assert_matches_type(NumberRetrieveResponse, number, path=["response"]) @@ -185,7 +179,7 @@ async def test_method_retrieve_with_all_params(self, async_client: AsyncTelnyx) @parametrize async def test_raw_response_retrieve(self, async_client: AsyncTelnyx) -> None: response = await async_client.reputation.numbers.with_raw_response.retrieve( - phone_number="+16035551234", + phone_number="+19493253498", ) assert response.is_closed is True @@ -197,7 +191,7 @@ async def test_raw_response_retrieve(self, async_client: AsyncTelnyx) -> None: @parametrize async def test_streaming_response_retrieve(self, async_client: AsyncTelnyx) -> None: async with async_client.reputation.numbers.with_streaming_response.retrieve( - phone_number="+16035551234", + phone_number="+19493253498", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -219,21 +213,17 @@ async def test_path_params_retrieve(self, async_client: AsyncTelnyx) -> None: @parametrize async def test_method_list(self, async_client: AsyncTelnyx) -> None: number = await async_client.reputation.numbers.list() - assert_matches_type( - AsyncDefaultFlatPagination[ReputationPhoneNumberWithReputationData], number, path=["response"] - ) + assert_matches_type(AsyncDefaultFlatPagination[NumberListResponse], number, 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: number = await async_client.reputation.numbers.list( page_number=1, - page_size=1, + page_size=20, phone_number="+16035551234", ) - assert_matches_type( - AsyncDefaultFlatPagination[ReputationPhoneNumberWithReputationData], number, path=["response"] - ) + assert_matches_type(AsyncDefaultFlatPagination[NumberListResponse], number, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -243,9 +233,7 @@ async def test_raw_response_list(self, async_client: AsyncTelnyx) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" number = await response.parse() - assert_matches_type( - AsyncDefaultFlatPagination[ReputationPhoneNumberWithReputationData], number, path=["response"] - ) + assert_matches_type(AsyncDefaultFlatPagination[NumberListResponse], number, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -255,9 +243,7 @@ async def test_streaming_response_list(self, async_client: AsyncTelnyx) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" number = await response.parse() - assert_matches_type( - AsyncDefaultFlatPagination[ReputationPhoneNumberWithReputationData], number, path=["response"] - ) + assert_matches_type(AsyncDefaultFlatPagination[NumberListResponse], number, path=["response"]) assert cast(Any, response.is_closed) is True @@ -265,7 +251,7 @@ async def test_streaming_response_list(self, async_client: AsyncTelnyx) -> None: @parametrize async def test_method_delete(self, async_client: AsyncTelnyx) -> None: number = await async_client.reputation.numbers.delete( - "+16035551234", + "+19493253498", ) assert number is None @@ -273,7 +259,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.reputation.numbers.with_raw_response.delete( - "+16035551234", + "+19493253498", ) assert response.is_closed is True @@ -285,7 +271,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.reputation.numbers.with_streaming_response.delete( - "+16035551234", + "+19493253498", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" diff --git a/tests/api_resources/terms_of_service/test_agreements.py b/tests/api_resources/terms_of_service/test_agreements.py new file mode 100644 index 00000000..1722ab6d --- /dev/null +++ b/tests/api_resources/terms_of_service/test_agreements.py @@ -0,0 +1,185 @@ +# 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.terms_of_service import AgreementListResponse, AgreementRetrieveResponse + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestAgreements: + 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(self, client: Telnyx) -> None: + agreement = client.terms_of_service.agreements.retrieve( + "550e8400-e29b-41d4-a716-446655440000", + ) + assert_matches_type(AgreementRetrieveResponse, agreement, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_retrieve(self, client: Telnyx) -> None: + response = client.terms_of_service.agreements.with_raw_response.retrieve( + "550e8400-e29b-41d4-a716-446655440000", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + agreement = response.parse() + assert_matches_type(AgreementRetrieveResponse, agreement, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_retrieve(self, client: Telnyx) -> None: + with client.terms_of_service.agreements.with_streaming_response.retrieve( + "550e8400-e29b-41d4-a716-446655440000", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + agreement = response.parse() + assert_matches_type(AgreementRetrieveResponse, agreement, 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(self, client: Telnyx) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `agreement_id` but received ''"): + client.terms_of_service.agreements.with_raw_response.retrieve( + "", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_list(self, client: Telnyx) -> None: + agreement = client.terms_of_service.agreements.list() + assert_matches_type(SyncDefaultFlatPagination[AgreementListResponse], agreement, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_list_with_all_params(self, client: Telnyx) -> None: + agreement = client.terms_of_service.agreements.list( + page_number=1, + page_size=20, + product_type="branded_calling", + ) + assert_matches_type(SyncDefaultFlatPagination[AgreementListResponse], agreement, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_list(self, client: Telnyx) -> None: + response = client.terms_of_service.agreements.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + agreement = response.parse() + assert_matches_type(SyncDefaultFlatPagination[AgreementListResponse], agreement, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_list(self, client: Telnyx) -> None: + with client.terms_of_service.agreements.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + agreement = response.parse() + assert_matches_type(SyncDefaultFlatPagination[AgreementListResponse], agreement, path=["response"]) + + assert cast(Any, response.is_closed) is True + + +class TestAsyncAgreements: + 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(self, async_client: AsyncTelnyx) -> None: + agreement = await async_client.terms_of_service.agreements.retrieve( + "550e8400-e29b-41d4-a716-446655440000", + ) + assert_matches_type(AgreementRetrieveResponse, agreement, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_retrieve(self, async_client: AsyncTelnyx) -> None: + response = await async_client.terms_of_service.agreements.with_raw_response.retrieve( + "550e8400-e29b-41d4-a716-446655440000", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + agreement = await response.parse() + assert_matches_type(AgreementRetrieveResponse, agreement, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_retrieve(self, async_client: AsyncTelnyx) -> None: + async with async_client.terms_of_service.agreements.with_streaming_response.retrieve( + "550e8400-e29b-41d4-a716-446655440000", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + agreement = await response.parse() + assert_matches_type(AgreementRetrieveResponse, agreement, 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(self, async_client: AsyncTelnyx) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `agreement_id` but received ''"): + await async_client.terms_of_service.agreements.with_raw_response.retrieve( + "", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_list(self, async_client: AsyncTelnyx) -> None: + agreement = await async_client.terms_of_service.agreements.list() + assert_matches_type(AsyncDefaultFlatPagination[AgreementListResponse], agreement, 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: + agreement = await async_client.terms_of_service.agreements.list( + page_number=1, + page_size=20, + product_type="branded_calling", + ) + assert_matches_type(AsyncDefaultFlatPagination[AgreementListResponse], agreement, 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.terms_of_service.agreements.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + agreement = await response.parse() + assert_matches_type(AsyncDefaultFlatPagination[AgreementListResponse], agreement, 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.terms_of_service.agreements.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + agreement = await response.parse() + assert_matches_type(AsyncDefaultFlatPagination[AgreementListResponse], agreement, path=["response"]) + + assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/terms_of_service/test_branded_calling.py b/tests/api_resources/terms_of_service/test_branded_calling.py new file mode 100644 index 00000000..932fd585 --- /dev/null +++ b/tests/api_resources/terms_of_service/test_branded_calling.py @@ -0,0 +1,80 @@ +# 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.terms_of_service import BrandedCallingAgreeResponse + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestBrandedCalling: + 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_agree(self, client: Telnyx) -> None: + branded_calling = client.terms_of_service.branded_calling.agree() + assert_matches_type(BrandedCallingAgreeResponse, branded_calling, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_agree(self, client: Telnyx) -> None: + response = client.terms_of_service.branded_calling.with_raw_response.agree() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + branded_calling = response.parse() + assert_matches_type(BrandedCallingAgreeResponse, branded_calling, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_agree(self, client: Telnyx) -> None: + with client.terms_of_service.branded_calling.with_streaming_response.agree() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + branded_calling = response.parse() + assert_matches_type(BrandedCallingAgreeResponse, branded_calling, path=["response"]) + + assert cast(Any, response.is_closed) is True + + +class TestAsyncBrandedCalling: + 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_agree(self, async_client: AsyncTelnyx) -> None: + branded_calling = await async_client.terms_of_service.branded_calling.agree() + assert_matches_type(BrandedCallingAgreeResponse, branded_calling, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_agree(self, async_client: AsyncTelnyx) -> None: + response = await async_client.terms_of_service.branded_calling.with_raw_response.agree() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + branded_calling = await response.parse() + assert_matches_type(BrandedCallingAgreeResponse, branded_calling, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_agree(self, async_client: AsyncTelnyx) -> None: + async with async_client.terms_of_service.branded_calling.with_streaming_response.agree() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + branded_calling = await response.parse() + assert_matches_type(BrandedCallingAgreeResponse, branded_calling, path=["response"]) + + assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/terms_of_service/test_number_reputation.py b/tests/api_resources/terms_of_service/test_number_reputation.py index 79b859d7..08542453 100644 --- a/tests/api_resources/terms_of_service/test_number_reputation.py +++ b/tests/api_resources/terms_of_service/test_number_reputation.py @@ -8,6 +8,8 @@ import pytest from telnyx import Telnyx, AsyncTelnyx +from tests.utils import assert_matches_type +from telnyx.types.terms_of_service import NumberReputationAgreeResponse base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -19,7 +21,7 @@ class TestNumberReputation: @parametrize def test_method_agree(self, client: Telnyx) -> None: number_reputation = client.terms_of_service.number_reputation.agree() - assert number_reputation is None + assert_matches_type(NumberReputationAgreeResponse, number_reputation, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -29,7 +31,7 @@ def test_raw_response_agree(self, client: Telnyx) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" number_reputation = response.parse() - assert number_reputation is None + assert_matches_type(NumberReputationAgreeResponse, number_reputation, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -39,7 +41,7 @@ def test_streaming_response_agree(self, client: Telnyx) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" number_reputation = response.parse() - assert number_reputation is None + assert_matches_type(NumberReputationAgreeResponse, number_reputation, path=["response"]) assert cast(Any, response.is_closed) is True @@ -53,7 +55,7 @@ class TestAsyncNumberReputation: @parametrize async def test_method_agree(self, async_client: AsyncTelnyx) -> None: number_reputation = await async_client.terms_of_service.number_reputation.agree() - assert number_reputation is None + assert_matches_type(NumberReputationAgreeResponse, number_reputation, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -63,7 +65,7 @@ async def test_raw_response_agree(self, async_client: AsyncTelnyx) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" number_reputation = await response.parse() - assert number_reputation is None + assert_matches_type(NumberReputationAgreeResponse, number_reputation, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -73,6 +75,6 @@ async def test_streaming_response_agree(self, async_client: AsyncTelnyx) -> None assert response.http_request.headers.get("X-Stainless-Lang") == "python" number_reputation = await response.parse() - assert number_reputation is None + assert_matches_type(NumberReputationAgreeResponse, number_reputation, path=["response"]) assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/test_call_reasons.py b/tests/api_resources/test_call_reasons.py new file mode 100644 index 00000000..09c9fa78 --- /dev/null +++ b/tests/api_resources/test_call_reasons.py @@ -0,0 +1,170 @@ +# 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 ( + CallReasonListResponse, + CallReasonValidateResponse, +) +from telnyx.pagination import SyncDefaultFlatPagination, AsyncDefaultFlatPagination + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestCallReasons: + 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: + call_reason = client.call_reasons.list() + assert_matches_type(SyncDefaultFlatPagination[CallReasonListResponse], call_reason, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_list_with_all_params(self, client: Telnyx) -> None: + call_reason = client.call_reasons.list( + page_number=1, + page_size=100, + ) + assert_matches_type(SyncDefaultFlatPagination[CallReasonListResponse], call_reason, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_list(self, client: Telnyx) -> None: + response = client.call_reasons.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + call_reason = response.parse() + assert_matches_type(SyncDefaultFlatPagination[CallReasonListResponse], call_reason, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_list(self, client: Telnyx) -> None: + with client.call_reasons.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + call_reason = response.parse() + assert_matches_type(SyncDefaultFlatPagination[CallReasonListResponse], call_reason, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_validate(self, client: Telnyx) -> None: + call_reason = client.call_reasons.validate( + body=["Appointment reminders", "Billing inquiries"], + ) + assert_matches_type(CallReasonValidateResponse, call_reason, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_validate(self, client: Telnyx) -> None: + response = client.call_reasons.with_raw_response.validate( + body=["Appointment reminders", "Billing inquiries"], + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + call_reason = response.parse() + assert_matches_type(CallReasonValidateResponse, call_reason, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_validate(self, client: Telnyx) -> None: + with client.call_reasons.with_streaming_response.validate( + body=["Appointment reminders", "Billing inquiries"], + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + call_reason = response.parse() + assert_matches_type(CallReasonValidateResponse, call_reason, path=["response"]) + + assert cast(Any, response.is_closed) is True + + +class TestAsyncCallReasons: + 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: + call_reason = await async_client.call_reasons.list() + assert_matches_type(AsyncDefaultFlatPagination[CallReasonListResponse], call_reason, 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: + call_reason = await async_client.call_reasons.list( + page_number=1, + page_size=100, + ) + assert_matches_type(AsyncDefaultFlatPagination[CallReasonListResponse], call_reason, 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.call_reasons.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + call_reason = await response.parse() + assert_matches_type(AsyncDefaultFlatPagination[CallReasonListResponse], call_reason, 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.call_reasons.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + call_reason = await response.parse() + assert_matches_type(AsyncDefaultFlatPagination[CallReasonListResponse], call_reason, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_validate(self, async_client: AsyncTelnyx) -> None: + call_reason = await async_client.call_reasons.validate( + body=["Appointment reminders", "Billing inquiries"], + ) + assert_matches_type(CallReasonValidateResponse, call_reason, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_validate(self, async_client: AsyncTelnyx) -> None: + response = await async_client.call_reasons.with_raw_response.validate( + body=["Appointment reminders", "Billing inquiries"], + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + call_reason = await response.parse() + assert_matches_type(CallReasonValidateResponse, call_reason, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_validate(self, async_client: AsyncTelnyx) -> None: + async with async_client.call_reasons.with_streaming_response.validate( + body=["Appointment reminders", "Billing inquiries"], + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + call_reason = await response.parse() + assert_matches_type(CallReasonValidateResponse, call_reason, path=["response"]) + + assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/test_dir.py b/tests/api_resources/test_dir.py new file mode 100644 index 00000000..93a88091 --- /dev/null +++ b/tests/api_resources/test_dir.py @@ -0,0 +1,814 @@ +# 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 ( + DirListResponse, + DirSubmitResponse, + DirUpdateResponse, + DirRetrieveResponse, + DirListDocumentTypesResponse, + DirUpdateInfringementResponse, + DirListInfringementClaimsResponse, +) +from telnyx._utils import parse_datetime +from telnyx.pagination import SyncDefaultFlatPagination, AsyncDefaultFlatPagination + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestDir: + 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(self, client: Telnyx) -> None: + dir = client.dir.retrieve( + "16635d38-75a6-4481-82e8-69af60e05011", + ) + assert_matches_type(DirRetrieveResponse, dir, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_retrieve(self, client: Telnyx) -> None: + response = client.dir.with_raw_response.retrieve( + "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(DirRetrieveResponse, dir, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_retrieve(self, client: Telnyx) -> None: + with client.dir.with_streaming_response.retrieve( + "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(DirRetrieveResponse, 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(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( + "", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_update(self, client: Telnyx) -> None: + dir = client.dir.update( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + ) + assert_matches_type(DirUpdateResponse, dir, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_update_with_all_params(self, client: Telnyx) -> None: + dir = client.dir.update( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + authorizer_email="dev@stainless.com", + authorizer_name="authorizer_name", + call_reasons=["Appointment reminders", "Billing inquiries", "Lab results"], + display_name="Acme Plumbing & Wellness", + logo_url="https://acmeplumbing.example.com/logo-v2-256.bmp", + reselling=True, + ) + assert_matches_type(DirUpdateResponse, dir, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_update(self, client: Telnyx) -> None: + response = client.dir.with_raw_response.update( + 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(DirUpdateResponse, dir, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_update(self, client: Telnyx) -> None: + with client.dir.with_streaming_response.update( + 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(DirUpdateResponse, 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_update(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.update( + dir_id="", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_list(self, client: Telnyx) -> None: + dir = client.dir.list() + assert_matches_type(SyncDefaultFlatPagination[DirListResponse], dir, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_list_with_all_params(self, client: Telnyx) -> None: + dir = client.dir.list( + enterprise_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + filter_expiring_at_gte=parse_datetime("2019-12-27T18:11:19.117Z"), + filter_expiring_at_lte=parse_datetime("2019-12-27T18:11:19.117Z"), + page_number=1, + page_size=20, + search="search", + sort="created_at", + status="draft", + ) + assert_matches_type(SyncDefaultFlatPagination[DirListResponse], dir, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_list(self, client: Telnyx) -> None: + response = client.dir.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + dir = response.parse() + assert_matches_type(SyncDefaultFlatPagination[DirListResponse], dir, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_list(self, client: Telnyx) -> None: + with client.dir.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + dir = response.parse() + assert_matches_type(SyncDefaultFlatPagination[DirListResponse], dir, 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: + dir = client.dir.delete( + "16635d38-75a6-4481-82e8-69af60e05011", + ) + assert dir is None + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_delete(self, client: Telnyx) -> None: + response = client.dir.with_raw_response.delete( + "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 dir is None + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_delete(self, client: Telnyx) -> None: + with client.dir.with_streaming_response.delete( + "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 dir 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 `dir_id` but received ''"): + client.dir.with_raw_response.delete( + "", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_list_document_types(self, client: Telnyx) -> None: + dir = client.dir.list_document_types() + assert_matches_type(DirListDocumentTypesResponse, dir, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_list_document_types(self, client: Telnyx) -> None: + response = client.dir.with_raw_response.list_document_types() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + dir = response.parse() + assert_matches_type(DirListDocumentTypesResponse, dir, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_list_document_types(self, client: Telnyx) -> None: + with client.dir.with_streaming_response.list_document_types() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + dir = response.parse() + assert_matches_type(DirListDocumentTypesResponse, dir, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_list_infringement_claims(self, client: Telnyx) -> None: + dir = client.dir.list_infringement_claims( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + ) + assert_matches_type(SyncDefaultFlatPagination[DirListInfringementClaimsResponse], dir, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_list_infringement_claims_with_all_params(self, client: Telnyx) -> None: + dir = client.dir.list_infringement_claims( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + page_number=1, + page_size=20, + ) + assert_matches_type(SyncDefaultFlatPagination[DirListInfringementClaimsResponse], dir, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_list_infringement_claims(self, client: Telnyx) -> None: + response = client.dir.with_raw_response.list_infringement_claims( + 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(SyncDefaultFlatPagination[DirListInfringementClaimsResponse], dir, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_list_infringement_claims(self, client: Telnyx) -> None: + with client.dir.with_streaming_response.list_infringement_claims( + 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(SyncDefaultFlatPagination[DirListInfringementClaimsResponse], 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_list_infringement_claims(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.list_infringement_claims( + dir_id="", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_submit(self, client: Telnyx) -> None: + dir = client.dir.submit( + "16635d38-75a6-4481-82e8-69af60e05011", + ) + assert_matches_type(DirSubmitResponse, dir, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_submit(self, client: Telnyx) -> None: + response = client.dir.with_raw_response.submit( + "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(DirSubmitResponse, dir, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_submit(self, client: Telnyx) -> None: + with client.dir.with_streaming_response.submit( + "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(DirSubmitResponse, 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_submit(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.submit( + "", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_update_infringement(self, client: Telnyx) -> None: + dir = client.dir.update_infringement( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + certify_brand_is_accurate=True, + certify_ip_ownership=True, + certify_no_infringement=True, + certify_no_shaft_content=True, + infringement_resolution_notes="Updated the display name to remove the disputed mark and re-uploaded the authorization.", + ) + assert_matches_type(DirUpdateInfringementResponse, dir, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_update_infringement_with_all_params(self, client: Telnyx) -> None: + dir = client.dir.update_infringement( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + certify_brand_is_accurate=True, + certify_ip_ownership=True, + certify_no_infringement=True, + certify_no_shaft_content=True, + infringement_resolution_notes="Updated the display name to remove the disputed mark and re-uploaded the authorization.", + call_reasons=["string"], + display_name="x", + documents=[ + { + "document_id": "2a7e8337-e803-4057-a4ae-26c40eb0bc6c", + "document_type": "business_registration", + "description": "Certificate of incorporation.", + } + ], + logo_url="logo_url", + ) + assert_matches_type(DirUpdateInfringementResponse, dir, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_update_infringement(self, client: Telnyx) -> None: + response = client.dir.with_raw_response.update_infringement( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + certify_brand_is_accurate=True, + certify_ip_ownership=True, + certify_no_infringement=True, + certify_no_shaft_content=True, + infringement_resolution_notes="Updated the display name to remove the disputed mark and re-uploaded the authorization.", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + dir = response.parse() + assert_matches_type(DirUpdateInfringementResponse, dir, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_update_infringement(self, client: Telnyx) -> None: + with client.dir.with_streaming_response.update_infringement( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + certify_brand_is_accurate=True, + certify_ip_ownership=True, + certify_no_infringement=True, + certify_no_shaft_content=True, + infringement_resolution_notes="Updated the display name to remove the disputed mark and re-uploaded the authorization.", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + dir = response.parse() + assert_matches_type(DirUpdateInfringementResponse, 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_update_infringement(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.update_infringement( + dir_id="", + certify_brand_is_accurate=True, + certify_ip_ownership=True, + certify_no_infringement=True, + certify_no_shaft_content=True, + infringement_resolution_notes="Updated the display name to remove the disputed mark and re-uploaded the authorization.", + ) + + +class TestAsyncDir: + 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(self, async_client: AsyncTelnyx) -> None: + dir = await async_client.dir.retrieve( + "16635d38-75a6-4481-82e8-69af60e05011", + ) + assert_matches_type(DirRetrieveResponse, dir, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_retrieve(self, async_client: AsyncTelnyx) -> None: + response = await async_client.dir.with_raw_response.retrieve( + "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(DirRetrieveResponse, dir, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_retrieve(self, async_client: AsyncTelnyx) -> None: + async with async_client.dir.with_streaming_response.retrieve( + "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(DirRetrieveResponse, 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(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( + "", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_update(self, async_client: AsyncTelnyx) -> None: + dir = await async_client.dir.update( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + ) + assert_matches_type(DirUpdateResponse, dir, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_update_with_all_params(self, async_client: AsyncTelnyx) -> None: + dir = await async_client.dir.update( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + authorizer_email="dev@stainless.com", + authorizer_name="authorizer_name", + call_reasons=["Appointment reminders", "Billing inquiries", "Lab results"], + display_name="Acme Plumbing & Wellness", + logo_url="https://acmeplumbing.example.com/logo-v2-256.bmp", + reselling=True, + ) + assert_matches_type(DirUpdateResponse, dir, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_update(self, async_client: AsyncTelnyx) -> None: + response = await async_client.dir.with_raw_response.update( + 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(DirUpdateResponse, dir, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_update(self, async_client: AsyncTelnyx) -> None: + async with async_client.dir.with_streaming_response.update( + 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(DirUpdateResponse, 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_update(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.update( + dir_id="", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_list(self, async_client: AsyncTelnyx) -> None: + dir = await async_client.dir.list() + assert_matches_type(AsyncDefaultFlatPagination[DirListResponse], dir, 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: + dir = await async_client.dir.list( + enterprise_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + filter_expiring_at_gte=parse_datetime("2019-12-27T18:11:19.117Z"), + filter_expiring_at_lte=parse_datetime("2019-12-27T18:11:19.117Z"), + page_number=1, + page_size=20, + search="search", + sort="created_at", + status="draft", + ) + assert_matches_type(AsyncDefaultFlatPagination[DirListResponse], dir, 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.dir.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + dir = await response.parse() + assert_matches_type(AsyncDefaultFlatPagination[DirListResponse], dir, 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.dir.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + dir = await response.parse() + assert_matches_type(AsyncDefaultFlatPagination[DirListResponse], dir, 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: + dir = await async_client.dir.delete( + "16635d38-75a6-4481-82e8-69af60e05011", + ) + assert dir 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.dir.with_raw_response.delete( + "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 dir 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.dir.with_streaming_response.delete( + "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 dir 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 `dir_id` but received ''"): + await async_client.dir.with_raw_response.delete( + "", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_list_document_types(self, async_client: AsyncTelnyx) -> None: + dir = await async_client.dir.list_document_types() + assert_matches_type(DirListDocumentTypesResponse, dir, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_list_document_types(self, async_client: AsyncTelnyx) -> None: + response = await async_client.dir.with_raw_response.list_document_types() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + dir = await response.parse() + assert_matches_type(DirListDocumentTypesResponse, dir, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_list_document_types(self, async_client: AsyncTelnyx) -> None: + async with async_client.dir.with_streaming_response.list_document_types() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + dir = await response.parse() + assert_matches_type(DirListDocumentTypesResponse, dir, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_list_infringement_claims(self, async_client: AsyncTelnyx) -> None: + dir = await async_client.dir.list_infringement_claims( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + ) + assert_matches_type(AsyncDefaultFlatPagination[DirListInfringementClaimsResponse], dir, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_list_infringement_claims_with_all_params(self, async_client: AsyncTelnyx) -> None: + dir = await async_client.dir.list_infringement_claims( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + page_number=1, + page_size=20, + ) + assert_matches_type(AsyncDefaultFlatPagination[DirListInfringementClaimsResponse], dir, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_list_infringement_claims(self, async_client: AsyncTelnyx) -> None: + response = await async_client.dir.with_raw_response.list_infringement_claims( + 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(AsyncDefaultFlatPagination[DirListInfringementClaimsResponse], dir, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_list_infringement_claims(self, async_client: AsyncTelnyx) -> None: + async with async_client.dir.with_streaming_response.list_infringement_claims( + 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(AsyncDefaultFlatPagination[DirListInfringementClaimsResponse], 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_list_infringement_claims(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.list_infringement_claims( + dir_id="", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_submit(self, async_client: AsyncTelnyx) -> None: + dir = await async_client.dir.submit( + "16635d38-75a6-4481-82e8-69af60e05011", + ) + assert_matches_type(DirSubmitResponse, dir, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_submit(self, async_client: AsyncTelnyx) -> None: + response = await async_client.dir.with_raw_response.submit( + "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(DirSubmitResponse, dir, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_submit(self, async_client: AsyncTelnyx) -> None: + async with async_client.dir.with_streaming_response.submit( + "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(DirSubmitResponse, 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_submit(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.submit( + "", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_update_infringement(self, async_client: AsyncTelnyx) -> None: + dir = await async_client.dir.update_infringement( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + certify_brand_is_accurate=True, + certify_ip_ownership=True, + certify_no_infringement=True, + certify_no_shaft_content=True, + infringement_resolution_notes="Updated the display name to remove the disputed mark and re-uploaded the authorization.", + ) + assert_matches_type(DirUpdateInfringementResponse, dir, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_update_infringement_with_all_params(self, async_client: AsyncTelnyx) -> None: + dir = await async_client.dir.update_infringement( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + certify_brand_is_accurate=True, + certify_ip_ownership=True, + certify_no_infringement=True, + certify_no_shaft_content=True, + infringement_resolution_notes="Updated the display name to remove the disputed mark and re-uploaded the authorization.", + call_reasons=["string"], + display_name="x", + documents=[ + { + "document_id": "2a7e8337-e803-4057-a4ae-26c40eb0bc6c", + "document_type": "business_registration", + "description": "Certificate of incorporation.", + } + ], + logo_url="logo_url", + ) + assert_matches_type(DirUpdateInfringementResponse, dir, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_update_infringement(self, async_client: AsyncTelnyx) -> None: + response = await async_client.dir.with_raw_response.update_infringement( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + certify_brand_is_accurate=True, + certify_ip_ownership=True, + certify_no_infringement=True, + certify_no_shaft_content=True, + infringement_resolution_notes="Updated the display name to remove the disputed mark and re-uploaded the authorization.", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + dir = await response.parse() + assert_matches_type(DirUpdateInfringementResponse, dir, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_update_infringement(self, async_client: AsyncTelnyx) -> None: + async with async_client.dir.with_streaming_response.update_infringement( + dir_id="16635d38-75a6-4481-82e8-69af60e05011", + certify_brand_is_accurate=True, + certify_ip_ownership=True, + certify_no_infringement=True, + certify_no_shaft_content=True, + infringement_resolution_notes="Updated the display name to remove the disputed mark and re-uploaded the authorization.", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + dir = await response.parse() + assert_matches_type(DirUpdateInfringementResponse, 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_update_infringement(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.update_infringement( + dir_id="", + certify_brand_is_accurate=True, + certify_ip_ownership=True, + certify_no_infringement=True, + certify_no_shaft_content=True, + infringement_resolution_notes="Updated the display name to remove the disputed mark and re-uploaded the authorization.", + ) diff --git a/tests/api_resources/test_enterprises.py b/tests/api_resources/test_enterprises.py index 63971370..bf7c4e54 100644 --- a/tests/api_resources/test_enterprises.py +++ b/tests/api_resources/test_enterprises.py @@ -14,6 +14,7 @@ EnterpriseCreateResponse, EnterpriseUpdateResponse, EnterpriseRetrieveResponse, + EnterpriseActivateBrandedCallingResponse, ) from telnyx.pagination import SyncDefaultFlatPagination, AsyncDefaultFlatPagination @@ -28,41 +29,42 @@ class TestEnterprises: def test_method_create(self, client: Telnyx) -> None: enterprise = client.enterprises.create( billing_address={ - "administrative_area": "Illinois", + "administrative_area": "IL", "city": "Chicago", - "country": "United States", + "country": "US", "postal_code": "60601", - "street_address": "123 Main St", + "street_address": "100 Main St", }, billing_contact={ - "email": "billing@acme.com", - "first_name": "John", - "last_name": "Doe", - "phone_number": "15551234568", + "email": "billing@run065.example.com", + "first_name": "Alex", + "last_name": "Bill", + "phone_number": "+13125550001", }, country_code="US", - doing_business_as="Acme", + doing_business_as="Run 065 Debug", fein="12-3456789", industry="technology", - legal_name="Acme Corp Inc.", + jurisdiction_of_incorporation="Delaware", + legal_name="Run 065 Debug Co", number_of_employees="51-200", organization_contact={ - "email": "jane.smith@acme.com", - "first_name": "Jane", - "job_title": "VP of Engineering", - "last_name": "Smith", - "phone": "+16035551234", + "email": "org@run065.example.com", + "first_name": "Sam", + "job_title": "Compliance Lead", + "last_name": "Org", + "phone_number": "+13125550000", }, - organization_legal_type="corporation", + organization_legal_type="llc", organization_physical_address={ - "administrative_area": "Illinois", + "administrative_area": "IL", "city": "Chicago", - "country": "United States", + "country": "US", "postal_code": "60601", - "street_address": "123 Main St", + "street_address": "100 Main St", }, organization_type="commercial", - website="https://acme.com", + website="https://run065.example.com", ) assert_matches_type(EnterpriseCreateResponse, enterprise, path=["response"]) @@ -71,47 +73,48 @@ def test_method_create(self, client: Telnyx) -> None: def test_method_create_with_all_params(self, client: Telnyx) -> None: enterprise = client.enterprises.create( billing_address={ - "administrative_area": "Illinois", + "administrative_area": "IL", "city": "Chicago", - "country": "United States", + "country": "US", "postal_code": "60601", - "street_address": "123 Main St", - "extended_address": "Suite 400", + "street_address": "100 Main St", + "extended_address": "Suite 504", }, billing_contact={ - "email": "billing@acme.com", - "first_name": "John", - "last_name": "Doe", - "phone_number": "15551234568", + "email": "billing@run065.example.com", + "first_name": "Alex", + "last_name": "Bill", + "phone_number": "+13125550001", }, country_code="US", - doing_business_as="Acme", + doing_business_as="Run 065 Debug", fein="12-3456789", industry="technology", - legal_name="Acme Corp Inc.", + jurisdiction_of_incorporation="Delaware", + legal_name="Run 065 Debug Co", number_of_employees="51-200", organization_contact={ - "email": "jane.smith@acme.com", - "first_name": "Jane", - "job_title": "VP of Engineering", - "last_name": "Smith", - "phone": "+16035551234", + "email": "org@run065.example.com", + "first_name": "Sam", + "job_title": "Compliance Lead", + "last_name": "Org", + "phone_number": "+13125550000", }, - organization_legal_type="corporation", + organization_legal_type="llc", organization_physical_address={ - "administrative_area": "Illinois", + "administrative_area": "IL", "city": "Chicago", - "country": "United States", + "country": "US", "postal_code": "60601", - "street_address": "123 Main St", - "extended_address": "Suite 400", + "street_address": "100 Main St", + "extended_address": "Suite 504", }, organization_type="commercial", - website="https://acme.com", + website="https://run065.example.com", corporate_registration_number="corporate_registration_number", - customer_reference="customer_reference", + customer_reference="internal-id-12345", dun_bradstreet_number="dun_bradstreet_number", - primary_business_domain_sic_code="7372", + primary_business_domain_sic_code="primary_business_domain_sic_code", professional_license_number="professional_license_number", role_type="enterprise", ) @@ -122,41 +125,42 @@ def test_method_create_with_all_params(self, client: Telnyx) -> None: def test_raw_response_create(self, client: Telnyx) -> None: response = client.enterprises.with_raw_response.create( billing_address={ - "administrative_area": "Illinois", + "administrative_area": "IL", "city": "Chicago", - "country": "United States", + "country": "US", "postal_code": "60601", - "street_address": "123 Main St", + "street_address": "100 Main St", }, billing_contact={ - "email": "billing@acme.com", - "first_name": "John", - "last_name": "Doe", - "phone_number": "15551234568", + "email": "billing@run065.example.com", + "first_name": "Alex", + "last_name": "Bill", + "phone_number": "+13125550001", }, country_code="US", - doing_business_as="Acme", + doing_business_as="Run 065 Debug", fein="12-3456789", industry="technology", - legal_name="Acme Corp Inc.", + jurisdiction_of_incorporation="Delaware", + legal_name="Run 065 Debug Co", number_of_employees="51-200", organization_contact={ - "email": "jane.smith@acme.com", - "first_name": "Jane", - "job_title": "VP of Engineering", - "last_name": "Smith", - "phone": "+16035551234", + "email": "org@run065.example.com", + "first_name": "Sam", + "job_title": "Compliance Lead", + "last_name": "Org", + "phone_number": "+13125550000", }, - organization_legal_type="corporation", + organization_legal_type="llc", organization_physical_address={ - "administrative_area": "Illinois", + "administrative_area": "IL", "city": "Chicago", - "country": "United States", + "country": "US", "postal_code": "60601", - "street_address": "123 Main St", + "street_address": "100 Main St", }, organization_type="commercial", - website="https://acme.com", + website="https://run065.example.com", ) assert response.is_closed is True @@ -169,41 +173,42 @@ def test_raw_response_create(self, client: Telnyx) -> None: def test_streaming_response_create(self, client: Telnyx) -> None: with client.enterprises.with_streaming_response.create( billing_address={ - "administrative_area": "Illinois", + "administrative_area": "IL", "city": "Chicago", - "country": "United States", + "country": "US", "postal_code": "60601", - "street_address": "123 Main St", + "street_address": "100 Main St", }, billing_contact={ - "email": "billing@acme.com", - "first_name": "John", - "last_name": "Doe", - "phone_number": "15551234568", + "email": "billing@run065.example.com", + "first_name": "Alex", + "last_name": "Bill", + "phone_number": "+13125550001", }, country_code="US", - doing_business_as="Acme", + doing_business_as="Run 065 Debug", fein="12-3456789", industry="technology", - legal_name="Acme Corp Inc.", + jurisdiction_of_incorporation="Delaware", + legal_name="Run 065 Debug Co", number_of_employees="51-200", organization_contact={ - "email": "jane.smith@acme.com", - "first_name": "Jane", - "job_title": "VP of Engineering", - "last_name": "Smith", - "phone": "+16035551234", + "email": "org@run065.example.com", + "first_name": "Sam", + "job_title": "Compliance Lead", + "last_name": "Org", + "phone_number": "+13125550000", }, - organization_legal_type="corporation", + organization_legal_type="llc", organization_physical_address={ - "administrative_area": "Illinois", + "administrative_area": "IL", "city": "Chicago", - "country": "United States", + "country": "US", "postal_code": "60601", - "street_address": "123 Main St", + "street_address": "100 Main St", }, organization_type="commercial", - website="https://acme.com", + website="https://run065.example.com", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -217,7 +222,7 @@ def test_streaming_response_create(self, client: Telnyx) -> None: @parametrize def test_method_retrieve(self, client: Telnyx) -> None: enterprise = client.enterprises.retrieve( - "6a09cdc3-8948-47f0-aa62-74ac943d6c58", + "4a6192a4-573d-446d-b3ce-aff9117272a6", ) assert_matches_type(EnterpriseRetrieveResponse, enterprise, path=["response"]) @@ -225,7 +230,7 @@ def test_method_retrieve(self, client: Telnyx) -> None: @parametrize def test_raw_response_retrieve(self, client: Telnyx) -> None: response = client.enterprises.with_raw_response.retrieve( - "6a09cdc3-8948-47f0-aa62-74ac943d6c58", + "4a6192a4-573d-446d-b3ce-aff9117272a6", ) assert response.is_closed is True @@ -237,7 +242,7 @@ def test_raw_response_retrieve(self, client: Telnyx) -> None: @parametrize def test_streaming_response_retrieve(self, client: Telnyx) -> None: with client.enterprises.with_streaming_response.retrieve( - "6a09cdc3-8948-47f0-aa62-74ac943d6c58", + "4a6192a4-573d-446d-b3ce-aff9117272a6", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -259,7 +264,7 @@ def test_path_params_retrieve(self, client: Telnyx) -> None: @parametrize def test_method_update(self, client: Telnyx) -> None: enterprise = client.enterprises.update( - enterprise_id="6a09cdc3-8948-47f0-aa62-74ac943d6c58", + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", ) assert_matches_type(EnterpriseUpdateResponse, enterprise, path=["response"]) @@ -267,48 +272,49 @@ def test_method_update(self, client: Telnyx) -> None: @parametrize def test_method_update_with_all_params(self, client: Telnyx) -> None: enterprise = client.enterprises.update( - enterprise_id="6a09cdc3-8948-47f0-aa62-74ac943d6c58", + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", billing_address={ - "administrative_area": "Illinois", + "administrative_area": "IL", "city": "Chicago", - "country": "United States", + "country": "US", "postal_code": "60601", - "street_address": "123 Main St", - "extended_address": "Suite 400", + "street_address": "100 Main St", + "extended_address": "Suite 504", }, billing_contact={ - "email": "billing@acme.com", - "first_name": "John", - "last_name": "Doe", - "phone_number": "15551234568", + "email": "billing@acmeplumbing.example.com", + "first_name": "Alex", + "last_name": "Bill", + "phone_number": "+13125550001", }, corporate_registration_number="corporate_registration_number", - customer_reference="customer_reference", - doing_business_as="doing_business_as", + customer_reference="internal-ref-2026Q2", + doing_business_as="Acme Plumbing", dun_bradstreet_number="dun_bradstreet_number", - fein="fein", - industry="industry", - legal_name="xxx", - number_of_employees="1-10", + fein="12-3456789", + industry="business", + jurisdiction_of_incorporation="Delaware", + legal_name="Acme Plumbing LLC", + number_of_employees="51-200", organization_contact={ - "email": "jane.smith@acme.com", - "first_name": "Jane", - "job_title": "VP of Engineering", - "last_name": "Smith", - "phone": "+16035551234", + "email": "sam@acmeplumbing.example.com", + "first_name": "Sam", + "job_title": "Compliance Lead", + "last_name": "Owner", + "phone_number": "+13125550000", }, - organization_legal_type="corporation", + organization_legal_type="llc", organization_physical_address={ - "administrative_area": "Illinois", + "administrative_area": "IL", "city": "Chicago", - "country": "United States", + "country": "US", "postal_code": "60601", - "street_address": "123 Main St", - "extended_address": "Suite 400", + "street_address": "100 Main St", + "extended_address": "Suite 504", }, primary_business_domain_sic_code="primary_business_domain_sic_code", professional_license_number="professional_license_number", - website="website", + website="https://acmeplumbing.example.com", ) assert_matches_type(EnterpriseUpdateResponse, enterprise, path=["response"]) @@ -316,7 +322,7 @@ def test_method_update_with_all_params(self, client: Telnyx) -> None: @parametrize def test_raw_response_update(self, client: Telnyx) -> None: response = client.enterprises.with_raw_response.update( - enterprise_id="6a09cdc3-8948-47f0-aa62-74ac943d6c58", + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", ) assert response.is_closed is True @@ -328,7 +334,7 @@ def test_raw_response_update(self, client: Telnyx) -> None: @parametrize def test_streaming_response_update(self, client: Telnyx) -> None: with client.enterprises.with_streaming_response.update( - enterprise_id="6a09cdc3-8948-47f0-aa62-74ac943d6c58", + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -358,7 +364,7 @@ def test_method_list_with_all_params(self, client: Telnyx) -> None: enterprise = client.enterprises.list( legal_name="Acme", page_number=1, - page_size=1, + page_size=10, ) assert_matches_type(SyncDefaultFlatPagination[EnterprisePublic], enterprise, path=["response"]) @@ -388,7 +394,7 @@ def test_streaming_response_list(self, client: Telnyx) -> None: @parametrize def test_method_delete(self, client: Telnyx) -> None: enterprise = client.enterprises.delete( - "6a09cdc3-8948-47f0-aa62-74ac943d6c58", + "4a6192a4-573d-446d-b3ce-aff9117272a6", ) assert enterprise is None @@ -396,7 +402,7 @@ def test_method_delete(self, client: Telnyx) -> None: @parametrize def test_raw_response_delete(self, client: Telnyx) -> None: response = client.enterprises.with_raw_response.delete( - "6a09cdc3-8948-47f0-aa62-74ac943d6c58", + "4a6192a4-573d-446d-b3ce-aff9117272a6", ) assert response.is_closed is True @@ -408,7 +414,7 @@ def test_raw_response_delete(self, client: Telnyx) -> None: @parametrize def test_streaming_response_delete(self, client: Telnyx) -> None: with client.enterprises.with_streaming_response.delete( - "6a09cdc3-8948-47f0-aa62-74ac943d6c58", + "4a6192a4-573d-446d-b3ce-aff9117272a6", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -426,6 +432,48 @@ def test_path_params_delete(self, client: Telnyx) -> None: "", ) + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_activate_branded_calling(self, client: Telnyx) -> None: + enterprise = client.enterprises.activate_branded_calling( + "4a6192a4-573d-446d-b3ce-aff9117272a6", + ) + assert_matches_type(EnterpriseActivateBrandedCallingResponse, enterprise, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_activate_branded_calling(self, client: Telnyx) -> None: + response = client.enterprises.with_raw_response.activate_branded_calling( + "4a6192a4-573d-446d-b3ce-aff9117272a6", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + enterprise = response.parse() + assert_matches_type(EnterpriseActivateBrandedCallingResponse, enterprise, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_activate_branded_calling(self, client: Telnyx) -> None: + with client.enterprises.with_streaming_response.activate_branded_calling( + "4a6192a4-573d-446d-b3ce-aff9117272a6", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + enterprise = response.parse() + assert_matches_type(EnterpriseActivateBrandedCallingResponse, enterprise, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_path_params_activate_branded_calling(self, client: Telnyx) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `enterprise_id` but received ''"): + client.enterprises.with_raw_response.activate_branded_calling( + "", + ) + class TestAsyncEnterprises: parametrize = pytest.mark.parametrize( @@ -437,41 +485,42 @@ class TestAsyncEnterprises: async def test_method_create(self, async_client: AsyncTelnyx) -> None: enterprise = await async_client.enterprises.create( billing_address={ - "administrative_area": "Illinois", + "administrative_area": "IL", "city": "Chicago", - "country": "United States", + "country": "US", "postal_code": "60601", - "street_address": "123 Main St", + "street_address": "100 Main St", }, billing_contact={ - "email": "billing@acme.com", - "first_name": "John", - "last_name": "Doe", - "phone_number": "15551234568", + "email": "billing@run065.example.com", + "first_name": "Alex", + "last_name": "Bill", + "phone_number": "+13125550001", }, country_code="US", - doing_business_as="Acme", + doing_business_as="Run 065 Debug", fein="12-3456789", industry="technology", - legal_name="Acme Corp Inc.", + jurisdiction_of_incorporation="Delaware", + legal_name="Run 065 Debug Co", number_of_employees="51-200", organization_contact={ - "email": "jane.smith@acme.com", - "first_name": "Jane", - "job_title": "VP of Engineering", - "last_name": "Smith", - "phone": "+16035551234", + "email": "org@run065.example.com", + "first_name": "Sam", + "job_title": "Compliance Lead", + "last_name": "Org", + "phone_number": "+13125550000", }, - organization_legal_type="corporation", + organization_legal_type="llc", organization_physical_address={ - "administrative_area": "Illinois", + "administrative_area": "IL", "city": "Chicago", - "country": "United States", + "country": "US", "postal_code": "60601", - "street_address": "123 Main St", + "street_address": "100 Main St", }, organization_type="commercial", - website="https://acme.com", + website="https://run065.example.com", ) assert_matches_type(EnterpriseCreateResponse, enterprise, path=["response"]) @@ -480,47 +529,48 @@ async def test_method_create(self, async_client: AsyncTelnyx) -> None: async def test_method_create_with_all_params(self, async_client: AsyncTelnyx) -> None: enterprise = await async_client.enterprises.create( billing_address={ - "administrative_area": "Illinois", + "administrative_area": "IL", "city": "Chicago", - "country": "United States", + "country": "US", "postal_code": "60601", - "street_address": "123 Main St", - "extended_address": "Suite 400", + "street_address": "100 Main St", + "extended_address": "Suite 504", }, billing_contact={ - "email": "billing@acme.com", - "first_name": "John", - "last_name": "Doe", - "phone_number": "15551234568", + "email": "billing@run065.example.com", + "first_name": "Alex", + "last_name": "Bill", + "phone_number": "+13125550001", }, country_code="US", - doing_business_as="Acme", + doing_business_as="Run 065 Debug", fein="12-3456789", industry="technology", - legal_name="Acme Corp Inc.", + jurisdiction_of_incorporation="Delaware", + legal_name="Run 065 Debug Co", number_of_employees="51-200", organization_contact={ - "email": "jane.smith@acme.com", - "first_name": "Jane", - "job_title": "VP of Engineering", - "last_name": "Smith", - "phone": "+16035551234", + "email": "org@run065.example.com", + "first_name": "Sam", + "job_title": "Compliance Lead", + "last_name": "Org", + "phone_number": "+13125550000", }, - organization_legal_type="corporation", + organization_legal_type="llc", organization_physical_address={ - "administrative_area": "Illinois", + "administrative_area": "IL", "city": "Chicago", - "country": "United States", + "country": "US", "postal_code": "60601", - "street_address": "123 Main St", - "extended_address": "Suite 400", + "street_address": "100 Main St", + "extended_address": "Suite 504", }, organization_type="commercial", - website="https://acme.com", + website="https://run065.example.com", corporate_registration_number="corporate_registration_number", - customer_reference="customer_reference", + customer_reference="internal-id-12345", dun_bradstreet_number="dun_bradstreet_number", - primary_business_domain_sic_code="7372", + primary_business_domain_sic_code="primary_business_domain_sic_code", professional_license_number="professional_license_number", role_type="enterprise", ) @@ -531,41 +581,42 @@ async def test_method_create_with_all_params(self, async_client: AsyncTelnyx) -> async def test_raw_response_create(self, async_client: AsyncTelnyx) -> None: response = await async_client.enterprises.with_raw_response.create( billing_address={ - "administrative_area": "Illinois", + "administrative_area": "IL", "city": "Chicago", - "country": "United States", + "country": "US", "postal_code": "60601", - "street_address": "123 Main St", + "street_address": "100 Main St", }, billing_contact={ - "email": "billing@acme.com", - "first_name": "John", - "last_name": "Doe", - "phone_number": "15551234568", + "email": "billing@run065.example.com", + "first_name": "Alex", + "last_name": "Bill", + "phone_number": "+13125550001", }, country_code="US", - doing_business_as="Acme", + doing_business_as="Run 065 Debug", fein="12-3456789", industry="technology", - legal_name="Acme Corp Inc.", + jurisdiction_of_incorporation="Delaware", + legal_name="Run 065 Debug Co", number_of_employees="51-200", organization_contact={ - "email": "jane.smith@acme.com", - "first_name": "Jane", - "job_title": "VP of Engineering", - "last_name": "Smith", - "phone": "+16035551234", + "email": "org@run065.example.com", + "first_name": "Sam", + "job_title": "Compliance Lead", + "last_name": "Org", + "phone_number": "+13125550000", }, - organization_legal_type="corporation", + organization_legal_type="llc", organization_physical_address={ - "administrative_area": "Illinois", + "administrative_area": "IL", "city": "Chicago", - "country": "United States", + "country": "US", "postal_code": "60601", - "street_address": "123 Main St", + "street_address": "100 Main St", }, organization_type="commercial", - website="https://acme.com", + website="https://run065.example.com", ) assert response.is_closed is True @@ -578,41 +629,42 @@ async def test_raw_response_create(self, async_client: AsyncTelnyx) -> None: async def test_streaming_response_create(self, async_client: AsyncTelnyx) -> None: async with async_client.enterprises.with_streaming_response.create( billing_address={ - "administrative_area": "Illinois", + "administrative_area": "IL", "city": "Chicago", - "country": "United States", + "country": "US", "postal_code": "60601", - "street_address": "123 Main St", + "street_address": "100 Main St", }, billing_contact={ - "email": "billing@acme.com", - "first_name": "John", - "last_name": "Doe", - "phone_number": "15551234568", + "email": "billing@run065.example.com", + "first_name": "Alex", + "last_name": "Bill", + "phone_number": "+13125550001", }, country_code="US", - doing_business_as="Acme", + doing_business_as="Run 065 Debug", fein="12-3456789", industry="technology", - legal_name="Acme Corp Inc.", + jurisdiction_of_incorporation="Delaware", + legal_name="Run 065 Debug Co", number_of_employees="51-200", organization_contact={ - "email": "jane.smith@acme.com", - "first_name": "Jane", - "job_title": "VP of Engineering", - "last_name": "Smith", - "phone": "+16035551234", + "email": "org@run065.example.com", + "first_name": "Sam", + "job_title": "Compliance Lead", + "last_name": "Org", + "phone_number": "+13125550000", }, - organization_legal_type="corporation", + organization_legal_type="llc", organization_physical_address={ - "administrative_area": "Illinois", + "administrative_area": "IL", "city": "Chicago", - "country": "United States", + "country": "US", "postal_code": "60601", - "street_address": "123 Main St", + "street_address": "100 Main St", }, organization_type="commercial", - website="https://acme.com", + website="https://run065.example.com", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -626,7 +678,7 @@ async def test_streaming_response_create(self, async_client: AsyncTelnyx) -> Non @parametrize async def test_method_retrieve(self, async_client: AsyncTelnyx) -> None: enterprise = await async_client.enterprises.retrieve( - "6a09cdc3-8948-47f0-aa62-74ac943d6c58", + "4a6192a4-573d-446d-b3ce-aff9117272a6", ) assert_matches_type(EnterpriseRetrieveResponse, enterprise, path=["response"]) @@ -634,7 +686,7 @@ async def test_method_retrieve(self, async_client: AsyncTelnyx) -> None: @parametrize async def test_raw_response_retrieve(self, async_client: AsyncTelnyx) -> None: response = await async_client.enterprises.with_raw_response.retrieve( - "6a09cdc3-8948-47f0-aa62-74ac943d6c58", + "4a6192a4-573d-446d-b3ce-aff9117272a6", ) assert response.is_closed is True @@ -646,7 +698,7 @@ async def test_raw_response_retrieve(self, async_client: AsyncTelnyx) -> None: @parametrize async def test_streaming_response_retrieve(self, async_client: AsyncTelnyx) -> None: async with async_client.enterprises.with_streaming_response.retrieve( - "6a09cdc3-8948-47f0-aa62-74ac943d6c58", + "4a6192a4-573d-446d-b3ce-aff9117272a6", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -668,7 +720,7 @@ async def test_path_params_retrieve(self, async_client: AsyncTelnyx) -> None: @parametrize async def test_method_update(self, async_client: AsyncTelnyx) -> None: enterprise = await async_client.enterprises.update( - enterprise_id="6a09cdc3-8948-47f0-aa62-74ac943d6c58", + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", ) assert_matches_type(EnterpriseUpdateResponse, enterprise, path=["response"]) @@ -676,48 +728,49 @@ async def test_method_update(self, async_client: AsyncTelnyx) -> None: @parametrize async def test_method_update_with_all_params(self, async_client: AsyncTelnyx) -> None: enterprise = await async_client.enterprises.update( - enterprise_id="6a09cdc3-8948-47f0-aa62-74ac943d6c58", + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", billing_address={ - "administrative_area": "Illinois", + "administrative_area": "IL", "city": "Chicago", - "country": "United States", + "country": "US", "postal_code": "60601", - "street_address": "123 Main St", - "extended_address": "Suite 400", + "street_address": "100 Main St", + "extended_address": "Suite 504", }, billing_contact={ - "email": "billing@acme.com", - "first_name": "John", - "last_name": "Doe", - "phone_number": "15551234568", + "email": "billing@acmeplumbing.example.com", + "first_name": "Alex", + "last_name": "Bill", + "phone_number": "+13125550001", }, corporate_registration_number="corporate_registration_number", - customer_reference="customer_reference", - doing_business_as="doing_business_as", + customer_reference="internal-ref-2026Q2", + doing_business_as="Acme Plumbing", dun_bradstreet_number="dun_bradstreet_number", - fein="fein", - industry="industry", - legal_name="xxx", - number_of_employees="1-10", + fein="12-3456789", + industry="business", + jurisdiction_of_incorporation="Delaware", + legal_name="Acme Plumbing LLC", + number_of_employees="51-200", organization_contact={ - "email": "jane.smith@acme.com", - "first_name": "Jane", - "job_title": "VP of Engineering", - "last_name": "Smith", - "phone": "+16035551234", + "email": "sam@acmeplumbing.example.com", + "first_name": "Sam", + "job_title": "Compliance Lead", + "last_name": "Owner", + "phone_number": "+13125550000", }, - organization_legal_type="corporation", + organization_legal_type="llc", organization_physical_address={ - "administrative_area": "Illinois", + "administrative_area": "IL", "city": "Chicago", - "country": "United States", + "country": "US", "postal_code": "60601", - "street_address": "123 Main St", - "extended_address": "Suite 400", + "street_address": "100 Main St", + "extended_address": "Suite 504", }, primary_business_domain_sic_code="primary_business_domain_sic_code", professional_license_number="professional_license_number", - website="website", + website="https://acmeplumbing.example.com", ) assert_matches_type(EnterpriseUpdateResponse, enterprise, path=["response"]) @@ -725,7 +778,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncTelnyx) -> @parametrize async def test_raw_response_update(self, async_client: AsyncTelnyx) -> None: response = await async_client.enterprises.with_raw_response.update( - enterprise_id="6a09cdc3-8948-47f0-aa62-74ac943d6c58", + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", ) assert response.is_closed is True @@ -737,7 +790,7 @@ async def test_raw_response_update(self, async_client: AsyncTelnyx) -> None: @parametrize async def test_streaming_response_update(self, async_client: AsyncTelnyx) -> None: async with async_client.enterprises.with_streaming_response.update( - enterprise_id="6a09cdc3-8948-47f0-aa62-74ac943d6c58", + enterprise_id="4a6192a4-573d-446d-b3ce-aff9117272a6", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -767,7 +820,7 @@ async def test_method_list_with_all_params(self, async_client: AsyncTelnyx) -> N enterprise = await async_client.enterprises.list( legal_name="Acme", page_number=1, - page_size=1, + page_size=10, ) assert_matches_type(AsyncDefaultFlatPagination[EnterprisePublic], enterprise, path=["response"]) @@ -797,7 +850,7 @@ async def test_streaming_response_list(self, async_client: AsyncTelnyx) -> None: @parametrize async def test_method_delete(self, async_client: AsyncTelnyx) -> None: enterprise = await async_client.enterprises.delete( - "6a09cdc3-8948-47f0-aa62-74ac943d6c58", + "4a6192a4-573d-446d-b3ce-aff9117272a6", ) assert enterprise is None @@ -805,7 +858,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.enterprises.with_raw_response.delete( - "6a09cdc3-8948-47f0-aa62-74ac943d6c58", + "4a6192a4-573d-446d-b3ce-aff9117272a6", ) assert response.is_closed is True @@ -817,7 +870,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.enterprises.with_streaming_response.delete( - "6a09cdc3-8948-47f0-aa62-74ac943d6c58", + "4a6192a4-573d-446d-b3ce-aff9117272a6", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -834,3 +887,45 @@ async def test_path_params_delete(self, async_client: AsyncTelnyx) -> None: await async_client.enterprises.with_raw_response.delete( "", ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_activate_branded_calling(self, async_client: AsyncTelnyx) -> None: + enterprise = await async_client.enterprises.activate_branded_calling( + "4a6192a4-573d-446d-b3ce-aff9117272a6", + ) + assert_matches_type(EnterpriseActivateBrandedCallingResponse, enterprise, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_activate_branded_calling(self, async_client: AsyncTelnyx) -> None: + response = await async_client.enterprises.with_raw_response.activate_branded_calling( + "4a6192a4-573d-446d-b3ce-aff9117272a6", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + enterprise = await response.parse() + assert_matches_type(EnterpriseActivateBrandedCallingResponse, enterprise, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_activate_branded_calling(self, async_client: AsyncTelnyx) -> None: + async with async_client.enterprises.with_streaming_response.activate_branded_calling( + "4a6192a4-573d-446d-b3ce-aff9117272a6", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + enterprise = await response.parse() + assert_matches_type(EnterpriseActivateBrandedCallingResponse, enterprise, 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_activate_branded_calling(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.with_raw_response.activate_branded_calling( + "", + ) diff --git a/tests/api_resources/test_infringement_claims.py b/tests/api_resources/test_infringement_claims.py new file mode 100644 index 00000000..376f2f06 --- /dev/null +++ b/tests/api_resources/test_infringement_claims.py @@ -0,0 +1,235 @@ +# 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 ( + InfringementClaimContestResponse, + InfringementClaimRetrieveResponse, +) + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestInfringementClaims: + 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(self, client: Telnyx) -> None: + infringement_claim = client.infringement_claims.retrieve( + "e379fbc8-cd83-4bef-a280-a0ac9d00dcf8", + ) + assert_matches_type(InfringementClaimRetrieveResponse, infringement_claim, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_retrieve(self, client: Telnyx) -> None: + response = client.infringement_claims.with_raw_response.retrieve( + "e379fbc8-cd83-4bef-a280-a0ac9d00dcf8", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + infringement_claim = response.parse() + assert_matches_type(InfringementClaimRetrieveResponse, infringement_claim, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_retrieve(self, client: Telnyx) -> None: + with client.infringement_claims.with_streaming_response.retrieve( + "e379fbc8-cd83-4bef-a280-a0ac9d00dcf8", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + infringement_claim = response.parse() + assert_matches_type(InfringementClaimRetrieveResponse, infringement_claim, 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(self, client: Telnyx) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `claim_id` but received ''"): + client.infringement_claims.with_raw_response.retrieve( + "", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_contest(self, client: Telnyx) -> None: + infringement_claim = client.infringement_claims.contest( + claim_id="e379fbc8-cd83-4bef-a280-a0ac9d00dcf8", + contest_notes="We own the trademark outright; our registration precedes the claimant by three years. See attached certificate.", + ) + assert_matches_type(InfringementClaimContestResponse, infringement_claim, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_contest_with_all_params(self, client: Telnyx) -> None: + infringement_claim = client.infringement_claims.contest( + claim_id="e379fbc8-cd83-4bef-a280-a0ac9d00dcf8", + contest_notes="We own the trademark outright; our registration precedes the claimant by three years. See attached certificate.", + documents=[ + { + "document_id": "2a7e8337-e803-4057-a4ae-26c40eb0bc6c", + "document_type": "trademark_registration", + "description": "USPTO trademark certificate.", + } + ], + ) + assert_matches_type(InfringementClaimContestResponse, infringement_claim, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_contest(self, client: Telnyx) -> None: + response = client.infringement_claims.with_raw_response.contest( + claim_id="e379fbc8-cd83-4bef-a280-a0ac9d00dcf8", + contest_notes="We own the trademark outright; our registration precedes the claimant by three years. See attached certificate.", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + infringement_claim = response.parse() + assert_matches_type(InfringementClaimContestResponse, infringement_claim, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_contest(self, client: Telnyx) -> None: + with client.infringement_claims.with_streaming_response.contest( + claim_id="e379fbc8-cd83-4bef-a280-a0ac9d00dcf8", + contest_notes="We own the trademark outright; our registration precedes the claimant by three years. See attached certificate.", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + infringement_claim = response.parse() + assert_matches_type(InfringementClaimContestResponse, infringement_claim, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_path_params_contest(self, client: Telnyx) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `claim_id` but received ''"): + client.infringement_claims.with_raw_response.contest( + claim_id="", + contest_notes="We own the trademark outright; our registration precedes the claimant by three years. See attached certificate.", + ) + + +class TestAsyncInfringementClaims: + 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(self, async_client: AsyncTelnyx) -> None: + infringement_claim = await async_client.infringement_claims.retrieve( + "e379fbc8-cd83-4bef-a280-a0ac9d00dcf8", + ) + assert_matches_type(InfringementClaimRetrieveResponse, infringement_claim, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_retrieve(self, async_client: AsyncTelnyx) -> None: + response = await async_client.infringement_claims.with_raw_response.retrieve( + "e379fbc8-cd83-4bef-a280-a0ac9d00dcf8", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + infringement_claim = await response.parse() + assert_matches_type(InfringementClaimRetrieveResponse, infringement_claim, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_retrieve(self, async_client: AsyncTelnyx) -> None: + async with async_client.infringement_claims.with_streaming_response.retrieve( + "e379fbc8-cd83-4bef-a280-a0ac9d00dcf8", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + infringement_claim = await response.parse() + assert_matches_type(InfringementClaimRetrieveResponse, infringement_claim, 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(self, async_client: AsyncTelnyx) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `claim_id` but received ''"): + await async_client.infringement_claims.with_raw_response.retrieve( + "", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_contest(self, async_client: AsyncTelnyx) -> None: + infringement_claim = await async_client.infringement_claims.contest( + claim_id="e379fbc8-cd83-4bef-a280-a0ac9d00dcf8", + contest_notes="We own the trademark outright; our registration precedes the claimant by three years. See attached certificate.", + ) + assert_matches_type(InfringementClaimContestResponse, infringement_claim, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_contest_with_all_params(self, async_client: AsyncTelnyx) -> None: + infringement_claim = await async_client.infringement_claims.contest( + claim_id="e379fbc8-cd83-4bef-a280-a0ac9d00dcf8", + contest_notes="We own the trademark outright; our registration precedes the claimant by three years. See attached certificate.", + documents=[ + { + "document_id": "2a7e8337-e803-4057-a4ae-26c40eb0bc6c", + "document_type": "trademark_registration", + "description": "USPTO trademark certificate.", + } + ], + ) + assert_matches_type(InfringementClaimContestResponse, infringement_claim, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_contest(self, async_client: AsyncTelnyx) -> None: + response = await async_client.infringement_claims.with_raw_response.contest( + claim_id="e379fbc8-cd83-4bef-a280-a0ac9d00dcf8", + contest_notes="We own the trademark outright; our registration precedes the claimant by three years. See attached certificate.", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + infringement_claim = await response.parse() + assert_matches_type(InfringementClaimContestResponse, infringement_claim, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_contest(self, async_client: AsyncTelnyx) -> None: + async with async_client.infringement_claims.with_streaming_response.contest( + claim_id="e379fbc8-cd83-4bef-a280-a0ac9d00dcf8", + contest_notes="We own the trademark outright; our registration precedes the claimant by three years. See attached certificate.", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + infringement_claim = await response.parse() + assert_matches_type(InfringementClaimContestResponse, infringement_claim, 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_contest(self, async_client: AsyncTelnyx) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `claim_id` but received ''"): + await async_client.infringement_claims.with_raw_response.contest( + claim_id="", + contest_notes="We own the trademark outright; our registration precedes the claimant by three years. See attached certificate.", + ) diff --git a/tests/api_resources/test_public_internet_gateways.py b/tests/api_resources/test_public_internet_gateways.py index 821b3803..14e4cf46 100644 --- a/tests/api_resources/test_public_internet_gateways.py +++ b/tests/api_resources/test_public_internet_gateways.py @@ -10,7 +10,7 @@ from telnyx import Telnyx, AsyncTelnyx from tests.utils import assert_matches_type from telnyx.types import ( - PublicInternetGatewayRead, + PublicInternetGatewayListResponse, PublicInternetGatewayCreateResponse, PublicInternetGatewayDeleteResponse, PublicInternetGatewayRetrieveResponse, @@ -108,7 +108,7 @@ def test_path_params_retrieve(self, client: Telnyx) -> None: def test_method_list(self, client: Telnyx) -> None: public_internet_gateway = client.public_internet_gateways.list() assert_matches_type( - SyncDefaultFlatPagination[PublicInternetGatewayRead], public_internet_gateway, path=["response"] + SyncDefaultFlatPagination[PublicInternetGatewayListResponse], public_internet_gateway, path=["response"] ) @pytest.mark.skip(reason="Mock server tests are disabled") @@ -120,7 +120,7 @@ def test_method_list_with_all_params(self, client: Telnyx) -> None: page_size=0, ) assert_matches_type( - SyncDefaultFlatPagination[PublicInternetGatewayRead], public_internet_gateway, path=["response"] + SyncDefaultFlatPagination[PublicInternetGatewayListResponse], public_internet_gateway, path=["response"] ) @pytest.mark.skip(reason="Mock server tests are disabled") @@ -132,7 +132,7 @@ def test_raw_response_list(self, client: Telnyx) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" public_internet_gateway = response.parse() assert_matches_type( - SyncDefaultFlatPagination[PublicInternetGatewayRead], public_internet_gateway, path=["response"] + SyncDefaultFlatPagination[PublicInternetGatewayListResponse], public_internet_gateway, path=["response"] ) @pytest.mark.skip(reason="Mock server tests are disabled") @@ -144,7 +144,7 @@ def test_streaming_response_list(self, client: Telnyx) -> None: public_internet_gateway = response.parse() assert_matches_type( - SyncDefaultFlatPagination[PublicInternetGatewayRead], public_internet_gateway, path=["response"] + SyncDefaultFlatPagination[PublicInternetGatewayListResponse], public_internet_gateway, path=["response"] ) assert cast(Any, response.is_closed) is True @@ -282,7 +282,7 @@ async def test_path_params_retrieve(self, async_client: AsyncTelnyx) -> None: async def test_method_list(self, async_client: AsyncTelnyx) -> None: public_internet_gateway = await async_client.public_internet_gateways.list() assert_matches_type( - AsyncDefaultFlatPagination[PublicInternetGatewayRead], public_internet_gateway, path=["response"] + AsyncDefaultFlatPagination[PublicInternetGatewayListResponse], public_internet_gateway, path=["response"] ) @pytest.mark.skip(reason="Mock server tests are disabled") @@ -294,7 +294,7 @@ async def test_method_list_with_all_params(self, async_client: AsyncTelnyx) -> N page_size=0, ) assert_matches_type( - AsyncDefaultFlatPagination[PublicInternetGatewayRead], public_internet_gateway, path=["response"] + AsyncDefaultFlatPagination[PublicInternetGatewayListResponse], public_internet_gateway, path=["response"] ) @pytest.mark.skip(reason="Mock server tests are disabled") @@ -306,7 +306,7 @@ async def test_raw_response_list(self, async_client: AsyncTelnyx) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" public_internet_gateway = await response.parse() assert_matches_type( - AsyncDefaultFlatPagination[PublicInternetGatewayRead], public_internet_gateway, path=["response"] + AsyncDefaultFlatPagination[PublicInternetGatewayListResponse], public_internet_gateway, path=["response"] ) @pytest.mark.skip(reason="Mock server tests are disabled") @@ -318,7 +318,9 @@ async def test_streaming_response_list(self, async_client: AsyncTelnyx) -> None: public_internet_gateway = await response.parse() assert_matches_type( - AsyncDefaultFlatPagination[PublicInternetGatewayRead], public_internet_gateway, path=["response"] + AsyncDefaultFlatPagination[PublicInternetGatewayListResponse], + public_internet_gateway, + path=["response"], ) assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/test_terms_of_service.py b/tests/api_resources/test_terms_of_service.py new file mode 100644 index 00000000..3fe0941c --- /dev/null +++ b/tests/api_resources/test_terms_of_service.py @@ -0,0 +1,96 @@ +# 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 TermsOfServiceStatusResponse + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestTermsOfService: + 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_status(self, client: Telnyx) -> None: + terms_of_service = client.terms_of_service.status() + assert_matches_type(TermsOfServiceStatusResponse, terms_of_service, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_status_with_all_params(self, client: Telnyx) -> None: + terms_of_service = client.terms_of_service.status( + product_type="branded_calling", + ) + assert_matches_type(TermsOfServiceStatusResponse, terms_of_service, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_status(self, client: Telnyx) -> None: + response = client.terms_of_service.with_raw_response.status() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + terms_of_service = response.parse() + assert_matches_type(TermsOfServiceStatusResponse, terms_of_service, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_status(self, client: Telnyx) -> None: + with client.terms_of_service.with_streaming_response.status() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + terms_of_service = response.parse() + assert_matches_type(TermsOfServiceStatusResponse, terms_of_service, path=["response"]) + + assert cast(Any, response.is_closed) is True + + +class TestAsyncTermsOfService: + 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_status(self, async_client: AsyncTelnyx) -> None: + terms_of_service = await async_client.terms_of_service.status() + assert_matches_type(TermsOfServiceStatusResponse, terms_of_service, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_status_with_all_params(self, async_client: AsyncTelnyx) -> None: + terms_of_service = await async_client.terms_of_service.status( + product_type="branded_calling", + ) + assert_matches_type(TermsOfServiceStatusResponse, terms_of_service, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_status(self, async_client: AsyncTelnyx) -> None: + response = await async_client.terms_of_service.with_raw_response.status() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + terms_of_service = await response.parse() + assert_matches_type(TermsOfServiceStatusResponse, terms_of_service, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_status(self, async_client: AsyncTelnyx) -> None: + async with async_client.terms_of_service.with_streaming_response.status() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + terms_of_service = await response.parse() + assert_matches_type(TermsOfServiceStatusResponse, terms_of_service, path=["response"]) + + assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/test_uac_connections.py b/tests/api_resources/test_uac_connections.py index 6fe9f2df..b50af293 100644 --- a/tests/api_resources/test_uac_connections.py +++ b/tests/api_resources/test_uac_connections.py @@ -10,7 +10,7 @@ from telnyx import Telnyx, AsyncTelnyx from tests.utils import assert_matches_type from telnyx.types import ( - UacConnection, + UacConnectionListResponse, UacConnectionCreateResponse, UacConnectionDeleteResponse, UacConnectionUpdateResponse, @@ -303,7 +303,7 @@ def test_path_params_update(self, client: Telnyx) -> None: @parametrize def test_method_list(self, client: Telnyx) -> None: uac_connection = client.uac_connections.list() - assert_matches_type(SyncDefaultFlatPagination[UacConnection], uac_connection, path=["response"]) + assert_matches_type(SyncDefaultFlatPagination[UacConnectionListResponse], uac_connection, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -318,7 +318,7 @@ def test_method_list_with_all_params(self, client: Telnyx) -> None: page_size=0, sort="connection_name", ) - assert_matches_type(SyncDefaultFlatPagination[UacConnection], uac_connection, path=["response"]) + assert_matches_type(SyncDefaultFlatPagination[UacConnectionListResponse], uac_connection, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -328,7 +328,7 @@ def test_raw_response_list(self, client: Telnyx) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" uac_connection = response.parse() - assert_matches_type(SyncDefaultFlatPagination[UacConnection], uac_connection, path=["response"]) + assert_matches_type(SyncDefaultFlatPagination[UacConnectionListResponse], uac_connection, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -338,7 +338,7 @@ def test_streaming_response_list(self, client: Telnyx) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" uac_connection = response.parse() - assert_matches_type(SyncDefaultFlatPagination[UacConnection], uac_connection, path=["response"]) + assert_matches_type(SyncDefaultFlatPagination[UacConnectionListResponse], uac_connection, path=["response"]) assert cast(Any, response.is_closed) is True @@ -669,7 +669,7 @@ async def test_path_params_update(self, async_client: AsyncTelnyx) -> None: @parametrize async def test_method_list(self, async_client: AsyncTelnyx) -> None: uac_connection = await async_client.uac_connections.list() - assert_matches_type(AsyncDefaultFlatPagination[UacConnection], uac_connection, path=["response"]) + assert_matches_type(AsyncDefaultFlatPagination[UacConnectionListResponse], uac_connection, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -684,7 +684,7 @@ async def test_method_list_with_all_params(self, async_client: AsyncTelnyx) -> N page_size=0, sort="connection_name", ) - assert_matches_type(AsyncDefaultFlatPagination[UacConnection], uac_connection, path=["response"]) + assert_matches_type(AsyncDefaultFlatPagination[UacConnectionListResponse], uac_connection, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -694,7 +694,7 @@ async def test_raw_response_list(self, async_client: AsyncTelnyx) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" uac_connection = await response.parse() - assert_matches_type(AsyncDefaultFlatPagination[UacConnection], uac_connection, path=["response"]) + assert_matches_type(AsyncDefaultFlatPagination[UacConnectionListResponse], uac_connection, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -704,7 +704,9 @@ async def test_streaming_response_list(self, async_client: AsyncTelnyx) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" uac_connection = await response.parse() - assert_matches_type(AsyncDefaultFlatPagination[UacConnection], uac_connection, path=["response"]) + assert_matches_type( + AsyncDefaultFlatPagination[UacConnectionListResponse], uac_connection, path=["response"] + ) assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/test_virtual_cross_connects.py b/tests/api_resources/test_virtual_cross_connects.py index 7b7e2cb1..e44f183c 100644 --- a/tests/api_resources/test_virtual_cross_connects.py +++ b/tests/api_resources/test_virtual_cross_connects.py @@ -10,7 +10,7 @@ from telnyx import Telnyx, AsyncTelnyx from tests.utils import assert_matches_type from telnyx.types import ( - VirtualCrossConnectCombined, + VirtualCrossConnectListResponse, VirtualCrossConnectCreateResponse, VirtualCrossConnectDeleteResponse, VirtualCrossConnectUpdateResponse, @@ -183,7 +183,7 @@ def test_path_params_update(self, client: Telnyx) -> None: def test_method_list(self, client: Telnyx) -> None: virtual_cross_connect = client.virtual_cross_connects.list() assert_matches_type( - SyncDefaultFlatPagination[VirtualCrossConnectCombined], virtual_cross_connect, path=["response"] + SyncDefaultFlatPagination[VirtualCrossConnectListResponse], virtual_cross_connect, path=["response"] ) @pytest.mark.skip(reason="Mock server tests are disabled") @@ -195,7 +195,7 @@ def test_method_list_with_all_params(self, client: Telnyx) -> None: page_size=0, ) assert_matches_type( - SyncDefaultFlatPagination[VirtualCrossConnectCombined], virtual_cross_connect, path=["response"] + SyncDefaultFlatPagination[VirtualCrossConnectListResponse], virtual_cross_connect, path=["response"] ) @pytest.mark.skip(reason="Mock server tests are disabled") @@ -207,7 +207,7 @@ def test_raw_response_list(self, client: Telnyx) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" virtual_cross_connect = response.parse() assert_matches_type( - SyncDefaultFlatPagination[VirtualCrossConnectCombined], virtual_cross_connect, path=["response"] + SyncDefaultFlatPagination[VirtualCrossConnectListResponse], virtual_cross_connect, path=["response"] ) @pytest.mark.skip(reason="Mock server tests are disabled") @@ -219,7 +219,7 @@ def test_streaming_response_list(self, client: Telnyx) -> None: virtual_cross_connect = response.parse() assert_matches_type( - SyncDefaultFlatPagination[VirtualCrossConnectCombined], virtual_cross_connect, path=["response"] + SyncDefaultFlatPagination[VirtualCrossConnectListResponse], virtual_cross_connect, path=["response"] ) assert cast(Any, response.is_closed) is True @@ -431,7 +431,7 @@ async def test_path_params_update(self, async_client: AsyncTelnyx) -> None: async def test_method_list(self, async_client: AsyncTelnyx) -> None: virtual_cross_connect = await async_client.virtual_cross_connects.list() assert_matches_type( - AsyncDefaultFlatPagination[VirtualCrossConnectCombined], virtual_cross_connect, path=["response"] + AsyncDefaultFlatPagination[VirtualCrossConnectListResponse], virtual_cross_connect, path=["response"] ) @pytest.mark.skip(reason="Mock server tests are disabled") @@ -443,7 +443,7 @@ async def test_method_list_with_all_params(self, async_client: AsyncTelnyx) -> N page_size=0, ) assert_matches_type( - AsyncDefaultFlatPagination[VirtualCrossConnectCombined], virtual_cross_connect, path=["response"] + AsyncDefaultFlatPagination[VirtualCrossConnectListResponse], virtual_cross_connect, path=["response"] ) @pytest.mark.skip(reason="Mock server tests are disabled") @@ -455,7 +455,7 @@ async def test_raw_response_list(self, async_client: AsyncTelnyx) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" virtual_cross_connect = await response.parse() assert_matches_type( - AsyncDefaultFlatPagination[VirtualCrossConnectCombined], virtual_cross_connect, path=["response"] + AsyncDefaultFlatPagination[VirtualCrossConnectListResponse], virtual_cross_connect, path=["response"] ) @pytest.mark.skip(reason="Mock server tests are disabled") @@ -467,7 +467,7 @@ async def test_streaming_response_list(self, async_client: AsyncTelnyx) -> None: virtual_cross_connect = await response.parse() assert_matches_type( - AsyncDefaultFlatPagination[VirtualCrossConnectCombined], virtual_cross_connect, path=["response"] + AsyncDefaultFlatPagination[VirtualCrossConnectListResponse], virtual_cross_connect, path=["response"] ) assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/test_wireguard_interfaces.py b/tests/api_resources/test_wireguard_interfaces.py index 88924f8c..8627060c 100644 --- a/tests/api_resources/test_wireguard_interfaces.py +++ b/tests/api_resources/test_wireguard_interfaces.py @@ -10,7 +10,7 @@ from telnyx import Telnyx, AsyncTelnyx from tests.utils import assert_matches_type from telnyx.types import ( - WireguardInterfaceRead, + WireguardInterfaceListResponse, WireguardInterfaceCreateResponse, WireguardInterfaceDeleteResponse, WireguardInterfaceRetrieveResponse, @@ -114,7 +114,9 @@ def test_path_params_retrieve(self, client: Telnyx) -> None: @parametrize def test_method_list(self, client: Telnyx) -> None: wireguard_interface = client.wireguard_interfaces.list() - assert_matches_type(SyncDefaultFlatPagination[WireguardInterfaceRead], wireguard_interface, path=["response"]) + assert_matches_type( + SyncDefaultFlatPagination[WireguardInterfaceListResponse], wireguard_interface, path=["response"] + ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -124,7 +126,9 @@ def test_method_list_with_all_params(self, client: Telnyx) -> None: page_number=0, page_size=0, ) - assert_matches_type(SyncDefaultFlatPagination[WireguardInterfaceRead], wireguard_interface, path=["response"]) + assert_matches_type( + SyncDefaultFlatPagination[WireguardInterfaceListResponse], wireguard_interface, path=["response"] + ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -134,7 +138,9 @@ def test_raw_response_list(self, client: Telnyx) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" wireguard_interface = response.parse() - assert_matches_type(SyncDefaultFlatPagination[WireguardInterfaceRead], wireguard_interface, path=["response"]) + assert_matches_type( + SyncDefaultFlatPagination[WireguardInterfaceListResponse], wireguard_interface, path=["response"] + ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -145,7 +151,7 @@ def test_streaming_response_list(self, client: Telnyx) -> None: wireguard_interface = response.parse() assert_matches_type( - SyncDefaultFlatPagination[WireguardInterfaceRead], wireguard_interface, path=["response"] + SyncDefaultFlatPagination[WireguardInterfaceListResponse], wireguard_interface, path=["response"] ) assert cast(Any, response.is_closed) is True @@ -289,7 +295,9 @@ async def test_path_params_retrieve(self, async_client: AsyncTelnyx) -> None: @parametrize async def test_method_list(self, async_client: AsyncTelnyx) -> None: wireguard_interface = await async_client.wireguard_interfaces.list() - assert_matches_type(AsyncDefaultFlatPagination[WireguardInterfaceRead], wireguard_interface, path=["response"]) + assert_matches_type( + AsyncDefaultFlatPagination[WireguardInterfaceListResponse], wireguard_interface, path=["response"] + ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -299,7 +307,9 @@ async def test_method_list_with_all_params(self, async_client: AsyncTelnyx) -> N page_number=0, page_size=0, ) - assert_matches_type(AsyncDefaultFlatPagination[WireguardInterfaceRead], wireguard_interface, path=["response"]) + assert_matches_type( + AsyncDefaultFlatPagination[WireguardInterfaceListResponse], wireguard_interface, path=["response"] + ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -309,7 +319,9 @@ async def test_raw_response_list(self, async_client: AsyncTelnyx) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" wireguard_interface = await response.parse() - assert_matches_type(AsyncDefaultFlatPagination[WireguardInterfaceRead], wireguard_interface, path=["response"]) + assert_matches_type( + AsyncDefaultFlatPagination[WireguardInterfaceListResponse], wireguard_interface, path=["response"] + ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -320,7 +332,7 @@ async def test_streaming_response_list(self, async_client: AsyncTelnyx) -> None: wireguard_interface = await response.parse() assert_matches_type( - AsyncDefaultFlatPagination[WireguardInterfaceRead], wireguard_interface, path=["response"] + AsyncDefaultFlatPagination[WireguardInterfaceListResponse], wireguard_interface, path=["response"] ) assert cast(Any, response.is_closed) is True From 17111c3cd703b7d4451f5c9b685afce3826f44e4 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 5 Jun 2026 18:53:19 +0000 Subject: [PATCH 2/2] release: 4.152.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 8 ++++++++ pyproject.toml | 2 +- src/telnyx/_version.py | 2 +- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index e7dafb47..195f950f 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "4.151.0" + ".": "4.152.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 3aac0bfb..e4a7a581 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## 4.152.0 (2026-06-05) + +Full Changelog: [v4.151.0...v4.152.0](https://github.com/team-telnyx/telnyx-python/compare/v4.151.0...v4.152.0) + +### Features + +* NUM-6470: Add branded-calling-v2 OpenAPI specs (external + internal) ([a2c999f](https://github.com/team-telnyx/telnyx-python/commit/a2c999f01668f86406e50c6a32fbefc099ae938b)) + ## 4.151.0 (2026-06-05) Full Changelog: [v4.150.0...v4.151.0](https://github.com/team-telnyx/telnyx-python/compare/v4.150.0...v4.151.0) diff --git a/pyproject.toml b/pyproject.toml index 14022cae..17245305 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "telnyx" -version = "4.151.0" +version = "4.152.0" description = "The official Python library for the telnyx API" dynamic = ["readme"] license = "MIT" diff --git a/src/telnyx/_version.py b/src/telnyx/_version.py index 5841a80c..c99502a1 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.151.0" # x-release-please-version +__version__ = "4.152.0" # x-release-please-version