From 4e46e8ceb9468bd2512430d8c3448af94b17c865 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Wed, 25 Feb 2026 21:04:45 +0000
Subject: [PATCH 1/3] codegen metadata
---
.stats.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 59c2b6bf..f28fab45 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-902a5f08430969510f0127e6985bb631c0c928b80d14b6f75ec8b71bd7c397b5.yml
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/telnyx%2Ftelnyx-46d2b18a142f548ea52a09d0be15f01dc026cbe1c8aeaa0576bbbf9516d1edfa.yml
openapi_spec_hash: 515f3d122ed486daa3f9a90a252908c8
-config_hash: 6f6c7ba66f40d55677e28da77c03ea96
+config_hash: 5fe73f94aace4c5e5996ce2eb60ac097
From 7c4e7096921ae6e07ede51b783711bbdcd9c088a Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 26 Feb 2026 12:10:21 +0000
Subject: [PATCH 2/3] feat: Add text-to-speech WebSocket streaming OpenAPI spec
---
.stats.yml | 6 +-
api.md | 11 +-
src/telnyx/resources/queues/queues.py | 14 +-
src/telnyx/resources/text_to_speech.py | 284 +++++++++++-------
src/telnyx/types/__init__.py | 4 +-
src/telnyx/types/queue_create_response.py | 34 ++-
.../{queue.py => queue_list_response.py} | 4 +-
src/telnyx/types/queue_retrieve_response.py | 34 ++-
src/telnyx/types/queue_update_response.py | 34 ++-
.../text_to_speech_generate_speech_params.py | 26 --
.../types/text_to_speech_stream_params.py | 49 +++
tests/api_resources/test_queues.py | 18 +-
tests/api_resources/test_text_to_speech.py | 174 +++++------
13 files changed, 428 insertions(+), 264 deletions(-)
rename src/telnyx/types/{queue.py => queue_list_response.py} (91%)
delete mode 100644 src/telnyx/types/text_to_speech_generate_speech_params.py
create mode 100644 src/telnyx/types/text_to_speech_stream_params.py
diff --git a/.stats.yml b/.stats.yml
index f28fab45..6eb74933 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-46d2b18a142f548ea52a09d0be15f01dc026cbe1c8aeaa0576bbbf9516d1edfa.yml
-openapi_spec_hash: 515f3d122ed486daa3f9a90a252908c8
-config_hash: 5fe73f94aace4c5e5996ce2eb60ac097
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/telnyx%2Ftelnyx-619f2e4cc820442ae564e2345323abd65d5049b428c5780cf9f14c56002a2ba3.yml
+openapi_spec_hash: 29de78582d8561745ff8f5f6c2474f1e
+config_hash: 535b049bef73708a7530337b14fd0b84
diff --git a/api.md b/api.md
index ffcc76d7..5902c352 100644
--- a/api.md
+++ b/api.md
@@ -3544,7 +3544,12 @@ Methods:
Types:
```python
-from telnyx.types import Queue, QueueCreateResponse, QueueRetrieveResponse, QueueUpdateResponse
+from telnyx.types import (
+ QueueCreateResponse,
+ QueueRetrieveResponse,
+ QueueUpdateResponse,
+ QueueListResponse,
+)
```
Methods:
@@ -3552,7 +3557,7 @@ Methods:
- client.queues.create(\*\*params) -> QueueCreateResponse
- client.queues.retrieve(queue_name) -> QueueRetrieveResponse
- client.queues.update(queue_name, \*\*params) -> QueueUpdateResponse
-- client.queues.list(\*\*params) -> SyncDefaultFlatPagination[Queue]
+- client.queues.list(\*\*params) -> SyncDefaultFlatPagination[QueueListResponse]
- client.queues.delete(queue_name) -> None
## Calls
@@ -4464,8 +4469,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/queues/queues.py b/src/telnyx/resources/queues/queues.py
index 648dd6e9..2a62a667 100644
--- a/src/telnyx/resources/queues/queues.py
+++ b/src/telnyx/resources/queues/queues.py
@@ -24,8 +24,8 @@
async_to_streamed_response_wrapper,
)
from ...pagination import SyncDefaultFlatPagination, AsyncDefaultFlatPagination
-from ...types.queue import Queue
from ..._base_client import AsyncPaginator, make_request_options
+from ...types.queue_list_response import QueueListResponse
from ...types.queue_create_response import QueueCreateResponse
from ...types.queue_update_response import QueueUpdateResponse
from ...types.queue_retrieve_response import QueueRetrieveResponse
@@ -182,7 +182,7 @@ def list(
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> SyncDefaultFlatPagination[Queue]:
+ ) -> SyncDefaultFlatPagination[QueueListResponse]:
"""
List all queues for the authenticated user.
@@ -201,7 +201,7 @@ def list(
"""
return self._get_api_list(
"/queues",
- page=SyncDefaultFlatPagination[Queue],
+ page=SyncDefaultFlatPagination[QueueListResponse],
options=make_request_options(
extra_headers=extra_headers,
extra_query=extra_query,
@@ -215,7 +215,7 @@ def list(
queue_list_params.QueueListParams,
),
),
- model=Queue,
+ model=QueueListResponse,
)
def delete(
@@ -402,7 +402,7 @@ def list(
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> AsyncPaginator[Queue, AsyncDefaultFlatPagination[Queue]]:
+ ) -> AsyncPaginator[QueueListResponse, AsyncDefaultFlatPagination[QueueListResponse]]:
"""
List all queues for the authenticated user.
@@ -421,7 +421,7 @@ def list(
"""
return self._get_api_list(
"/queues",
- page=AsyncDefaultFlatPagination[Queue],
+ page=AsyncDefaultFlatPagination[QueueListResponse],
options=make_request_options(
extra_headers=extra_headers,
extra_query=extra_query,
@@ -435,7 +435,7 @@ def list(
queue_list_params.QueueListParams,
),
),
- model=Queue,
+ model=QueueListResponse,
)
async def delete(
diff --git a/src/telnyx/resources/text_to_speech.py b/src/telnyx/resources/text_to_speech.py
index 7e37a6f5..4b9ff0e3 100644
--- a/src/telnyx/resources/text_to_speech.py
+++ b/src/telnyx/resources/text_to_speech.py
@@ -6,24 +6,16 @@
import httpx
-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 ..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 .._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
@@ -51,36 +43,25 @@ def with_streaming_response(self) -> TextToSpeechResourceWithStreamingResponse:
"""
return TextToSpeechResourceWithStreamingResponse(self)
- def generate_speech(
+ def list_voices(
self,
*,
- text: str,
- voice: str,
+ 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,
- ) -> BinaryAPIResponse:
+ ) -> TextToSpeechListVoicesResponse:
"""
- Converts the provided text to speech using the specified voice and returns audio
- data
+ Returns a list of voices that can be used with the text to speech commands.
Args:
- text: The text to convert to speech
-
- 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
+ elevenlabs_api_key_ref: Reference to your ElevenLabs API key stored in the Telnyx Portal
- Use the `GET /text-to-speech/voices` endpoint to get a complete list of
- available voices.
+ provider: Filter voices by provider
extra_headers: Send extra headers
@@ -90,41 +71,86 @@ def generate_speech(
timeout: Override the client-level default timeout for this request, in seconds
"""
- 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,
- ),
+ return self._get(
+ "/text-to-speech/voices",
options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {
+ "elevenlabs_api_key_ref": elevenlabs_api_key_ref,
+ "provider": provider,
+ },
+ text_to_speech_list_voices_params.TextToSpeechListVoicesParams,
+ ),
),
- cast_to=BinaryAPIResponse,
+ cast_to=TextToSpeechListVoicesResponse,
)
- def list_voices(
+ def stream(
self,
*,
- elevenlabs_api_key_ref: str | Omit = omit,
- provider: Literal["aws", "azure", "elevenlabs", "telnyx"] | Omit = omit,
+ 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,
# 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:
+ ) -> None:
"""
- Returns a list of voices that can be used with the text to speech commands.
+ 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.
Args:
- elevenlabs_api_key_ref: Reference to your ElevenLabs API key stored in the Telnyx Portal
+ audio_format: Audio output format override. Supported for Telnyx `Natural`/`NaturalHD` models
+ only. Accepted values: `pcm`, `wav`.
- provider: Filter voices by provider
+ 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.
+
+ voice_id: Voice identifier for the chosen provider.
extra_headers: Send extra headers
@@ -134,8 +160,9 @@ def list_voices(
timeout: Override the client-level default timeout for this request, in seconds
"""
+ extra_headers = {"Accept": "*/*", **(extra_headers or {})}
return self._get(
- "/text-to-speech/voices",
+ "/text-to-speech/speech",
options=make_request_options(
extra_headers=extra_headers,
extra_query=extra_query,
@@ -143,13 +170,18 @@ def list_voices(
timeout=timeout,
query=maybe_transform(
{
- "elevenlabs_api_key_ref": elevenlabs_api_key_ref,
+ "audio_format": audio_format,
+ "disable_cache": disable_cache,
+ "model_id": model_id,
"provider": provider,
+ "socket_id": socket_id,
+ "voice": voice,
+ "voice_id": voice_id,
},
- text_to_speech_list_voices_params.TextToSpeechListVoicesParams,
+ text_to_speech_stream_params.TextToSpeechStreamParams,
),
),
- cast_to=TextToSpeechListVoicesResponse,
+ cast_to=NoneType,
)
@@ -173,36 +205,25 @@ def with_streaming_response(self) -> AsyncTextToSpeechResourceWithStreamingRespo
"""
return AsyncTextToSpeechResourceWithStreamingResponse(self)
- async def generate_speech(
+ async def list_voices(
self,
*,
- text: str,
- voice: str,
+ 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,
- ) -> AsyncBinaryAPIResponse:
+ ) -> TextToSpeechListVoicesResponse:
"""
- Converts the provided text to speech using the specified voice and returns audio
- data
+ Returns a list of voices that can be used with the text to speech commands.
Args:
- text: The text to convert to speech
-
- 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
+ elevenlabs_api_key_ref: Reference to your ElevenLabs API key stored in the Telnyx Portal
- Use the `GET /text-to-speech/voices` endpoint to get a complete list of
- available voices.
+ provider: Filter voices by provider
extra_headers: Send extra headers
@@ -212,41 +233,86 @@ async def generate_speech(
timeout: Override the client-level default timeout for this request, in seconds
"""
- 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,
- ),
+ return await self._get(
+ "/text-to-speech/voices",
options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=await async_maybe_transform(
+ {
+ "elevenlabs_api_key_ref": elevenlabs_api_key_ref,
+ "provider": provider,
+ },
+ text_to_speech_list_voices_params.TextToSpeechListVoicesParams,
+ ),
),
- cast_to=AsyncBinaryAPIResponse,
+ cast_to=TextToSpeechListVoicesResponse,
)
- async def list_voices(
+ async def stream(
self,
*,
- elevenlabs_api_key_ref: str | Omit = omit,
- provider: Literal["aws", "azure", "elevenlabs", "telnyx"] | Omit = omit,
+ 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,
# 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:
+ ) -> None:
"""
- Returns a list of voices that can be used with the text to speech commands.
+ 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.
Args:
- elevenlabs_api_key_ref: Reference to your ElevenLabs API key stored in the Telnyx Portal
+ audio_format: Audio output format override. Supported for Telnyx `Natural`/`NaturalHD` models
+ only. Accepted values: `pcm`, `wav`.
- provider: Filter voices by provider
+ 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.
+
+ voice_id: Voice identifier for the chosen provider.
extra_headers: Send extra headers
@@ -256,8 +322,9 @@ async def list_voices(
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/voices",
+ "/text-to-speech/speech",
options=make_request_options(
extra_headers=extra_headers,
extra_query=extra_query,
@@ -265,13 +332,18 @@ async def list_voices(
timeout=timeout,
query=await async_maybe_transform(
{
- "elevenlabs_api_key_ref": elevenlabs_api_key_ref,
+ "audio_format": audio_format,
+ "disable_cache": disable_cache,
+ "model_id": model_id,
"provider": provider,
+ "socket_id": socket_id,
+ "voice": voice,
+ "voice_id": voice_id,
},
- text_to_speech_list_voices_params.TextToSpeechListVoicesParams,
+ text_to_speech_stream_params.TextToSpeechStreamParams,
),
),
- cast_to=TextToSpeechListVoicesResponse,
+ cast_to=NoneType,
)
@@ -279,49 +351,45 @@ 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 10f0b762..976846fe 100644
--- a/src/telnyx/types/__init__.py
+++ b/src/telnyx/types/__init__.py
@@ -8,7 +8,6 @@
from .fax import Fax as Fax
from .fqdn import Fqdn as Fqdn
from .room import Room as Room
-from .queue import Queue as Queue
from .record import Record as Record
from .shared import (
APIError as APIError,
@@ -171,6 +170,7 @@
from .outbound_fqdn_param import OutboundFqdnParam as OutboundFqdnParam
from .portout_list_params import PortoutListParams as PortoutListParams
from .queue_create_params import QueueCreateParams as QueueCreateParams
+from .queue_list_response import QueueListResponse as QueueListResponse
from .queue_update_params import QueueUpdateParams as QueueUpdateParams
from .replaced_link_click import ReplacedLinkClick as ReplacedLinkClick
from .verify_profile_data import VerifyProfileData as VerifyProfileData
@@ -437,6 +437,7 @@
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
@@ -830,7 +831,6 @@
)
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/queue_create_response.py b/src/telnyx/types/queue_create_response.py
index 987b3918..15bb5301 100644
--- a/src/telnyx/types/queue_create_response.py
+++ b/src/telnyx/types/queue_create_response.py
@@ -1,12 +1,40 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
from typing import Optional
+from typing_extensions import Literal
-from .queue import Queue
from .._models import BaseModel
-__all__ = ["QueueCreateResponse"]
+__all__ = ["QueueCreateResponse", "Data"]
+
+
+class Data(BaseModel):
+ id: str
+ """Uniquely identifies the queue"""
+
+ average_wait_time_secs: int
+ """
+ The average time that the calls currently in the queue have spent waiting, given
+ in seconds.
+ """
+
+ created_at: str
+ """ISO 8601 formatted date of when the queue was created"""
+
+ current_size: int
+ """The number of calls currently in the queue"""
+
+ max_size: int
+ """The maximum number of calls allowed in the queue"""
+
+ name: str
+ """Name of the queue"""
+
+ record_type: Literal["queue"]
+
+ updated_at: str
+ """ISO 8601 formatted date of when the queue was last updated"""
class QueueCreateResponse(BaseModel):
- data: Optional[Queue] = None
+ data: Optional[Data] = None
diff --git a/src/telnyx/types/queue.py b/src/telnyx/types/queue_list_response.py
similarity index 91%
rename from src/telnyx/types/queue.py
rename to src/telnyx/types/queue_list_response.py
index 24e4c6ce..888ee525 100644
--- a/src/telnyx/types/queue.py
+++ b/src/telnyx/types/queue_list_response.py
@@ -4,10 +4,10 @@
from .._models import BaseModel
-__all__ = ["Queue"]
+__all__ = ["QueueListResponse"]
-class Queue(BaseModel):
+class QueueListResponse(BaseModel):
id: str
"""Uniquely identifies the queue"""
diff --git a/src/telnyx/types/queue_retrieve_response.py b/src/telnyx/types/queue_retrieve_response.py
index f51d426d..2136e305 100644
--- a/src/telnyx/types/queue_retrieve_response.py
+++ b/src/telnyx/types/queue_retrieve_response.py
@@ -1,12 +1,40 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
from typing import Optional
+from typing_extensions import Literal
-from .queue import Queue
from .._models import BaseModel
-__all__ = ["QueueRetrieveResponse"]
+__all__ = ["QueueRetrieveResponse", "Data"]
+
+
+class Data(BaseModel):
+ id: str
+ """Uniquely identifies the queue"""
+
+ average_wait_time_secs: int
+ """
+ The average time that the calls currently in the queue have spent waiting, given
+ in seconds.
+ """
+
+ created_at: str
+ """ISO 8601 formatted date of when the queue was created"""
+
+ current_size: int
+ """The number of calls currently in the queue"""
+
+ max_size: int
+ """The maximum number of calls allowed in the queue"""
+
+ name: str
+ """Name of the queue"""
+
+ record_type: Literal["queue"]
+
+ updated_at: str
+ """ISO 8601 formatted date of when the queue was last updated"""
class QueueRetrieveResponse(BaseModel):
- data: Optional[Queue] = None
+ data: Optional[Data] = None
diff --git a/src/telnyx/types/queue_update_response.py b/src/telnyx/types/queue_update_response.py
index dee8a551..ab97b4da 100644
--- a/src/telnyx/types/queue_update_response.py
+++ b/src/telnyx/types/queue_update_response.py
@@ -1,12 +1,40 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
from typing import Optional
+from typing_extensions import Literal
-from .queue import Queue
from .._models import BaseModel
-__all__ = ["QueueUpdateResponse"]
+__all__ = ["QueueUpdateResponse", "Data"]
+
+
+class Data(BaseModel):
+ id: str
+ """Uniquely identifies the queue"""
+
+ average_wait_time_secs: int
+ """
+ The average time that the calls currently in the queue have spent waiting, given
+ in seconds.
+ """
+
+ created_at: str
+ """ISO 8601 formatted date of when the queue was created"""
+
+ current_size: int
+ """The number of calls currently in the queue"""
+
+ max_size: int
+ """The maximum number of calls allowed in the queue"""
+
+ name: str
+ """Name of the queue"""
+
+ record_type: Literal["queue"]
+
+ updated_at: str
+ """ISO 8601 formatted date of when the queue was last updated"""
class QueueUpdateResponse(BaseModel):
- data: Optional[Queue] = None
+ data: Optional[Data] = None
diff --git a/src/telnyx/types/text_to_speech_generate_speech_params.py b/src/telnyx/types/text_to_speech_generate_speech_params.py
deleted file mode 100644
index 95b43e53..00000000
--- a/src/telnyx/types/text_to_speech_generate_speech_params.py
+++ /dev/null
@@ -1,26 +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__ = ["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
new file mode 100644
index 00000000..9a4aac90
--- /dev/null
+++ b/src/telnyx/types/text_to_speech_stream_params.py
@@ -0,0 +1,49 @@
+# 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/test_queues.py b/tests/api_resources/test_queues.py
index ef672dcf..8caf76ab 100644
--- a/tests/api_resources/test_queues.py
+++ b/tests/api_resources/test_queues.py
@@ -10,7 +10,7 @@
from telnyx import Telnyx, AsyncTelnyx
from tests.utils import assert_matches_type
from telnyx.types import (
- Queue,
+ QueueListResponse,
QueueCreateResponse,
QueueUpdateResponse,
QueueRetrieveResponse,
@@ -158,7 +158,7 @@ def test_path_params_update(self, client: Telnyx) -> None:
@parametrize
def test_method_list(self, client: Telnyx) -> None:
queue = client.queues.list()
- assert_matches_type(SyncDefaultFlatPagination[Queue], queue, path=["response"])
+ assert_matches_type(SyncDefaultFlatPagination[QueueListResponse], queue, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -167,7 +167,7 @@ def test_method_list_with_all_params(self, client: Telnyx) -> None:
page_number=1,
page_size=1,
)
- assert_matches_type(SyncDefaultFlatPagination[Queue], queue, path=["response"])
+ assert_matches_type(SyncDefaultFlatPagination[QueueListResponse], queue, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -177,7 +177,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"
queue = response.parse()
- assert_matches_type(SyncDefaultFlatPagination[Queue], queue, path=["response"])
+ assert_matches_type(SyncDefaultFlatPagination[QueueListResponse], queue, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -187,7 +187,7 @@ def test_streaming_response_list(self, client: Telnyx) -> None:
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
queue = response.parse()
- assert_matches_type(SyncDefaultFlatPagination[Queue], queue, path=["response"])
+ assert_matches_type(SyncDefaultFlatPagination[QueueListResponse], queue, path=["response"])
assert cast(Any, response.is_closed) is True
@@ -374,7 +374,7 @@ async def test_path_params_update(self, async_client: AsyncTelnyx) -> None:
@parametrize
async def test_method_list(self, async_client: AsyncTelnyx) -> None:
queue = await async_client.queues.list()
- assert_matches_type(AsyncDefaultFlatPagination[Queue], queue, path=["response"])
+ assert_matches_type(AsyncDefaultFlatPagination[QueueListResponse], queue, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -383,7 +383,7 @@ async def test_method_list_with_all_params(self, async_client: AsyncTelnyx) -> N
page_number=1,
page_size=1,
)
- assert_matches_type(AsyncDefaultFlatPagination[Queue], queue, path=["response"])
+ assert_matches_type(AsyncDefaultFlatPagination[QueueListResponse], queue, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -393,7 +393,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"
queue = await response.parse()
- assert_matches_type(AsyncDefaultFlatPagination[Queue], queue, path=["response"])
+ assert_matches_type(AsyncDefaultFlatPagination[QueueListResponse], queue, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -403,7 +403,7 @@ async def test_streaming_response_list(self, async_client: AsyncTelnyx) -> None:
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
queue = await response.parse()
- assert_matches_type(AsyncDefaultFlatPagination[Queue], queue, path=["response"])
+ assert_matches_type(AsyncDefaultFlatPagination[QueueListResponse], queue, path=["response"])
assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/test_text_to_speech.py b/tests/api_resources/test_text_to_speech.py
index 2db1196b..19825e23 100644
--- a/tests/api_resources/test_text_to_speech.py
+++ b/tests/api_resources/test_text_to_speech.py
@@ -5,21 +5,11 @@
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._response import (
- BinaryAPIResponse,
- AsyncBinaryAPIResponse,
- StreamedBinaryAPIResponse,
- AsyncStreamedBinaryAPIResponse,
-)
+from telnyx.types import TextToSpeechListVoicesResponse
base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
@@ -27,51 +17,6 @@
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:
@@ -109,56 +54,53 @@ 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
-class TestAsyncTextToSpeech:
- 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
- @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",
+ 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",
voice="voice",
+ voice_id="voice_id",
)
- 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)
+ assert text_to_speech is None
+ @pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
- @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"}))
+ def test_raw_response_stream(self, client: Telnyx) -> None:
+ response = client.text_to_speech.with_raw_response.stream()
- text_to_speech = await async_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 await text_to_speech.json() == {"foo": "bar"}
- assert isinstance(text_to_speech, AsyncBinaryAPIResponse)
+ 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
- @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"
+ 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 = response.parse()
+ assert text_to_speech is None
+
+ assert cast(Any, response.is_closed) is True
- assert await text_to_speech.json() == {"foo": "bar"}
- assert cast(Any, text_to_speech.is_closed) is True
- assert isinstance(text_to_speech, AsyncStreamedBinaryAPIResponse)
- assert cast(Any, text_to_speech.is_closed) is True
+class TestAsyncTextToSpeech:
+ 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
@@ -196,3 +138,45 @@ 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 a86a1d8b6f7976a50cf23b2d527581d435bd50a2 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 26 Feb 2026 12:10:46 +0000
Subject: [PATCH 3/3] release: 4.50.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 d351f029..2e339e66 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "4.49.0"
+ ".": "4.50.0"
}
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a5703c1b..eff1182d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,13 @@
# Changelog
+## 4.50.0 (2026-02-26)
+
+Full Changelog: [v4.49.0...v4.50.0](https://github.com/team-telnyx/telnyx-python/compare/v4.49.0...v4.50.0)
+
+### Features
+
+* Add text-to-speech WebSocket streaming OpenAPI spec ([7c4e709](https://github.com/team-telnyx/telnyx-python/commit/7c4e7096921ae6e07ede51b783711bbdcd9c088a))
+
## 4.49.0 (2026-02-25)
Full Changelog: [v4.48.0...v4.49.0](https://github.com/team-telnyx/telnyx-python/compare/v4.48.0...v4.49.0)
diff --git a/pyproject.toml b/pyproject.toml
index d9296359..06480867 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "telnyx"
-version = "4.49.0"
+version = "4.50.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 32d6f397..576133ab 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.49.0" # x-release-please-version
+__version__ = "4.50.0" # x-release-please-version