From 411894ea26cd10281d95d619feca4d50f7f57897 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 26 Feb 2026 14:32:30 +0000 Subject: [PATCH 1/5] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index d9cefbd2..6aaf0974 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 946 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/telnyx%2Ftelnyx-462166922656820a2c260496fa86ce259c51c8ad7aaa783e1975e16f05c08af7.yml -openapi_spec_hash: bc16f6bdab2570564f73ece9ec24f57c +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/telnyx%2Ftelnyx-7508cbe75462245fb5cdf6935064e7342011990bf26539ae6590e9b65a65b826.yml +openapi_spec_hash: 08ae3f68c700f1a6432feb1f3df446fd config_hash: 86808d35d9648ffe4b87e3e5b858c17c From f54a80e694595f81293ab50af4548f054b48df43 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 26 Feb 2026 15:17:35 +0000 Subject: [PATCH 2/5] codegen metadata --- .stats.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.stats.yml b/.stats.yml index 6aaf0974..cabca1cd 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 946 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/telnyx%2Ftelnyx-7508cbe75462245fb5cdf6935064e7342011990bf26539ae6590e9b65a65b826.yml -openapi_spec_hash: 08ae3f68c700f1a6432feb1f3df446fd -config_hash: 86808d35d9648ffe4b87e3e5b858c17c +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/telnyx%2Ftelnyx-f8ac3fc0b11c82c4504efdfd9719d069fb41ab1d977f8cb3de1ed1a53d8b2c24.yml +openapi_spec_hash: b103646d1bc605319de9dc598af102a6 +config_hash: 5300e28459aea095deff56269a1d7e9e From e30bc6fa5f91da4f8734564a66e8458d09422000 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 26 Feb 2026 15:35:34 +0000 Subject: [PATCH 3/5] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index cabca1cd..1b8e2150 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 946 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/telnyx%2Ftelnyx-f8ac3fc0b11c82c4504efdfd9719d069fb41ab1d977f8cb3de1ed1a53d8b2c24.yml +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/telnyx%2Ftelnyx-ba02fe79cc421415e64d1c7a406b6e9e7edd0735b0bd8ca60cc0cb2f65d71fe6.yml openapi_spec_hash: b103646d1bc605319de9dc598af102a6 -config_hash: 5300e28459aea095deff56269a1d7e9e +config_hash: a928849ebc1d9775bbdf265cf313c0f7 From f14db77cd98183ca8919771c2ba9d01c7f9dacfc Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 26 Feb 2026 17:58:48 +0000 Subject: [PATCH 4/5] feat(api): manual updates --- .stats.yml | 6 +- api.md | 2 +- src/telnyx/resources/conferences/actions.py | 10 - src/telnyx/resources/text_to_speech.py | 284 +++++++----------- src/telnyx/types/__init__.py | 2 +- .../conferences/action_record_start_params.py | 6 - .../text_to_speech_generate_speech_params.py | 26 ++ .../types/text_to_speech_stream_params.py | 49 --- .../api_resources/conferences/test_actions.py | 2 - tests/api_resources/test_text_to_speech.py | 174 ++++++----- 10 files changed, 234 insertions(+), 327 deletions(-) create mode 100644 src/telnyx/types/text_to_speech_generate_speech_params.py delete mode 100644 src/telnyx/types/text_to_speech_stream_params.py diff --git a/.stats.yml b/.stats.yml index 1b8e2150..3984b45a 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 946 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/telnyx%2Ftelnyx-ba02fe79cc421415e64d1c7a406b6e9e7edd0735b0bd8ca60cc0cb2f65d71fe6.yml -openapi_spec_hash: b103646d1bc605319de9dc598af102a6 -config_hash: a928849ebc1d9775bbdf265cf313c0f7 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/telnyx%2Ftelnyx-e5b44768a2da327dbb88d2a4f97653388c6489365db2e873d1225d48280c1530.yml +openapi_spec_hash: 515f3d122ed486daa3f9a90a252908c8 +config_hash: 147ed46e6f2c0900ee7716ce4dddb8e2 diff --git a/api.md b/api.md index 1c0081a5..ffcc76d7 100644 --- a/api.md +++ b/api.md @@ -4464,8 +4464,8 @@ from telnyx.types import TextToSpeechListVoicesResponse Methods: +- client.text_to_speech.generate_speech(\*\*params) -> BinaryAPIResponse - client.text_to_speech.list_voices(\*\*params) -> TextToSpeechListVoicesResponse -- client.text_to_speech.stream(\*\*params) -> None # UsageReports diff --git a/src/telnyx/resources/conferences/actions.py b/src/telnyx/resources/conferences/actions.py index c10db5ed..cbad915a 100644 --- a/src/telnyx/resources/conferences/actions.py +++ b/src/telnyx/resources/conferences/actions.py @@ -765,7 +765,6 @@ def record_start( id: str, *, format: Literal["wav", "mp3"], - channels: Literal["single", "dual"] | Omit = omit, command_id: str | Omit = omit, custom_file_name: str | Omit = omit, play_beep: bool | Omit = omit, @@ -791,9 +790,6 @@ def record_start( format: The audio file format used when storing the conference recording. Can be either `mp3` or `wav`. - channels: When `dual`, final audio file will be stereo recorded with the conference - creator on the first channel, and the rest on the second channel. - command_id: Use this field to avoid duplicate commands. Telnyx will ignore any command with the same `command_id` for the same `conference_id`. @@ -823,7 +819,6 @@ def record_start( body=maybe_transform( { "format": format, - "channels": channels, "command_id": command_id, "custom_file_name": custom_file_name, "play_beep": play_beep, @@ -1956,7 +1951,6 @@ async def record_start( id: str, *, format: Literal["wav", "mp3"], - channels: Literal["single", "dual"] | Omit = omit, command_id: str | Omit = omit, custom_file_name: str | Omit = omit, play_beep: bool | Omit = omit, @@ -1982,9 +1976,6 @@ async def record_start( format: The audio file format used when storing the conference recording. Can be either `mp3` or `wav`. - channels: When `dual`, final audio file will be stereo recorded with the conference - creator on the first channel, and the rest on the second channel. - command_id: Use this field to avoid duplicate commands. Telnyx will ignore any command with the same `command_id` for the same `conference_id`. @@ -2014,7 +2005,6 @@ async def record_start( body=await async_maybe_transform( { "format": format, - "channels": channels, "command_id": command_id, "custom_file_name": custom_file_name, "play_beep": play_beep, diff --git a/src/telnyx/resources/text_to_speech.py b/src/telnyx/resources/text_to_speech.py index 4b9ff0e3..7e37a6f5 100644 --- a/src/telnyx/resources/text_to_speech.py +++ b/src/telnyx/resources/text_to_speech.py @@ -6,16 +6,24 @@ import httpx -from ..types import text_to_speech_stream_params, text_to_speech_list_voices_params -from .._types import Body, Omit, Query, Headers, NoneType, NotGiven, omit, not_given +from ..types import text_to_speech_list_voices_params, text_to_speech_generate_speech_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 .._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.text_to_speech_list_voices_response import TextToSpeechListVoicesResponse @@ -43,25 +51,36 @@ def with_streaming_response(self) -> TextToSpeechResourceWithStreamingResponse: """ return TextToSpeechResourceWithStreamingResponse(self) - def list_voices( + def generate_speech( self, *, - elevenlabs_api_key_ref: str | Omit = omit, - provider: Literal["aws", "azure", "elevenlabs", "telnyx"] | Omit = omit, + text: str, + voice: 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, - ) -> TextToSpeechListVoicesResponse: + ) -> BinaryAPIResponse: """ - Returns a list of voices that can be used with the text to speech commands. + Converts the provided text to speech using the specified voice and returns audio + data Args: - elevenlabs_api_key_ref: Reference to your ElevenLabs API key stored in the Telnyx Portal + text: The text to convert to speech - provider: Filter voices by provider + voice: The voice ID in the format Provider.ModelId.VoiceId. + + Examples: + + - AWS.Polly.Joanna-Neural + - Azure.en-US-AvaMultilingualNeural + - ElevenLabs.eleven_multilingual_v2.Rachel + - Telnyx.KokoroTTS.af + + Use the `GET /text-to-speech/voices` endpoint to get a complete list of + available voices. extra_headers: Send extra headers @@ -71,86 +90,41 @@ def list_voices( timeout: Override the client-level default timeout for this request, in seconds """ - return self._get( - "/text-to-speech/voices", + extra_headers = {"Accept": "audio/mpeg", **(extra_headers or {})} + return self._post( + "/text-to-speech/speech", + body=maybe_transform( + { + "text": text, + "voice": voice, + }, + text_to_speech_generate_speech_params.TextToSpeechGenerateSpeechParams, + ), options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=maybe_transform( - { - "elevenlabs_api_key_ref": elevenlabs_api_key_ref, - "provider": provider, - }, - text_to_speech_list_voices_params.TextToSpeechListVoicesParams, - ), + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=TextToSpeechListVoicesResponse, + cast_to=BinaryAPIResponse, ) - def stream( + def list_voices( self, *, - audio_format: Literal["pcm", "wav"] | Omit = omit, - disable_cache: bool | Omit = omit, - model_id: str | Omit = omit, - provider: Literal["aws", "telnyx", "azure", "elevenlabs", "minimax", "murfai", "rime", "resemble"] - | Omit = omit, - socket_id: str | Omit = omit, - voice: str | Omit = omit, - voice_id: str | Omit = omit, + elevenlabs_api_key_ref: str | Omit = omit, + provider: Literal["aws", "azure", "elevenlabs", "telnyx"] | 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, - ) -> None: + ) -> TextToSpeechListVoicesResponse: """ - Open a WebSocket connection to stream text and receive synthesized audio in real - time. Authentication is provided via the standard - `Authorization: Bearer ` header. Send JSON frames with text to - synthesize; receive JSON frames containing base64-encoded audio chunks. - - Supported providers: `aws`, `telnyx`, `azure`, `murfai`, `minimax`, `rime`, - `resemble`, `elevenlabs`. - - **Connection flow:** - - 1. Open WebSocket with query parameters specifying provider, voice, and model. - 2. Send an initial handshake message `{"text": " "}` (single space) with - optional `voice_settings` to initialize the session. - 3. Send text messages as `{"text": "Hello world"}`. - 4. Receive audio chunks as JSON frames with base64-encoded audio. - 5. A final frame with `isFinal: true` indicates the end of audio for the current - text. - - To interrupt and restart synthesis mid-stream, send `{"force": true}` — the - current worker is stopped and a new one is started. + Returns a list of voices that can be used with the text to speech commands. Args: - audio_format: Audio output format override. Supported for Telnyx `Natural`/`NaturalHD` models - only. Accepted values: `pcm`, `wav`. - - disable_cache: When `true`, bypass the audio cache and generate fresh audio. - - model_id: Model identifier for the chosen provider. Examples: `Natural`, `NaturalHD` - (Telnyx); `Polly.Generative` (AWS). - - provider: TTS provider. Defaults to `telnyx` if not specified. Ignored when `voice` is - provided. - - socket_id: Client-provided socket identifier for tracking. If not provided, one is - generated server-side. - - voice: Voice identifier in the format `provider.model_id.voice_id` or - `provider.voice_id` (e.g. `telnyx.NaturalHD.Telnyx_Alloy` or - `azure.en-US-AvaMultilingualNeural`). When provided, the `provider`, `model_id`, - and `voice_id` are extracted automatically. Takes precedence over individual - `provider`/`model_id`/`voice_id` parameters. + elevenlabs_api_key_ref: Reference to your ElevenLabs API key stored in the Telnyx Portal - voice_id: Voice identifier for the chosen provider. + provider: Filter voices by provider extra_headers: Send extra headers @@ -160,9 +134,8 @@ def stream( timeout: Override the client-level default timeout for this request, in seconds """ - extra_headers = {"Accept": "*/*", **(extra_headers or {})} return self._get( - "/text-to-speech/speech", + "/text-to-speech/voices", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -170,18 +143,13 @@ def stream( timeout=timeout, query=maybe_transform( { - "audio_format": audio_format, - "disable_cache": disable_cache, - "model_id": model_id, + "elevenlabs_api_key_ref": elevenlabs_api_key_ref, "provider": provider, - "socket_id": socket_id, - "voice": voice, - "voice_id": voice_id, }, - text_to_speech_stream_params.TextToSpeechStreamParams, + text_to_speech_list_voices_params.TextToSpeechListVoicesParams, ), ), - cast_to=NoneType, + cast_to=TextToSpeechListVoicesResponse, ) @@ -205,25 +173,36 @@ def with_streaming_response(self) -> AsyncTextToSpeechResourceWithStreamingRespo """ return AsyncTextToSpeechResourceWithStreamingResponse(self) - async def list_voices( + async def generate_speech( self, *, - elevenlabs_api_key_ref: str | Omit = omit, - provider: Literal["aws", "azure", "elevenlabs", "telnyx"] | Omit = omit, + text: str, + voice: 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, - ) -> TextToSpeechListVoicesResponse: + ) -> AsyncBinaryAPIResponse: """ - Returns a list of voices that can be used with the text to speech commands. + Converts the provided text to speech using the specified voice and returns audio + data Args: - elevenlabs_api_key_ref: Reference to your ElevenLabs API key stored in the Telnyx Portal + text: The text to convert to speech - provider: Filter voices by provider + voice: The voice ID in the format Provider.ModelId.VoiceId. + + Examples: + + - AWS.Polly.Joanna-Neural + - Azure.en-US-AvaMultilingualNeural + - ElevenLabs.eleven_multilingual_v2.Rachel + - Telnyx.KokoroTTS.af + + Use the `GET /text-to-speech/voices` endpoint to get a complete list of + available voices. extra_headers: Send extra headers @@ -233,86 +212,41 @@ async def list_voices( timeout: Override the client-level default timeout for this request, in seconds """ - return await self._get( - "/text-to-speech/voices", + extra_headers = {"Accept": "audio/mpeg", **(extra_headers or {})} + return await self._post( + "/text-to-speech/speech", + body=await async_maybe_transform( + { + "text": text, + "voice": voice, + }, + text_to_speech_generate_speech_params.TextToSpeechGenerateSpeechParams, + ), options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=await async_maybe_transform( - { - "elevenlabs_api_key_ref": elevenlabs_api_key_ref, - "provider": provider, - }, - text_to_speech_list_voices_params.TextToSpeechListVoicesParams, - ), + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=TextToSpeechListVoicesResponse, + cast_to=AsyncBinaryAPIResponse, ) - async def stream( + async def list_voices( self, *, - audio_format: Literal["pcm", "wav"] | Omit = omit, - disable_cache: bool | Omit = omit, - model_id: str | Omit = omit, - provider: Literal["aws", "telnyx", "azure", "elevenlabs", "minimax", "murfai", "rime", "resemble"] - | Omit = omit, - socket_id: str | Omit = omit, - voice: str | Omit = omit, - voice_id: str | Omit = omit, + elevenlabs_api_key_ref: str | Omit = omit, + provider: Literal["aws", "azure", "elevenlabs", "telnyx"] | 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, - ) -> None: + ) -> TextToSpeechListVoicesResponse: """ - Open a WebSocket connection to stream text and receive synthesized audio in real - time. Authentication is provided via the standard - `Authorization: Bearer ` header. Send JSON frames with text to - synthesize; receive JSON frames containing base64-encoded audio chunks. - - Supported providers: `aws`, `telnyx`, `azure`, `murfai`, `minimax`, `rime`, - `resemble`, `elevenlabs`. - - **Connection flow:** - - 1. Open WebSocket with query parameters specifying provider, voice, and model. - 2. Send an initial handshake message `{"text": " "}` (single space) with - optional `voice_settings` to initialize the session. - 3. Send text messages as `{"text": "Hello world"}`. - 4. Receive audio chunks as JSON frames with base64-encoded audio. - 5. A final frame with `isFinal: true` indicates the end of audio for the current - text. - - To interrupt and restart synthesis mid-stream, send `{"force": true}` — the - current worker is stopped and a new one is started. + Returns a list of voices that can be used with the text to speech commands. Args: - audio_format: Audio output format override. Supported for Telnyx `Natural`/`NaturalHD` models - only. Accepted values: `pcm`, `wav`. - - disable_cache: When `true`, bypass the audio cache and generate fresh audio. - - model_id: Model identifier for the chosen provider. Examples: `Natural`, `NaturalHD` - (Telnyx); `Polly.Generative` (AWS). - - provider: TTS provider. Defaults to `telnyx` if not specified. Ignored when `voice` is - provided. - - socket_id: Client-provided socket identifier for tracking. If not provided, one is - generated server-side. - - voice: Voice identifier in the format `provider.model_id.voice_id` or - `provider.voice_id` (e.g. `telnyx.NaturalHD.Telnyx_Alloy` or - `azure.en-US-AvaMultilingualNeural`). When provided, the `provider`, `model_id`, - and `voice_id` are extracted automatically. Takes precedence over individual - `provider`/`model_id`/`voice_id` parameters. + elevenlabs_api_key_ref: Reference to your ElevenLabs API key stored in the Telnyx Portal - voice_id: Voice identifier for the chosen provider. + provider: Filter voices by provider extra_headers: Send extra headers @@ -322,9 +256,8 @@ async def stream( timeout: Override the client-level default timeout for this request, in seconds """ - extra_headers = {"Accept": "*/*", **(extra_headers or {})} return await self._get( - "/text-to-speech/speech", + "/text-to-speech/voices", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -332,18 +265,13 @@ async def stream( timeout=timeout, query=await async_maybe_transform( { - "audio_format": audio_format, - "disable_cache": disable_cache, - "model_id": model_id, + "elevenlabs_api_key_ref": elevenlabs_api_key_ref, "provider": provider, - "socket_id": socket_id, - "voice": voice, - "voice_id": voice_id, }, - text_to_speech_stream_params.TextToSpeechStreamParams, + text_to_speech_list_voices_params.TextToSpeechListVoicesParams, ), ), - cast_to=NoneType, + cast_to=TextToSpeechListVoicesResponse, ) @@ -351,45 +279,49 @@ class TextToSpeechResourceWithRawResponse: def __init__(self, text_to_speech: TextToSpeechResource) -> None: self._text_to_speech = text_to_speech + self.generate_speech = to_custom_raw_response_wrapper( + text_to_speech.generate_speech, + BinaryAPIResponse, + ) self.list_voices = to_raw_response_wrapper( text_to_speech.list_voices, ) - self.stream = to_raw_response_wrapper( - text_to_speech.stream, - ) class AsyncTextToSpeechResourceWithRawResponse: def __init__(self, text_to_speech: AsyncTextToSpeechResource) -> None: self._text_to_speech = text_to_speech + self.generate_speech = async_to_custom_raw_response_wrapper( + text_to_speech.generate_speech, + AsyncBinaryAPIResponse, + ) self.list_voices = async_to_raw_response_wrapper( text_to_speech.list_voices, ) - self.stream = async_to_raw_response_wrapper( - text_to_speech.stream, - ) class TextToSpeechResourceWithStreamingResponse: def __init__(self, text_to_speech: TextToSpeechResource) -> None: self._text_to_speech = text_to_speech + self.generate_speech = to_custom_streamed_response_wrapper( + text_to_speech.generate_speech, + StreamedBinaryAPIResponse, + ) self.list_voices = to_streamed_response_wrapper( text_to_speech.list_voices, ) - self.stream = to_streamed_response_wrapper( - text_to_speech.stream, - ) class AsyncTextToSpeechResourceWithStreamingResponse: def __init__(self, text_to_speech: AsyncTextToSpeechResource) -> None: self._text_to_speech = text_to_speech + self.generate_speech = async_to_custom_streamed_response_wrapper( + text_to_speech.generate_speech, + AsyncStreamedBinaryAPIResponse, + ) self.list_voices = async_to_streamed_response_wrapper( text_to_speech.list_voices, ) - self.stream = async_to_streamed_response_wrapper( - text_to_speech.stream, - ) diff --git a/src/telnyx/types/__init__.py b/src/telnyx/types/__init__.py index d6801488..10f0b762 100644 --- a/src/telnyx/types/__init__.py +++ b/src/telnyx/types/__init__.py @@ -437,7 +437,6 @@ from .sim_card_group_update_params import SimCardGroupUpdateParams as SimCardGroupUpdateParams from .sim_card_order_create_params import SimCardOrderCreateParams as SimCardOrderCreateParams from .sub_number_order_list_params import SubNumberOrderListParams as SubNumberOrderListParams -from .text_to_speech_stream_params import TextToSpeechStreamParams as TextToSpeechStreamParams from .url_shortener_settings_param import URLShortenerSettingsParam as URLShortenerSettingsParam from .user_address_create_response import UserAddressCreateResponse as UserAddressCreateResponse from .verified_number_data_wrapper import VerifiedNumberDataWrapper as VerifiedNumberDataWrapper @@ -831,6 +830,7 @@ ) from .sim_card_get_activation_code_response import SimCardGetActivationCodeResponse as SimCardGetActivationCodeResponse from .sim_card_order_preview_preview_params import SimCardOrderPreviewPreviewParams as SimCardOrderPreviewPreviewParams +from .text_to_speech_generate_speech_params import TextToSpeechGenerateSpeechParams as TextToSpeechGenerateSpeechParams from .verification_trigger_flashcall_params import ( VerificationTriggerFlashcallParams as VerificationTriggerFlashcallParams, ) diff --git a/src/telnyx/types/conferences/action_record_start_params.py b/src/telnyx/types/conferences/action_record_start_params.py index d568dc16..09c21496 100644 --- a/src/telnyx/types/conferences/action_record_start_params.py +++ b/src/telnyx/types/conferences/action_record_start_params.py @@ -14,12 +14,6 @@ class ActionRecordStartParams(TypedDict, total=False): Can be either `mp3` or `wav`. """ - channels: Literal["single", "dual"] - """ - When `dual`, final audio file will be stereo recorded with the conference - creator on the first channel, and the rest on the second channel. - """ - command_id: str """Use this field to avoid duplicate commands. diff --git a/src/telnyx/types/text_to_speech_generate_speech_params.py b/src/telnyx/types/text_to_speech_generate_speech_params.py new file mode 100644 index 00000000..95b43e53 --- /dev/null +++ b/src/telnyx/types/text_to_speech_generate_speech_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 Required, TypedDict + +__all__ = ["TextToSpeechGenerateSpeechParams"] + + +class TextToSpeechGenerateSpeechParams(TypedDict, total=False): + text: Required[str] + """The text to convert to speech""" + + voice: Required[str] + """The voice ID in the format Provider.ModelId.VoiceId. + + Examples: + + - AWS.Polly.Joanna-Neural + - Azure.en-US-AvaMultilingualNeural + - ElevenLabs.eleven_multilingual_v2.Rachel + - Telnyx.KokoroTTS.af + + Use the `GET /text-to-speech/voices` endpoint to get a complete list of + available voices. + """ diff --git a/src/telnyx/types/text_to_speech_stream_params.py b/src/telnyx/types/text_to_speech_stream_params.py deleted file mode 100644 index 9a4aac90..00000000 --- a/src/telnyx/types/text_to_speech_stream_params.py +++ /dev/null @@ -1,49 +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__ = ["TextToSpeechStreamParams"] - - -class TextToSpeechStreamParams(TypedDict, total=False): - audio_format: Literal["pcm", "wav"] - """Audio output format override. - - Supported for Telnyx `Natural`/`NaturalHD` models only. Accepted values: `pcm`, - `wav`. - """ - - disable_cache: bool - """When `true`, bypass the audio cache and generate fresh audio.""" - - model_id: str - """Model identifier for the chosen provider. - - Examples: `Natural`, `NaturalHD` (Telnyx); `Polly.Generative` (AWS). - """ - - provider: Literal["aws", "telnyx", "azure", "elevenlabs", "minimax", "murfai", "rime", "resemble"] - """TTS provider. - - Defaults to `telnyx` if not specified. Ignored when `voice` is provided. - """ - - socket_id: str - """Client-provided socket identifier for tracking. - - If not provided, one is generated server-side. - """ - - voice: str - """ - Voice identifier in the format `provider.model_id.voice_id` or - `provider.voice_id` (e.g. `telnyx.NaturalHD.Telnyx_Alloy` or - `azure.en-US-AvaMultilingualNeural`). When provided, the `provider`, `model_id`, - and `voice_id` are extracted automatically. Takes precedence over individual - `provider`/`model_id`/`voice_id` parameters. - """ - - voice_id: str - """Voice identifier for the chosen provider.""" diff --git a/tests/api_resources/conferences/test_actions.py b/tests/api_resources/conferences/test_actions.py index 1ea4ee48..c628fcaa 100644 --- a/tests/api_resources/conferences/test_actions.py +++ b/tests/api_resources/conferences/test_actions.py @@ -633,7 +633,6 @@ def test_method_record_start_with_all_params(self, client: Telnyx) -> None: action = client.conferences.actions.record_start( id="id", format="wav", - channels="dual", command_id="891510ac-f3e4-11e8-af5b-de00688a4901", custom_file_name="my_recording_file_name", play_beep=True, @@ -1624,7 +1623,6 @@ async def test_method_record_start_with_all_params(self, async_client: AsyncTeln action = await async_client.conferences.actions.record_start( id="id", format="wav", - channels="dual", command_id="891510ac-f3e4-11e8-af5b-de00688a4901", custom_file_name="my_recording_file_name", play_beep=True, diff --git a/tests/api_resources/test_text_to_speech.py b/tests/api_resources/test_text_to_speech.py index 19825e23..2db1196b 100644 --- a/tests/api_resources/test_text_to_speech.py +++ b/tests/api_resources/test_text_to_speech.py @@ -5,11 +5,21 @@ 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.types import TextToSpeechListVoicesResponse +from telnyx.types import ( + TextToSpeechListVoicesResponse, +) +from telnyx._response import ( + BinaryAPIResponse, + AsyncBinaryAPIResponse, + StreamedBinaryAPIResponse, + AsyncStreamedBinaryAPIResponse, +) base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -17,6 +27,51 @@ class TestTextToSpeech: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + @parametrize + @pytest.mark.respx(base_url=base_url) + def test_method_generate_speech(self, client: Telnyx, respx_mock: MockRouter) -> None: + respx_mock.post("/text-to-speech/speech").mock(return_value=httpx.Response(200, json={"foo": "bar"})) + text_to_speech = client.text_to_speech.generate_speech( + text="text", + voice="voice", + ) + assert text_to_speech.is_closed + assert text_to_speech.json() == {"foo": "bar"} + assert cast(Any, text_to_speech.is_closed) is True + assert isinstance(text_to_speech, BinaryAPIResponse) + + @parametrize + @pytest.mark.respx(base_url=base_url) + def test_raw_response_generate_speech(self, client: Telnyx, respx_mock: MockRouter) -> None: + respx_mock.post("/text-to-speech/speech").mock(return_value=httpx.Response(200, json={"foo": "bar"})) + + text_to_speech = client.text_to_speech.with_raw_response.generate_speech( + text="text", + voice="voice", + ) + + assert text_to_speech.is_closed is True + assert text_to_speech.http_request.headers.get("X-Stainless-Lang") == "python" + assert text_to_speech.json() == {"foo": "bar"} + assert isinstance(text_to_speech, BinaryAPIResponse) + + @parametrize + @pytest.mark.respx(base_url=base_url) + def test_streaming_response_generate_speech(self, client: Telnyx, respx_mock: MockRouter) -> None: + respx_mock.post("/text-to-speech/speech").mock(return_value=httpx.Response(200, json={"foo": "bar"})) + with client.text_to_speech.with_streaming_response.generate_speech( + text="text", + voice="voice", + ) as text_to_speech: + assert not text_to_speech.is_closed + assert text_to_speech.http_request.headers.get("X-Stainless-Lang") == "python" + + assert text_to_speech.json() == {"foo": "bar"} + assert cast(Any, text_to_speech.is_closed) is True + assert isinstance(text_to_speech, StreamedBinaryAPIResponse) + + assert cast(Any, text_to_speech.is_closed) is True + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_method_list_voices(self, client: Telnyx) -> None: @@ -54,53 +109,56 @@ def test_streaming_response_list_voices(self, client: Telnyx) -> None: assert cast(Any, response.is_closed) is True - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_method_stream(self, client: Telnyx) -> None: - text_to_speech = client.text_to_speech.stream() - assert text_to_speech is None - @pytest.mark.skip(reason="Mock server tests are disabled") +class TestAsyncTextToSpeech: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + @parametrize - def test_method_stream_with_all_params(self, client: Telnyx) -> None: - text_to_speech = client.text_to_speech.stream( - audio_format="pcm", - disable_cache=True, - model_id="model_id", - provider="aws", - socket_id="socket_id", + @pytest.mark.respx(base_url=base_url) + async def test_method_generate_speech(self, async_client: AsyncTelnyx, respx_mock: MockRouter) -> None: + respx_mock.post("/text-to-speech/speech").mock(return_value=httpx.Response(200, json={"foo": "bar"})) + text_to_speech = await async_client.text_to_speech.generate_speech( + text="text", voice="voice", - voice_id="voice_id", ) - assert text_to_speech is None + assert text_to_speech.is_closed + assert await text_to_speech.json() == {"foo": "bar"} + assert cast(Any, text_to_speech.is_closed) is True + assert isinstance(text_to_speech, AsyncBinaryAPIResponse) - @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - def test_raw_response_stream(self, client: Telnyx) -> None: - response = client.text_to_speech.with_raw_response.stream() + @pytest.mark.respx(base_url=base_url) + async def test_raw_response_generate_speech(self, async_client: AsyncTelnyx, respx_mock: MockRouter) -> None: + respx_mock.post("/text-to-speech/speech").mock(return_value=httpx.Response(200, json={"foo": "bar"})) - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - text_to_speech = response.parse() - assert text_to_speech is None - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_streaming_response_stream(self, client: Telnyx) -> None: - with client.text_to_speech.with_streaming_response.stream() as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" + text_to_speech = await async_client.text_to_speech.with_raw_response.generate_speech( + text="text", + voice="voice", + ) - text_to_speech = response.parse() - assert text_to_speech is None + assert text_to_speech.is_closed is True + assert text_to_speech.http_request.headers.get("X-Stainless-Lang") == "python" + assert await text_to_speech.json() == {"foo": "bar"} + assert isinstance(text_to_speech, AsyncBinaryAPIResponse) - assert cast(Any, response.is_closed) is True + @parametrize + @pytest.mark.respx(base_url=base_url) + async def test_streaming_response_generate_speech(self, async_client: AsyncTelnyx, respx_mock: MockRouter) -> None: + respx_mock.post("/text-to-speech/speech").mock(return_value=httpx.Response(200, json={"foo": "bar"})) + async with async_client.text_to_speech.with_streaming_response.generate_speech( + text="text", + voice="voice", + ) as text_to_speech: + assert not text_to_speech.is_closed + assert text_to_speech.http_request.headers.get("X-Stainless-Lang") == "python" + assert await text_to_speech.json() == {"foo": "bar"} + assert cast(Any, text_to_speech.is_closed) is True + assert isinstance(text_to_speech, AsyncStreamedBinaryAPIResponse) -class TestAsyncTextToSpeech: - parametrize = pytest.mark.parametrize( - "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] - ) + assert cast(Any, text_to_speech.is_closed) is True @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -138,45 +196,3 @@ async def test_streaming_response_list_voices(self, async_client: AsyncTelnyx) - assert_matches_type(TextToSpeechListVoicesResponse, text_to_speech, path=["response"]) assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_method_stream(self, async_client: AsyncTelnyx) -> None: - text_to_speech = await async_client.text_to_speech.stream() - assert text_to_speech is None - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_method_stream_with_all_params(self, async_client: AsyncTelnyx) -> None: - text_to_speech = await async_client.text_to_speech.stream( - audio_format="pcm", - disable_cache=True, - model_id="model_id", - provider="aws", - socket_id="socket_id", - voice="voice", - voice_id="voice_id", - ) - assert text_to_speech is None - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_raw_response_stream(self, async_client: AsyncTelnyx) -> None: - response = await async_client.text_to_speech.with_raw_response.stream() - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - text_to_speech = await response.parse() - assert text_to_speech is None - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_streaming_response_stream(self, async_client: AsyncTelnyx) -> None: - async with async_client.text_to_speech.with_streaming_response.stream() as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - text_to_speech = await response.parse() - assert text_to_speech is None - - assert cast(Any, response.is_closed) is True From ef54d1bf9e80441af3a43b33aa0b850ec48b1750 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 26 Feb 2026 17:59:58 +0000 Subject: [PATCH 5/5] release: 4.53.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 04014e1d..9b75df70 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "4.52.0" + ".": "4.53.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 55998159..169435af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## 4.53.0 (2026-02-26) + +Full Changelog: [v4.52.0...v4.53.0](https://github.com/team-telnyx/telnyx-python/compare/v4.52.0...v4.53.0) + +### Features + +* **api:** manual updates ([f14db77](https://github.com/team-telnyx/telnyx-python/commit/f14db77cd98183ca8919771c2ba9d01c7f9dacfc)) + ## 4.52.0 (2026-02-26) Full Changelog: [v4.51.0...v4.52.0](https://github.com/team-telnyx/telnyx-python/compare/v4.51.0...v4.52.0) diff --git a/pyproject.toml b/pyproject.toml index 5cefb405..08504cd6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "telnyx" -version = "4.52.0" +version = "4.53.0" description = "Telnyx API SDK for global Voice, SMS, MMS, WhatsApp, Fax, Wireless IoT, SIP Trunking, and Call Control." dynamic = ["readme"] license = "MIT" diff --git a/src/telnyx/_version.py b/src/telnyx/_version.py index 4011b841..2592ed1b 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.52.0" # x-release-please-version +__version__ = "4.53.0" # x-release-please-version