diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index 28a64b708..8e79f95c6 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "4.180.0"
+ ".": "4.181.0"
}
\ No newline at end of file
diff --git a/.stats.yml b/.stats.yml
index d0e375fdc..52f1034fa 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1 +1 @@
-configured_endpoints: 1256
+configured_endpoints: 1268
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4fc124d9a..c87690b38 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,12 @@
# Changelog
+## [4.181.0](https://github.com/team-telnyx/telnyx-python/compare/v4.180.0...v4.181.0) (2026-09-23)
+
+
+### Features
+
+* promote from staging f1f53a1 ([fde2e3f](https://github.com/team-telnyx/telnyx-python/commit/fde2e3fa65abf37492695ecea1e646dbfab87c28))
+
## [4.180.0](https://github.com/team-telnyx/telnyx-python/compare/v4.179.0...v4.180.0) (2026-09-13)
diff --git a/api.md b/api.md
index e1e4fdd12..d3663fb39 100644
--- a/api.md
+++ b/api.md
@@ -326,6 +326,7 @@ from telnyx.types import (
FaxSendingStarted,
InboundMessage,
InboundSipHeader,
+ MessagingInboundMessage,
NumberOrderStatusUpdate,
OutboundMessage,
ReplacedLinkClick,
@@ -844,7 +845,7 @@ Methods:
Types:
```python
-from telnyx.types.ai import AudioTranscribeResponse
+from telnyx.types.ai import AudioTranscriptionResponseWord, AudioTranscribeResponse
```
Methods:
@@ -1286,7 +1287,7 @@ Methods:
Types:
```python
-from telnyx.types.ai.openai import ChatCreateCompletionResponse
+from telnyx.types.ai.openai import FunctionDefinition, ChatCreateCompletionResponse
```
Methods:
@@ -1337,6 +1338,20 @@ Methods:
- client.ai.knowledge.collections.retrieve_documents(slug, \*\*params) -> CollectionRetrieveDocumentsResponse
+## Typesafe
+
+### V1
+
+Types:
+
+```python
+from telnyx.types.ai.typesafe import V1SystemoneResponse
+```
+
+Methods:
+
+- client.ai.typesafe.v1.systemone(\*\*params) -> V1SystemoneResponse
+
# AuditEvents
Types:
@@ -1823,7 +1838,12 @@ Methods:
Types:
```python
-from telnyx.types import Connection, ConnectionRetrieveResponse, ConnectionListActiveCallsResponse
+from telnyx.types import (
+ Connection,
+ ConnectionRetrieveResponse,
+ ConnectionListActiveCallsResponse,
+ ConnectionRetrieveCountResponse,
+)
```
Methods:
@@ -1831,6 +1851,7 @@ Methods:
- client.connections.retrieve(id) -> ConnectionRetrieveResponse
- client.connections.list(\*\*params) -> SyncDefaultFlatPagination[Connection]
- client.connections.list_active_calls(connection_id, \*\*params) -> SyncDefaultFlatPagination[ConnectionListActiveCallsResponse]
+- client.connections.retrieve_count() -> ConnectionRetrieveCountResponse
# CountryCoverage
@@ -4773,6 +4794,18 @@ Methods:
- client.texml.initiate_ai_call(connection_id, \*\*params) -> TexmlInitiateAICallResponse
- client.texml.secrets(\*\*params) -> TexmlSecretsResponse
+## Calls
+
+Types:
+
+```python
+from telnyx.types.texml import CallCreateResponse
+```
+
+Methods:
+
+- client.texml.calls.create(connection_id, \*\*params) -> CallCreateResponse
+
## Accounts
Types:
@@ -6826,7 +6859,82 @@ from telnyx.types.compute import (
Methods:
-- client.compute.funcs.retrieve_logs(id, \*\*params) -> FuncRetrieveLogsResponse
-- client.compute.funcs.retrieve_metric_aggregates(id, \*\*params) -> FuncRetrieveMetricAggregatesResponse
-- client.compute.funcs.retrieve_revisions(id, \*\*params) -> FuncRetrieveRevisionsResponse
-- client.compute.funcs.retrieve_ship_inspection(id) -> FuncRetrieveShipInspectionResponse
+- client.compute.funcs.retrieve_logs(id, \*\*params) -> FuncRetrieveLogsResponse
+- client.compute.funcs.retrieve_metric_aggregates(id, \*\*params) -> FuncRetrieveMetricAggregatesResponse
+- client.compute.funcs.retrieve_revisions(id, \*\*params) -> FuncRetrieveRevisionsResponse
+- client.compute.funcs.retrieve_ship_inspection(id) -> FuncRetrieveShipInspectionResponse
+
+### Export
+
+Types:
+
+```python
+from telnyx.types.compute.funcs import FuncLogExportConfigResponse
+```
+
+Methods:
+
+- client.compute.funcs.export.create(id, \*\*params) -> FuncLogExportConfigResponse
+- client.compute.funcs.export.list(id) -> FuncLogExportConfigResponse
+- client.compute.funcs.export.delete_all(id) -> None
+
+# NoiseSuppressionEngines
+
+Types:
+
+```python
+from telnyx.types import NoiseSuppressionEngineListResponse
+```
+
+Methods:
+
+- client.noise_suppression_engines.list() -> NoiseSuppressionEngineListResponse
+
+# BotChallenge
+
+Types:
+
+```python
+from telnyx.types import BotChallengeCreateResponse
+```
+
+Methods:
+
+- client.bot_challenge.create(\*\*params) -> BotChallengeCreateResponse
+
+# BotSessions
+
+Types:
+
+```python
+from telnyx.types import BotSessionListResponse
+```
+
+Methods:
+
+- client.bot_sessions.list(\*\*params) -> BotSessionListResponse
+
+# BotSignup
+
+Types:
+
+```python
+from telnyx.types import SuccessResponse
+```
+
+Methods:
+
+- client.bot_signup.create(\*\*params) -> SuccessResponse
+- client.bot_signup.resend_magic_link(\*\*params) -> SuccessResponse
+
+# MachinePayments
+
+Types:
+
+```python
+from telnyx.types import MachinePaymentAccountCreditResponse
+```
+
+Methods:
+
+- client.machine_payments.account_credit(\*\*params) -> MachinePaymentAccountCreditResponse
diff --git a/pyproject.toml b/pyproject.toml
index ab8d35410..9f250f1e5 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "telnyx"
-version = "4.180.0"
+version = "4.181.0"
description = "The official Python library for the telnyx API"
dynamic = ["readme"]
license = "MIT"
diff --git a/src/telnyx/_client.py b/src/telnyx/_client.py
index 11c29ae54..8a9e789f8 100644
--- a/src/telnyx/_client.py
+++ b/src/telnyx/_client.py
@@ -74,6 +74,7 @@
messaging,
sim_cards,
user_tags,
+ bot_signup,
global_ips,
recordings,
reputation,
@@ -86,12 +87,14 @@
ota_updates,
short_codes,
audit_events,
+ bot_sessions,
call_reasons,
email_blocks,
email_events,
oauth_grants,
requirements,
voice_clones,
+ bot_challenge,
channel_zones,
email_domains,
email_inboxes,
@@ -130,6 +133,7 @@
fax_applications,
fqdn_connections,
inbound_channels,
+ machine_payments,
managed_accounts,
meeting_sessions,
network_coverage,
@@ -201,6 +205,7 @@
sub_number_orders_report,
call_control_applications,
messaging_profile_metrics,
+ noise_suppression_engines,
private_wireless_gateways,
wireless_blocklist_values,
custom_storage_credentials,
@@ -237,6 +242,7 @@
from .resources.documents import DocumentsResource, AsyncDocumentsResource
from .resources.user_tags import UserTagsResource, AsyncUserTagsResource
from .resources.x402.x402 import X402Resource, AsyncX402Resource
+ from .resources.bot_signup import BotSignupResource, AsyncBotSignupResource
from .resources.global_ips import GlobalIPsResource, AsyncGlobalIPsResource
from .resources.well_known import WellKnownResource, AsyncWellKnownResource
from .resources.call_events import CallEventsResource, AsyncCallEventsResource
@@ -248,11 +254,13 @@
from .resources.short_codes import ShortCodesResource, AsyncShortCodesResource
from .resources.texml.texml import TexmlResource, AsyncTexmlResource
from .resources.audit_events import AuditEventsResource, AsyncAuditEventsResource
+ from .resources.bot_sessions import BotSessionsResource, AsyncBotSessionsResource
from .resources.call_reasons import CallReasonsResource, AsyncCallReasonsResource
from .resources.email_events import EmailEventsResource, AsyncEmailEventsResource
from .resources.oauth_grants import OAuthGrantsResource, AsyncOAuthGrantsResource
from .resources.requirements import RequirementsResource, AsyncRequirementsResource
from .resources.voice_clones import VoiceClonesResource, AsyncVoiceClonesResource
+ from .resources.bot_challenge import BotChallengeResource, AsyncBotChallengeResource
from .resources.channel_zones import ChannelZonesResource, AsyncChannelZonesResource
from .resources.email_threads import EmailThreadsResource, AsyncEmailThreadsResource
from .resources.legacy.legacy import LegacyResource, AsyncLegacyResource
@@ -288,6 +296,7 @@
from .resources.country_coverage import CountryCoverageResource, AsyncCountryCoverageResource
from .resources.fax_applications import FaxApplicationsResource, AsyncFaxApplicationsResource
from .resources.inbound_channels import InboundChannelsResource, AsyncInboundChannelsResource
+ from .resources.machine_payments import MachinePaymentsResource, AsyncMachinePaymentsResource
from .resources.network_coverage import NetworkCoverageResource, AsyncNetworkCoverageResource
from .resources.numbers_features import NumbersFeaturesResource, AsyncNumbersFeaturesResource
from .resources.access_ip_address import AccessIPAddressResource, AsyncAccessIPAddressResource
@@ -369,6 +378,10 @@
MessagingProfileMetricsResource,
AsyncMessagingProfileMetricsResource,
)
+ from .resources.noise_suppression_engines import (
+ NoiseSuppressionEnginesResource,
+ AsyncNoiseSuppressionEnginesResource,
+ )
from .resources.private_wireless_gateways import (
PrivateWirelessGatewaysResource,
AsyncPrivateWirelessGatewaysResource,
@@ -1858,6 +1871,55 @@ def compute(self) -> ComputeResource:
return ComputeResource(self)
+ @cached_property
+ def noise_suppression_engines(self) -> NoiseSuppressionEnginesResource:
+ """
+ Noise suppression engines that can be selected when configuring noise suppression on voice connections.
+ """
+ from .resources.noise_suppression_engines import NoiseSuppressionEnginesResource
+
+ return NoiseSuppressionEnginesResource(self)
+
+ @cached_property
+ def bot_challenge(self) -> BotChallengeResource:
+ """Agentic (bot) signup for Telnyx accounts.
+
+ An AI agent solves a reverse-CAPTCHA challenge designed to be easy for LLMs and hard for humans, registers an account, and signs in by consuming a magic link emailed to the account owner. All endpoints are public and unauthenticated; signup endpoints are additionally gated by the freemium feature flags and per-country availability.
+ """
+ from .resources.bot_challenge import BotChallengeResource
+
+ return BotChallengeResource(self)
+
+ @cached_property
+ def bot_sessions(self) -> BotSessionsResource:
+ """Agentic (bot) signup for Telnyx accounts.
+
+ An AI agent solves a reverse-CAPTCHA challenge designed to be easy for LLMs and hard for humans, registers an account, and signs in by consuming a magic link emailed to the account owner. All endpoints are public and unauthenticated; signup endpoints are additionally gated by the freemium feature flags and per-country availability.
+ """
+ from .resources.bot_sessions import BotSessionsResource
+
+ return BotSessionsResource(self)
+
+ @cached_property
+ def bot_signup(self) -> BotSignupResource:
+ """Agentic (bot) signup for Telnyx accounts.
+
+ An AI agent solves a reverse-CAPTCHA challenge designed to be easy for LLMs and hard for humans, registers an account, and signs in by consuming a magic link emailed to the account owner. All endpoints are public and unauthenticated; signup endpoints are additionally gated by the freemium feature flags and per-country availability.
+ """
+ from .resources.bot_signup import BotSignupResource
+
+ return BotSignupResource(self)
+
+ @cached_property
+ def machine_payments(self) -> MachinePaymentsResource:
+ """Machine payment (MPP) account-credit operations.
+
+ Fund your Telnyx account programmatically from a machine or agent using the Machine Payment Protocol, an HTTP-402 flow settled via Stripe or Tempo.
+ """
+ from .resources.machine_payments import MachinePaymentsResource
+
+ return MachinePaymentsResource(self)
+
@cached_property
def with_raw_response(self) -> TelnyxWithRawResponse:
return TelnyxWithRawResponse(self)
@@ -3362,6 +3424,55 @@ def compute(self) -> AsyncComputeResource:
return AsyncComputeResource(self)
+ @cached_property
+ def noise_suppression_engines(self) -> AsyncNoiseSuppressionEnginesResource:
+ """
+ Noise suppression engines that can be selected when configuring noise suppression on voice connections.
+ """
+ from .resources.noise_suppression_engines import AsyncNoiseSuppressionEnginesResource
+
+ return AsyncNoiseSuppressionEnginesResource(self)
+
+ @cached_property
+ def bot_challenge(self) -> AsyncBotChallengeResource:
+ """Agentic (bot) signup for Telnyx accounts.
+
+ An AI agent solves a reverse-CAPTCHA challenge designed to be easy for LLMs and hard for humans, registers an account, and signs in by consuming a magic link emailed to the account owner. All endpoints are public and unauthenticated; signup endpoints are additionally gated by the freemium feature flags and per-country availability.
+ """
+ from .resources.bot_challenge import AsyncBotChallengeResource
+
+ return AsyncBotChallengeResource(self)
+
+ @cached_property
+ def bot_sessions(self) -> AsyncBotSessionsResource:
+ """Agentic (bot) signup for Telnyx accounts.
+
+ An AI agent solves a reverse-CAPTCHA challenge designed to be easy for LLMs and hard for humans, registers an account, and signs in by consuming a magic link emailed to the account owner. All endpoints are public and unauthenticated; signup endpoints are additionally gated by the freemium feature flags and per-country availability.
+ """
+ from .resources.bot_sessions import AsyncBotSessionsResource
+
+ return AsyncBotSessionsResource(self)
+
+ @cached_property
+ def bot_signup(self) -> AsyncBotSignupResource:
+ """Agentic (bot) signup for Telnyx accounts.
+
+ An AI agent solves a reverse-CAPTCHA challenge designed to be easy for LLMs and hard for humans, registers an account, and signs in by consuming a magic link emailed to the account owner. All endpoints are public and unauthenticated; signup endpoints are additionally gated by the freemium feature flags and per-country availability.
+ """
+ from .resources.bot_signup import AsyncBotSignupResource
+
+ return AsyncBotSignupResource(self)
+
+ @cached_property
+ def machine_payments(self) -> AsyncMachinePaymentsResource:
+ """Machine payment (MPP) account-credit operations.
+
+ Fund your Telnyx account programmatically from a machine or agent using the Machine Payment Protocol, an HTTP-402 flow settled via Stripe or Tempo.
+ """
+ from .resources.machine_payments import AsyncMachinePaymentsResource
+
+ return AsyncMachinePaymentsResource(self)
+
@cached_property
def with_raw_response(self) -> AsyncTelnyxWithRawResponse:
return AsyncTelnyxWithRawResponse(self)
@@ -4802,6 +4913,55 @@ def compute(self) -> compute.ComputeResourceWithRawResponse:
return ComputeResourceWithRawResponse(self._client.compute)
+ @cached_property
+ def noise_suppression_engines(self) -> noise_suppression_engines.NoiseSuppressionEnginesResourceWithRawResponse:
+ """
+ Noise suppression engines that can be selected when configuring noise suppression on voice connections.
+ """
+ from .resources.noise_suppression_engines import NoiseSuppressionEnginesResourceWithRawResponse
+
+ return NoiseSuppressionEnginesResourceWithRawResponse(self._client.noise_suppression_engines)
+
+ @cached_property
+ def bot_challenge(self) -> bot_challenge.BotChallengeResourceWithRawResponse:
+ """Agentic (bot) signup for Telnyx accounts.
+
+ An AI agent solves a reverse-CAPTCHA challenge designed to be easy for LLMs and hard for humans, registers an account, and signs in by consuming a magic link emailed to the account owner. All endpoints are public and unauthenticated; signup endpoints are additionally gated by the freemium feature flags and per-country availability.
+ """
+ from .resources.bot_challenge import BotChallengeResourceWithRawResponse
+
+ return BotChallengeResourceWithRawResponse(self._client.bot_challenge)
+
+ @cached_property
+ def bot_sessions(self) -> bot_sessions.BotSessionsResourceWithRawResponse:
+ """Agentic (bot) signup for Telnyx accounts.
+
+ An AI agent solves a reverse-CAPTCHA challenge designed to be easy for LLMs and hard for humans, registers an account, and signs in by consuming a magic link emailed to the account owner. All endpoints are public and unauthenticated; signup endpoints are additionally gated by the freemium feature flags and per-country availability.
+ """
+ from .resources.bot_sessions import BotSessionsResourceWithRawResponse
+
+ return BotSessionsResourceWithRawResponse(self._client.bot_sessions)
+
+ @cached_property
+ def bot_signup(self) -> bot_signup.BotSignupResourceWithRawResponse:
+ """Agentic (bot) signup for Telnyx accounts.
+
+ An AI agent solves a reverse-CAPTCHA challenge designed to be easy for LLMs and hard for humans, registers an account, and signs in by consuming a magic link emailed to the account owner. All endpoints are public and unauthenticated; signup endpoints are additionally gated by the freemium feature flags and per-country availability.
+ """
+ from .resources.bot_signup import BotSignupResourceWithRawResponse
+
+ return BotSignupResourceWithRawResponse(self._client.bot_signup)
+
+ @cached_property
+ def machine_payments(self) -> machine_payments.MachinePaymentsResourceWithRawResponse:
+ """Machine payment (MPP) account-credit operations.
+
+ Fund your Telnyx account programmatically from a machine or agent using the Machine Payment Protocol, an HTTP-402 flow settled via Stripe or Tempo.
+ """
+ from .resources.machine_payments import MachinePaymentsResourceWithRawResponse
+
+ return MachinePaymentsResourceWithRawResponse(self._client.machine_payments)
+
class AsyncTelnyxWithRawResponse:
_client: AsyncTelnyx
@@ -6113,6 +6273,57 @@ def compute(self) -> compute.AsyncComputeResourceWithRawResponse:
return AsyncComputeResourceWithRawResponse(self._client.compute)
+ @cached_property
+ def noise_suppression_engines(
+ self,
+ ) -> noise_suppression_engines.AsyncNoiseSuppressionEnginesResourceWithRawResponse:
+ """
+ Noise suppression engines that can be selected when configuring noise suppression on voice connections.
+ """
+ from .resources.noise_suppression_engines import AsyncNoiseSuppressionEnginesResourceWithRawResponse
+
+ return AsyncNoiseSuppressionEnginesResourceWithRawResponse(self._client.noise_suppression_engines)
+
+ @cached_property
+ def bot_challenge(self) -> bot_challenge.AsyncBotChallengeResourceWithRawResponse:
+ """Agentic (bot) signup for Telnyx accounts.
+
+ An AI agent solves a reverse-CAPTCHA challenge designed to be easy for LLMs and hard for humans, registers an account, and signs in by consuming a magic link emailed to the account owner. All endpoints are public and unauthenticated; signup endpoints are additionally gated by the freemium feature flags and per-country availability.
+ """
+ from .resources.bot_challenge import AsyncBotChallengeResourceWithRawResponse
+
+ return AsyncBotChallengeResourceWithRawResponse(self._client.bot_challenge)
+
+ @cached_property
+ def bot_sessions(self) -> bot_sessions.AsyncBotSessionsResourceWithRawResponse:
+ """Agentic (bot) signup for Telnyx accounts.
+
+ An AI agent solves a reverse-CAPTCHA challenge designed to be easy for LLMs and hard for humans, registers an account, and signs in by consuming a magic link emailed to the account owner. All endpoints are public and unauthenticated; signup endpoints are additionally gated by the freemium feature flags and per-country availability.
+ """
+ from .resources.bot_sessions import AsyncBotSessionsResourceWithRawResponse
+
+ return AsyncBotSessionsResourceWithRawResponse(self._client.bot_sessions)
+
+ @cached_property
+ def bot_signup(self) -> bot_signup.AsyncBotSignupResourceWithRawResponse:
+ """Agentic (bot) signup for Telnyx accounts.
+
+ An AI agent solves a reverse-CAPTCHA challenge designed to be easy for LLMs and hard for humans, registers an account, and signs in by consuming a magic link emailed to the account owner. All endpoints are public and unauthenticated; signup endpoints are additionally gated by the freemium feature flags and per-country availability.
+ """
+ from .resources.bot_signup import AsyncBotSignupResourceWithRawResponse
+
+ return AsyncBotSignupResourceWithRawResponse(self._client.bot_signup)
+
+ @cached_property
+ def machine_payments(self) -> machine_payments.AsyncMachinePaymentsResourceWithRawResponse:
+ """Machine payment (MPP) account-credit operations.
+
+ Fund your Telnyx account programmatically from a machine or agent using the Machine Payment Protocol, an HTTP-402 flow settled via Stripe or Tempo.
+ """
+ from .resources.machine_payments import AsyncMachinePaymentsResourceWithRawResponse
+
+ return AsyncMachinePaymentsResourceWithRawResponse(self._client.machine_payments)
+
class TelnyxWithStreamedResponse:
_client: Telnyx
@@ -7426,6 +7637,57 @@ def compute(self) -> compute.ComputeResourceWithStreamingResponse:
return ComputeResourceWithStreamingResponse(self._client.compute)
+ @cached_property
+ def noise_suppression_engines(
+ self,
+ ) -> noise_suppression_engines.NoiseSuppressionEnginesResourceWithStreamingResponse:
+ """
+ Noise suppression engines that can be selected when configuring noise suppression on voice connections.
+ """
+ from .resources.noise_suppression_engines import NoiseSuppressionEnginesResourceWithStreamingResponse
+
+ return NoiseSuppressionEnginesResourceWithStreamingResponse(self._client.noise_suppression_engines)
+
+ @cached_property
+ def bot_challenge(self) -> bot_challenge.BotChallengeResourceWithStreamingResponse:
+ """Agentic (bot) signup for Telnyx accounts.
+
+ An AI agent solves a reverse-CAPTCHA challenge designed to be easy for LLMs and hard for humans, registers an account, and signs in by consuming a magic link emailed to the account owner. All endpoints are public and unauthenticated; signup endpoints are additionally gated by the freemium feature flags and per-country availability.
+ """
+ from .resources.bot_challenge import BotChallengeResourceWithStreamingResponse
+
+ return BotChallengeResourceWithStreamingResponse(self._client.bot_challenge)
+
+ @cached_property
+ def bot_sessions(self) -> bot_sessions.BotSessionsResourceWithStreamingResponse:
+ """Agentic (bot) signup for Telnyx accounts.
+
+ An AI agent solves a reverse-CAPTCHA challenge designed to be easy for LLMs and hard for humans, registers an account, and signs in by consuming a magic link emailed to the account owner. All endpoints are public and unauthenticated; signup endpoints are additionally gated by the freemium feature flags and per-country availability.
+ """
+ from .resources.bot_sessions import BotSessionsResourceWithStreamingResponse
+
+ return BotSessionsResourceWithStreamingResponse(self._client.bot_sessions)
+
+ @cached_property
+ def bot_signup(self) -> bot_signup.BotSignupResourceWithStreamingResponse:
+ """Agentic (bot) signup for Telnyx accounts.
+
+ An AI agent solves a reverse-CAPTCHA challenge designed to be easy for LLMs and hard for humans, registers an account, and signs in by consuming a magic link emailed to the account owner. All endpoints are public and unauthenticated; signup endpoints are additionally gated by the freemium feature flags and per-country availability.
+ """
+ from .resources.bot_signup import BotSignupResourceWithStreamingResponse
+
+ return BotSignupResourceWithStreamingResponse(self._client.bot_signup)
+
+ @cached_property
+ def machine_payments(self) -> machine_payments.MachinePaymentsResourceWithStreamingResponse:
+ """Machine payment (MPP) account-credit operations.
+
+ Fund your Telnyx account programmatically from a machine or agent using the Machine Payment Protocol, an HTTP-402 flow settled via Stripe or Tempo.
+ """
+ from .resources.machine_payments import MachinePaymentsResourceWithStreamingResponse
+
+ return MachinePaymentsResourceWithStreamingResponse(self._client.machine_payments)
+
class AsyncTelnyxWithStreamedResponse:
_client: AsyncTelnyx
@@ -8787,6 +9049,57 @@ def compute(self) -> compute.AsyncComputeResourceWithStreamingResponse:
return AsyncComputeResourceWithStreamingResponse(self._client.compute)
+ @cached_property
+ def noise_suppression_engines(
+ self,
+ ) -> noise_suppression_engines.AsyncNoiseSuppressionEnginesResourceWithStreamingResponse:
+ """
+ Noise suppression engines that can be selected when configuring noise suppression on voice connections.
+ """
+ from .resources.noise_suppression_engines import AsyncNoiseSuppressionEnginesResourceWithStreamingResponse
+
+ return AsyncNoiseSuppressionEnginesResourceWithStreamingResponse(self._client.noise_suppression_engines)
+
+ @cached_property
+ def bot_challenge(self) -> bot_challenge.AsyncBotChallengeResourceWithStreamingResponse:
+ """Agentic (bot) signup for Telnyx accounts.
+
+ An AI agent solves a reverse-CAPTCHA challenge designed to be easy for LLMs and hard for humans, registers an account, and signs in by consuming a magic link emailed to the account owner. All endpoints are public and unauthenticated; signup endpoints are additionally gated by the freemium feature flags and per-country availability.
+ """
+ from .resources.bot_challenge import AsyncBotChallengeResourceWithStreamingResponse
+
+ return AsyncBotChallengeResourceWithStreamingResponse(self._client.bot_challenge)
+
+ @cached_property
+ def bot_sessions(self) -> bot_sessions.AsyncBotSessionsResourceWithStreamingResponse:
+ """Agentic (bot) signup for Telnyx accounts.
+
+ An AI agent solves a reverse-CAPTCHA challenge designed to be easy for LLMs and hard for humans, registers an account, and signs in by consuming a magic link emailed to the account owner. All endpoints are public and unauthenticated; signup endpoints are additionally gated by the freemium feature flags and per-country availability.
+ """
+ from .resources.bot_sessions import AsyncBotSessionsResourceWithStreamingResponse
+
+ return AsyncBotSessionsResourceWithStreamingResponse(self._client.bot_sessions)
+
+ @cached_property
+ def bot_signup(self) -> bot_signup.AsyncBotSignupResourceWithStreamingResponse:
+ """Agentic (bot) signup for Telnyx accounts.
+
+ An AI agent solves a reverse-CAPTCHA challenge designed to be easy for LLMs and hard for humans, registers an account, and signs in by consuming a magic link emailed to the account owner. All endpoints are public and unauthenticated; signup endpoints are additionally gated by the freemium feature flags and per-country availability.
+ """
+ from .resources.bot_signup import AsyncBotSignupResourceWithStreamingResponse
+
+ return AsyncBotSignupResourceWithStreamingResponse(self._client.bot_signup)
+
+ @cached_property
+ def machine_payments(self) -> machine_payments.AsyncMachinePaymentsResourceWithStreamingResponse:
+ """Machine payment (MPP) account-credit operations.
+
+ Fund your Telnyx account programmatically from a machine or agent using the Machine Payment Protocol, an HTTP-402 flow settled via Stripe or Tempo.
+ """
+ from .resources.machine_payments import AsyncMachinePaymentsResourceWithStreamingResponse
+
+ return AsyncMachinePaymentsResourceWithStreamingResponse(self._client.machine_payments)
+
Client = Telnyx
diff --git a/src/telnyx/_version.py b/src/telnyx/_version.py
index 2c5801666..000f5dc32 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.180.0" # x-release-please-version
+__version__ = "4.181.0" # x-release-please-version
diff --git a/src/telnyx/resources/__init__.py b/src/telnyx/resources/__init__.py
index 7595ed0ba..a07625f89 100644
--- a/src/telnyx/resources/__init__.py
+++ b/src/telnyx/resources/__init__.py
@@ -297,6 +297,14 @@
UserTagsResourceWithStreamingResponse,
AsyncUserTagsResourceWithStreamingResponse,
)
+from .bot_signup import (
+ BotSignupResource,
+ AsyncBotSignupResource,
+ BotSignupResourceWithRawResponse,
+ AsyncBotSignupResourceWithRawResponse,
+ BotSignupResourceWithStreamingResponse,
+ AsyncBotSignupResourceWithStreamingResponse,
+)
from .global_ips import (
GlobalIPsResource,
AsyncGlobalIPsResource,
@@ -393,6 +401,14 @@
AuditEventsResourceWithStreamingResponse,
AsyncAuditEventsResourceWithStreamingResponse,
)
+from .bot_sessions import (
+ BotSessionsResource,
+ AsyncBotSessionsResource,
+ BotSessionsResourceWithRawResponse,
+ AsyncBotSessionsResourceWithRawResponse,
+ BotSessionsResourceWithStreamingResponse,
+ AsyncBotSessionsResourceWithStreamingResponse,
+)
from .call_reasons import (
CallReasonsResource,
AsyncCallReasonsResource,
@@ -441,6 +457,14 @@
VoiceClonesResourceWithStreamingResponse,
AsyncVoiceClonesResourceWithStreamingResponse,
)
+from .bot_challenge import (
+ BotChallengeResource,
+ AsyncBotChallengeResource,
+ BotChallengeResourceWithRawResponse,
+ AsyncBotChallengeResourceWithRawResponse,
+ BotChallengeResourceWithStreamingResponse,
+ AsyncBotChallengeResourceWithStreamingResponse,
+)
from .channel_zones import (
ChannelZonesResource,
AsyncChannelZonesResource,
@@ -745,6 +769,14 @@
InboundChannelsResourceWithStreamingResponse,
AsyncInboundChannelsResourceWithStreamingResponse,
)
+from .machine_payments import (
+ MachinePaymentsResource,
+ AsyncMachinePaymentsResource,
+ MachinePaymentsResourceWithRawResponse,
+ AsyncMachinePaymentsResourceWithRawResponse,
+ MachinePaymentsResourceWithStreamingResponse,
+ AsyncMachinePaymentsResourceWithStreamingResponse,
+)
from .managed_accounts import (
ManagedAccountsResource,
AsyncManagedAccountsResource,
@@ -1313,6 +1345,14 @@
MessagingProfileMetricsResourceWithStreamingResponse,
AsyncMessagingProfileMetricsResourceWithStreamingResponse,
)
+from .noise_suppression_engines import (
+ NoiseSuppressionEnginesResource,
+ AsyncNoiseSuppressionEnginesResource,
+ NoiseSuppressionEnginesResourceWithRawResponse,
+ AsyncNoiseSuppressionEnginesResourceWithRawResponse,
+ NoiseSuppressionEnginesResourceWithStreamingResponse,
+ AsyncNoiseSuppressionEnginesResourceWithStreamingResponse,
+)
from .private_wireless_gateways import (
PrivateWirelessGatewaysResource,
AsyncPrivateWirelessGatewaysResource,
@@ -2553,4 +2593,34 @@
"AsyncComputeResourceWithRawResponse",
"ComputeResourceWithStreamingResponse",
"AsyncComputeResourceWithStreamingResponse",
+ "NoiseSuppressionEnginesResource",
+ "AsyncNoiseSuppressionEnginesResource",
+ "NoiseSuppressionEnginesResourceWithRawResponse",
+ "AsyncNoiseSuppressionEnginesResourceWithRawResponse",
+ "NoiseSuppressionEnginesResourceWithStreamingResponse",
+ "AsyncNoiseSuppressionEnginesResourceWithStreamingResponse",
+ "BotChallengeResource",
+ "AsyncBotChallengeResource",
+ "BotChallengeResourceWithRawResponse",
+ "AsyncBotChallengeResourceWithRawResponse",
+ "BotChallengeResourceWithStreamingResponse",
+ "AsyncBotChallengeResourceWithStreamingResponse",
+ "BotSessionsResource",
+ "AsyncBotSessionsResource",
+ "BotSessionsResourceWithRawResponse",
+ "AsyncBotSessionsResourceWithRawResponse",
+ "BotSessionsResourceWithStreamingResponse",
+ "AsyncBotSessionsResourceWithStreamingResponse",
+ "BotSignupResource",
+ "AsyncBotSignupResource",
+ "BotSignupResourceWithRawResponse",
+ "AsyncBotSignupResourceWithRawResponse",
+ "BotSignupResourceWithStreamingResponse",
+ "AsyncBotSignupResourceWithStreamingResponse",
+ "MachinePaymentsResource",
+ "AsyncMachinePaymentsResource",
+ "MachinePaymentsResourceWithRawResponse",
+ "AsyncMachinePaymentsResourceWithRawResponse",
+ "MachinePaymentsResourceWithStreamingResponse",
+ "AsyncMachinePaymentsResourceWithStreamingResponse",
]
diff --git a/src/telnyx/resources/ai/__init__.py b/src/telnyx/resources/ai/__init__.py
index 8aff9743b..eeb3e681a 100644
--- a/src/telnyx/resources/ai/__init__.py
+++ b/src/telnyx/resources/ai/__init__.py
@@ -48,6 +48,14 @@
MissionsResourceWithStreamingResponse,
AsyncMissionsResourceWithStreamingResponse,
)
+from .typesafe import (
+ TypesafeResource,
+ AsyncTypesafeResource,
+ TypesafeResourceWithRawResponse,
+ AsyncTypesafeResourceWithRawResponse,
+ TypesafeResourceWithStreamingResponse,
+ AsyncTypesafeResourceWithStreamingResponse,
+)
from .anthropic import (
AnthropicResource,
AsyncAnthropicResource,
@@ -206,6 +214,12 @@
"AsyncKnowledgeResourceWithRawResponse",
"KnowledgeResourceWithStreamingResponse",
"AsyncKnowledgeResourceWithStreamingResponse",
+ "TypesafeResource",
+ "AsyncTypesafeResource",
+ "TypesafeResourceWithRawResponse",
+ "AsyncTypesafeResourceWithRawResponse",
+ "TypesafeResourceWithStreamingResponse",
+ "AsyncTypesafeResourceWithStreamingResponse",
"AIResource",
"AsyncAIResource",
"AIResourceWithRawResponse",
diff --git a/src/telnyx/resources/ai/ai.py b/src/telnyx/resources/ai/ai.py
index 2d4f72a1b..3c5b076a7 100644
--- a/src/telnyx/resources/ai/ai.py
+++ b/src/telnyx/resources/ai/ai.py
@@ -69,6 +69,14 @@
MissionsResourceWithStreamingResponse,
AsyncMissionsResourceWithStreamingResponse,
)
+from .typesafe.typesafe import (
+ TypesafeResource,
+ AsyncTypesafeResource,
+ TypesafeResourceWithRawResponse,
+ AsyncTypesafeResourceWithRawResponse,
+ TypesafeResourceWithStreamingResponse,
+ AsyncTypesafeResourceWithStreamingResponse,
+)
from .anthropic.anthropic import (
AnthropicResource,
AsyncAnthropicResource,
@@ -204,6 +212,10 @@ def anthropic(self) -> AnthropicResource:
def knowledge(self) -> KnowledgeResource:
return KnowledgeResource(self._client)
+ @cached_property
+ def typesafe(self) -> TypesafeResource:
+ return TypesafeResource(self._client)
+
@cached_property
def with_raw_response(self) -> AIResourceWithRawResponse:
"""
@@ -497,6 +509,10 @@ def anthropic(self) -> AsyncAnthropicResource:
def knowledge(self) -> AsyncKnowledgeResource:
return AsyncKnowledgeResource(self._client)
+ @cached_property
+ def typesafe(self) -> AsyncTypesafeResource:
+ return AsyncTypesafeResource(self._client)
+
@cached_property
def with_raw_response(self) -> AsyncAIResourceWithRawResponse:
"""
@@ -802,6 +818,10 @@ def anthropic(self) -> AnthropicResourceWithRawResponse:
def knowledge(self) -> KnowledgeResourceWithRawResponse:
return KnowledgeResourceWithRawResponse(self._ai.knowledge)
+ @cached_property
+ def typesafe(self) -> TypesafeResourceWithRawResponse:
+ return TypesafeResourceWithRawResponse(self._ai.typesafe)
+
class AsyncAIResourceWithRawResponse:
def __init__(self, ai: AsyncAIResource) -> None:
@@ -878,6 +898,10 @@ def anthropic(self) -> AsyncAnthropicResourceWithRawResponse:
def knowledge(self) -> AsyncKnowledgeResourceWithRawResponse:
return AsyncKnowledgeResourceWithRawResponse(self._ai.knowledge)
+ @cached_property
+ def typesafe(self) -> AsyncTypesafeResourceWithRawResponse:
+ return AsyncTypesafeResourceWithRawResponse(self._ai.typesafe)
+
class AIResourceWithStreamingResponse:
def __init__(self, ai: AIResource) -> None:
@@ -954,6 +978,10 @@ def anthropic(self) -> AnthropicResourceWithStreamingResponse:
def knowledge(self) -> KnowledgeResourceWithStreamingResponse:
return KnowledgeResourceWithStreamingResponse(self._ai.knowledge)
+ @cached_property
+ def typesafe(self) -> TypesafeResourceWithStreamingResponse:
+ return TypesafeResourceWithStreamingResponse(self._ai.typesafe)
+
class AsyncAIResourceWithStreamingResponse:
def __init__(self, ai: AsyncAIResource) -> None:
@@ -1029,3 +1057,7 @@ def anthropic(self) -> AsyncAnthropicResourceWithStreamingResponse:
@cached_property
def knowledge(self) -> AsyncKnowledgeResourceWithStreamingResponse:
return AsyncKnowledgeResourceWithStreamingResponse(self._ai.knowledge)
+
+ @cached_property
+ def typesafe(self) -> AsyncTypesafeResourceWithStreamingResponse:
+ return AsyncTypesafeResourceWithStreamingResponse(self._ai.typesafe)
diff --git a/src/telnyx/resources/ai/assistants/assistants.py b/src/telnyx/resources/ai/assistants/assistants.py
index 62e44f416..6fca0cf0b 100644
--- a/src/telnyx/resources/ai/assistants/assistants.py
+++ b/src/telnyx/resources/ai/assistants/assistants.py
@@ -282,10 +282,10 @@ def create(
post_conversation_settings: 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.
+ execute final tool calls such as sending a summary or updating a record via
+ webhook or function tools. Integration and MCP server tools are not available
+ post-conversation; call-control tools (e.g. hangup, transfer) are also
+ unavailable. Beta feature.
tags: Tags associated with the assistant. Tags can also be managed with the assistant
tag endpoints.
@@ -527,10 +527,10 @@ def update(
post_conversation_settings: 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.
+ execute final tool calls such as sending a summary or updating a record via
+ webhook or function tools. Integration and MCP server tools are not available
+ post-conversation; call-control tools (e.g. hangup, transfer) are also
+ unavailable. Beta feature.
promote_to_main: Indicates whether the assistant should be promoted to the main version. Defaults
to true.
@@ -539,11 +539,22 @@ def update(
tag endpoints.
tool_ids: IDs of shared tools to attach to the assistant. New integrations should prefer
- `tool_ids` over inline `tools`.
+ `tool_ids` over inline `tools`. On update, a sent `tool_ids` array fully
+ replaces the assistant's attached shared tools; omit the field to leave them
+ unchanged. Single-instance tool types are counted across inline `tools` and
+ `tool_ids` combined, so attaching a shared tool of such a type when an instance
+ already exists returns HTTP 400 with error code 10015.
tools: Deprecated for new integrations. Inline tool definitions available to the
assistant. Prefer `tool_ids` to attach shared tools created with the AI Tools
- endpoints.
+ endpoints. On update, a sent `tools` array fully replaces the assistant's inline
+ tools; omit the field to leave the inline tools unchanged. Each tool type except
+ `function`, `webhook`, and `client_side_tool` allows at most one instance per
+ assistant, counted across inline `tools` and shared `tool_ids` combined —
+ sending a duplicate of such a type returns HTTP 400 with error code 10015.
+ Responses merge shared tools into `tools` with `shared: true`; when updating,
+ omit those tools from the `tools` array and manage them through `tool_ids`
+ instead.
version_name: Human-readable name for the assistant version.
@@ -1079,10 +1090,10 @@ async def create(
post_conversation_settings: 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.
+ execute final tool calls such as sending a summary or updating a record via
+ webhook or function tools. Integration and MCP server tools are not available
+ post-conversation; call-control tools (e.g. hangup, transfer) are also
+ unavailable. Beta feature.
tags: Tags associated with the assistant. Tags can also be managed with the assistant
tag endpoints.
@@ -1324,10 +1335,10 @@ async def update(
post_conversation_settings: 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.
+ execute final tool calls such as sending a summary or updating a record via
+ webhook or function tools. Integration and MCP server tools are not available
+ post-conversation; call-control tools (e.g. hangup, transfer) are also
+ unavailable. Beta feature.
promote_to_main: Indicates whether the assistant should be promoted to the main version. Defaults
to true.
@@ -1336,11 +1347,22 @@ async def update(
tag endpoints.
tool_ids: IDs of shared tools to attach to the assistant. New integrations should prefer
- `tool_ids` over inline `tools`.
+ `tool_ids` over inline `tools`. On update, a sent `tool_ids` array fully
+ replaces the assistant's attached shared tools; omit the field to leave them
+ unchanged. Single-instance tool types are counted across inline `tools` and
+ `tool_ids` combined, so attaching a shared tool of such a type when an instance
+ already exists returns HTTP 400 with error code 10015.
tools: Deprecated for new integrations. Inline tool definitions available to the
assistant. Prefer `tool_ids` to attach shared tools created with the AI Tools
- endpoints.
+ endpoints. On update, a sent `tools` array fully replaces the assistant's inline
+ tools; omit the field to leave the inline tools unchanged. Each tool type except
+ `function`, `webhook`, and `client_side_tool` allows at most one instance per
+ assistant, counted across inline `tools` and shared `tool_ids` combined —
+ sending a duplicate of such a type returns HTTP 400 with error code 10015.
+ Responses merge shared tools into `tools` with `shared: true`; when updating,
+ omit those tools from the `tools` array and manage them through `tool_ids`
+ instead.
version_name: Human-readable name for the assistant version.
diff --git a/src/telnyx/resources/ai/assistants/versions.py b/src/telnyx/resources/ai/assistants/versions.py
index 33af21060..3d6b53050 100644
--- a/src/telnyx/resources/ai/assistants/versions.py
+++ b/src/telnyx/resources/ai/assistants/versions.py
@@ -231,20 +231,31 @@ def update(
post_conversation_settings: 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.
+ execute final tool calls such as sending a summary or updating a record via
+ webhook or function tools. Integration and MCP server tools are not available
+ post-conversation; call-control tools (e.g. hangup, transfer) are also
+ unavailable. Beta feature.
tags: Tags associated with the assistant. Tags can also be managed with the assistant
tag endpoints.
tool_ids: IDs of shared tools to attach to the assistant. New integrations should prefer
- `tool_ids` over inline `tools`.
+ `tool_ids` over inline `tools`. On update, a sent `tool_ids` array fully
+ replaces the assistant's attached shared tools; omit the field to leave them
+ unchanged. Single-instance tool types are counted across inline `tools` and
+ `tool_ids` combined, so attaching a shared tool of such a type when an instance
+ already exists returns HTTP 400 with error code 10015.
tools: Deprecated for new integrations. Inline tool definitions available to the
assistant. Prefer `tool_ids` to attach shared tools created with the AI Tools
- endpoints.
+ endpoints. On update, a sent `tools` array fully replaces the assistant's inline
+ tools; omit the field to leave the inline tools unchanged. Each tool type except
+ `function`, `webhook`, and `client_side_tool` allows at most one instance per
+ assistant, counted across inline `tools` and shared `tool_ids` combined —
+ sending a duplicate of such a type returns HTTP 400 with error code 10015.
+ Responses merge shared tools into `tools` with `shared: true`; when updating,
+ omit those tools from the `tools` array and manage them through `tool_ids`
+ instead.
version_name: Human-readable name for the assistant version.
@@ -614,20 +625,31 @@ async def update(
post_conversation_settings: 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.
+ execute final tool calls such as sending a summary or updating a record via
+ webhook or function tools. Integration and MCP server tools are not available
+ post-conversation; call-control tools (e.g. hangup, transfer) are also
+ unavailable. Beta feature.
tags: Tags associated with the assistant. Tags can also be managed with the assistant
tag endpoints.
tool_ids: IDs of shared tools to attach to the assistant. New integrations should prefer
- `tool_ids` over inline `tools`.
+ `tool_ids` over inline `tools`. On update, a sent `tool_ids` array fully
+ replaces the assistant's attached shared tools; omit the field to leave them
+ unchanged. Single-instance tool types are counted across inline `tools` and
+ `tool_ids` combined, so attaching a shared tool of such a type when an instance
+ already exists returns HTTP 400 with error code 10015.
tools: Deprecated for new integrations. Inline tool definitions available to the
assistant. Prefer `tool_ids` to attach shared tools created with the AI Tools
- endpoints.
+ endpoints. On update, a sent `tools` array fully replaces the assistant's inline
+ tools; omit the field to leave the inline tools unchanged. Each tool type except
+ `function`, `webhook`, and `client_side_tool` allows at most one instance per
+ assistant, counted across inline `tools` and shared `tool_ids` combined —
+ sending a duplicate of such a type returns HTTP 400 with error code 10015.
+ Responses merge shared tools into `tools` with `shared: true`; when updating,
+ omit those tools from the `tools` array and manage them through `tool_ids`
+ instead.
version_name: Human-readable name for the assistant version.
diff --git a/src/telnyx/resources/ai/audio.py b/src/telnyx/resources/ai/audio.py
index 3f1f53bb5..1325aec42 100644
--- a/src/telnyx/resources/ai/audio.py
+++ b/src/telnyx/resources/ai/audio.py
@@ -48,7 +48,16 @@ def with_streaming_response(self) -> AudioResourceWithStreamingResponse:
def transcribe(
self,
*,
- model: Literal["distil-whisper/distil-large-v2", "openai/whisper-large-v3-turbo", "deepgram/nova-3"],
+ model: Literal[
+ "distil-whisper/distil-large-v2",
+ "openai/whisper-large-v3-turbo",
+ "deepgram/nova-2",
+ "deepgram/nova-2-medical",
+ "deepgram/nova-3",
+ "deepgram/nova-3-medical",
+ "nvidia/parakeet-v3",
+ "omi-health/omi-med-stt-v1",
+ ],
file: FileTypes | Omit = omit,
file_url: str | Omit = omit,
language: str | Omit = omit,
@@ -71,25 +80,36 @@ def transcribe(
Args:
model: ID of the model to use. `distil-whisper/distil-large-v2` is lower latency but
English-only. `openai/whisper-large-v3-turbo` is multi-lingual but slightly
- higher latency. `deepgram/nova-3` supports English variants (en, en-US, en-GB,
- en-AU, en-NZ, en-IN) and only accepts mp3/wav files.
+ higher latency. The `deepgram/*` models only accept mp3/wav files:
+ `deepgram/nova-3` covers ~49 languages plus `multi` and `deepgram/nova-2` covers
+ ~33, while the `-medical` variants are tuned for clinical vocabulary and accept
+ English only (`en` and its regional variants, e.g. `en-US`, `en-GB`).
+ `nvidia/parakeet-v3` is multilingual with automatic language detection;
+ `omi-health/omi-med-stt-v1` is a medical model, English only.
file: The audio file object to transcribe, in one of these formats: flac, mp3, mp4,
mpeg, mpga, m4a, ogg, wav, or webm. File uploads are limited to 100 MB. Cannot
- be used together with `file_url`. Note: `deepgram/nova-3` only supports mp3 and
- wav formats.
+ be used together with `file_url`. Note: the `deepgram/*` models only support mp3
+ and wav formats.
file_url: Link to audio file in one of these formats: flac, mp3, mp4, mpeg, mpga, m4a,
ogg, wav, or webm. Support for hosted files is limited to 100MB. Cannot be used
- together with `file`. Note: `deepgram/nova-3` only supports mp3 and wav formats.
-
- language: The language of the audio to be transcribed. For `deepgram/nova-3`, only English
- variants are supported: `en`, `en-US`, `en-GB`, `en-AU`, `en-NZ`, `en-IN`. For
+ together with `file`. Note: the `deepgram/*` models only support mp3 and wav
+ formats.
+
+ language: The language of the audio to be transcribed. `deepgram/nova-3` supports ~49
+ languages plus `multi`, and `deepgram/nova-2` supports ~33 plus `multi`; the
+ `-medical` variants are English only (`en` and its regional variants, e.g.
+ `en-US`, `en-GB`). Deepgram models validate on the base language and forward the
+ full tag, so regional variants such as `de-CH` and `pt-BR` are accepted where
+ the base language is supported; an unsupported language returns a 400. For
`openai/whisper-large-v3-turbo`, supports multiple languages.
`distil-whisper/distil-large-v2` does not support language parameter.
+ `nvidia/parakeet-v3` detects the language automatically;
+ `omi-health/omi-med-stt-v1` is English only.
- model_config: Additional model-specific configuration parameters. Only allowed with
- `deepgram/nova-3` model. Can include Deepgram-specific options such as
+ model_config: Additional model-specific configuration parameters. Only allowed with the
+ `deepgram/*` models. Can include Deepgram-specific options such as
`smart_format`, `punctuate`, `diarize`, `utterance`, `numerals`, and `language`.
If `language` is provided both as a top-level parameter and in `model_config`,
the top-level parameter takes precedence.
@@ -160,7 +180,16 @@ def with_streaming_response(self) -> AsyncAudioResourceWithStreamingResponse:
async def transcribe(
self,
*,
- model: Literal["distil-whisper/distil-large-v2", "openai/whisper-large-v3-turbo", "deepgram/nova-3"],
+ model: Literal[
+ "distil-whisper/distil-large-v2",
+ "openai/whisper-large-v3-turbo",
+ "deepgram/nova-2",
+ "deepgram/nova-2-medical",
+ "deepgram/nova-3",
+ "deepgram/nova-3-medical",
+ "nvidia/parakeet-v3",
+ "omi-health/omi-med-stt-v1",
+ ],
file: FileTypes | Omit = omit,
file_url: str | Omit = omit,
language: str | Omit = omit,
@@ -183,25 +212,36 @@ async def transcribe(
Args:
model: ID of the model to use. `distil-whisper/distil-large-v2` is lower latency but
English-only. `openai/whisper-large-v3-turbo` is multi-lingual but slightly
- higher latency. `deepgram/nova-3` supports English variants (en, en-US, en-GB,
- en-AU, en-NZ, en-IN) and only accepts mp3/wav files.
+ higher latency. The `deepgram/*` models only accept mp3/wav files:
+ `deepgram/nova-3` covers ~49 languages plus `multi` and `deepgram/nova-2` covers
+ ~33, while the `-medical` variants are tuned for clinical vocabulary and accept
+ English only (`en` and its regional variants, e.g. `en-US`, `en-GB`).
+ `nvidia/parakeet-v3` is multilingual with automatic language detection;
+ `omi-health/omi-med-stt-v1` is a medical model, English only.
file: The audio file object to transcribe, in one of these formats: flac, mp3, mp4,
mpeg, mpga, m4a, ogg, wav, or webm. File uploads are limited to 100 MB. Cannot
- be used together with `file_url`. Note: `deepgram/nova-3` only supports mp3 and
- wav formats.
+ be used together with `file_url`. Note: the `deepgram/*` models only support mp3
+ and wav formats.
file_url: Link to audio file in one of these formats: flac, mp3, mp4, mpeg, mpga, m4a,
ogg, wav, or webm. Support for hosted files is limited to 100MB. Cannot be used
- together with `file`. Note: `deepgram/nova-3` only supports mp3 and wav formats.
-
- language: The language of the audio to be transcribed. For `deepgram/nova-3`, only English
- variants are supported: `en`, `en-US`, `en-GB`, `en-AU`, `en-NZ`, `en-IN`. For
+ together with `file`. Note: the `deepgram/*` models only support mp3 and wav
+ formats.
+
+ language: The language of the audio to be transcribed. `deepgram/nova-3` supports ~49
+ languages plus `multi`, and `deepgram/nova-2` supports ~33 plus `multi`; the
+ `-medical` variants are English only (`en` and its regional variants, e.g.
+ `en-US`, `en-GB`). Deepgram models validate on the base language and forward the
+ full tag, so regional variants such as `de-CH` and `pt-BR` are accepted where
+ the base language is supported; an unsupported language returns a 400. For
`openai/whisper-large-v3-turbo`, supports multiple languages.
`distil-whisper/distil-large-v2` does not support language parameter.
+ `nvidia/parakeet-v3` detects the language automatically;
+ `omi-health/omi-med-stt-v1` is English only.
- model_config: Additional model-specific configuration parameters. Only allowed with
- `deepgram/nova-3` model. Can include Deepgram-specific options such as
+ model_config: Additional model-specific configuration parameters. Only allowed with the
+ `deepgram/*` models. Can include Deepgram-specific options such as
`smart_format`, `punctuate`, `diarize`, `utterance`, `numerals`, and `language`.
If `language` is provided both as a top-level parameter and in `model_config`,
the top-level parameter takes precedence.
diff --git a/src/telnyx/resources/ai/typesafe/__init__.py b/src/telnyx/resources/ai/typesafe/__init__.py
new file mode 100644
index 000000000..330efe519
--- /dev/null
+++ b/src/telnyx/resources/ai/typesafe/__init__.py
@@ -0,0 +1,33 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from .v1 import (
+ V1Resource,
+ AsyncV1Resource,
+ V1ResourceWithRawResponse,
+ AsyncV1ResourceWithRawResponse,
+ V1ResourceWithStreamingResponse,
+ AsyncV1ResourceWithStreamingResponse,
+)
+from .typesafe import (
+ TypesafeResource,
+ AsyncTypesafeResource,
+ TypesafeResourceWithRawResponse,
+ AsyncTypesafeResourceWithRawResponse,
+ TypesafeResourceWithStreamingResponse,
+ AsyncTypesafeResourceWithStreamingResponse,
+)
+
+__all__ = [
+ "V1Resource",
+ "AsyncV1Resource",
+ "V1ResourceWithRawResponse",
+ "AsyncV1ResourceWithRawResponse",
+ "V1ResourceWithStreamingResponse",
+ "AsyncV1ResourceWithStreamingResponse",
+ "TypesafeResource",
+ "AsyncTypesafeResource",
+ "TypesafeResourceWithRawResponse",
+ "AsyncTypesafeResourceWithRawResponse",
+ "TypesafeResourceWithStreamingResponse",
+ "AsyncTypesafeResourceWithStreamingResponse",
+]
diff --git a/src/telnyx/resources/ai/typesafe/typesafe.py b/src/telnyx/resources/ai/typesafe/typesafe.py
new file mode 100644
index 000000000..a91b38c44
--- /dev/null
+++ b/src/telnyx/resources/ai/typesafe/typesafe.py
@@ -0,0 +1,120 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from .v1 import (
+ V1Resource,
+ AsyncV1Resource,
+ V1ResourceWithRawResponse,
+ AsyncV1ResourceWithRawResponse,
+ V1ResourceWithStreamingResponse,
+ AsyncV1ResourceWithStreamingResponse,
+)
+from ...._compat import cached_property
+from ...._resource import SyncAPIResource, AsyncAPIResource
+
+__all__ = ["TypesafeResource", "AsyncTypesafeResource"]
+
+
+class TypesafeResource(SyncAPIResource):
+ @cached_property
+ def v1(self) -> V1Resource:
+ """
+ Beta API for evaluating shared context with typed questions and structured answers. Telnyx manages model selection.
+ """
+ return V1Resource(self._client)
+
+ @cached_property
+ def with_raw_response(self) -> TypesafeResourceWithRawResponse:
+ """
+ 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 TypesafeResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> TypesafeResourceWithStreamingResponse:
+ """
+ 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 TypesafeResourceWithStreamingResponse(self)
+
+
+class AsyncTypesafeResource(AsyncAPIResource):
+ @cached_property
+ def v1(self) -> AsyncV1Resource:
+ """
+ Beta API for evaluating shared context with typed questions and structured answers. Telnyx manages model selection.
+ """
+ return AsyncV1Resource(self._client)
+
+ @cached_property
+ def with_raw_response(self) -> AsyncTypesafeResourceWithRawResponse:
+ """
+ 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 AsyncTypesafeResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncTypesafeResourceWithStreamingResponse:
+ """
+ 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 AsyncTypesafeResourceWithStreamingResponse(self)
+
+
+class TypesafeResourceWithRawResponse:
+ def __init__(self, typesafe: TypesafeResource) -> None:
+ self._typesafe = typesafe
+
+ @cached_property
+ def v1(self) -> V1ResourceWithRawResponse:
+ """
+ Beta API for evaluating shared context with typed questions and structured answers. Telnyx manages model selection.
+ """
+ return V1ResourceWithRawResponse(self._typesafe.v1)
+
+
+class AsyncTypesafeResourceWithRawResponse:
+ def __init__(self, typesafe: AsyncTypesafeResource) -> None:
+ self._typesafe = typesafe
+
+ @cached_property
+ def v1(self) -> AsyncV1ResourceWithRawResponse:
+ """
+ Beta API for evaluating shared context with typed questions and structured answers. Telnyx manages model selection.
+ """
+ return AsyncV1ResourceWithRawResponse(self._typesafe.v1)
+
+
+class TypesafeResourceWithStreamingResponse:
+ def __init__(self, typesafe: TypesafeResource) -> None:
+ self._typesafe = typesafe
+
+ @cached_property
+ def v1(self) -> V1ResourceWithStreamingResponse:
+ """
+ Beta API for evaluating shared context with typed questions and structured answers. Telnyx manages model selection.
+ """
+ return V1ResourceWithStreamingResponse(self._typesafe.v1)
+
+
+class AsyncTypesafeResourceWithStreamingResponse:
+ def __init__(self, typesafe: AsyncTypesafeResource) -> None:
+ self._typesafe = typesafe
+
+ @cached_property
+ def v1(self) -> AsyncV1ResourceWithStreamingResponse:
+ """
+ Beta API for evaluating shared context with typed questions and structured answers. Telnyx manages model selection.
+ """
+ return AsyncV1ResourceWithStreamingResponse(self._typesafe.v1)
diff --git a/src/telnyx/resources/ai/typesafe/v1.py b/src/telnyx/resources/ai/typesafe/v1.py
new file mode 100644
index 000000000..f08ba8dfb
--- /dev/null
+++ b/src/telnyx/resources/ai/typesafe/v1.py
@@ -0,0 +1,231 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Dict, Union, Iterable
+
+import httpx
+
+from ...._types import Body, Query, Headers, NotGiven, not_given
+from ...._utils import maybe_transform, async_maybe_transform
+from ...._compat import cached_property
+from ...._resource import SyncAPIResource, AsyncAPIResource
+from ...._response import (
+ to_raw_response_wrapper,
+ to_streamed_response_wrapper,
+ async_to_raw_response_wrapper,
+ async_to_streamed_response_wrapper,
+)
+from ...._base_client import make_request_options
+from ....types.ai.typesafe import v1_systemone_params
+from ....types.ai.typesafe.v1_systemone_response import V1SystemoneResponse
+
+__all__ = ["V1Resource", "AsyncV1Resource"]
+
+
+class V1Resource(SyncAPIResource):
+ """
+ Beta API for evaluating shared context with typed questions and structured answers. Telnyx manages model selection.
+ """
+
+ @cached_property
+ def with_raw_response(self) -> V1ResourceWithRawResponse:
+ """
+ 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 V1ResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> V1ResourceWithStreamingResponse:
+ """
+ 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 V1ResourceWithStreamingResponse(self)
+
+ def systemone(
+ self,
+ *,
+ questions: Dict[str, v1_systemone_params.Questions],
+ state: Union[str, Dict[str, object], Iterable[object]],
+ # 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,
+ ) -> V1SystemoneResponse:
+ """
+ **Beta API.** Telnyx controls model selection.
+
+ Evaluate shared context using named choice, noul (yes/no), and score questions.
+ Returns TypeSafe System One-compatible answer shapes, an opaque compatibility
+ identifier, and token usage. See the
+ [decision model guide](https://developers.telnyx.com/docs/inference/decision-models)
+ for examples and compatibility limits.
+
+ The supported request subset requires instructions for every question, string
+ descriptions for criteria (or null for choice descriptions), 1–64 questions, and
+ 2–64 options for choice and score questions. The SDK-supplied model value is
+ ignored and cannot select a model. Other unknown fields are rejected. The
+ endpoint is synchronous and does not stream.
+
+ Use the TypeSafe Python SDK with base_url set to
+ https://api.telnyx.com/v2/ai/typesafe and a Telnyx API key. The SDK appends
+ /v1/systemone. Compatibility covers this operation and the documented request
+ subset; it does not include TypeSafe model listing. Scores describe relative
+ preference, not calibrated correctness.
+
+ Args:
+ questions: Between 1 and 64 named questions. Each key identifies the corresponding answer.
+
+ state: Shared context evaluated by every question.
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ return self._post(
+ "/ai/typesafe/v1/systemone",
+ body=maybe_transform(
+ {
+ "questions": questions,
+ "state": state,
+ },
+ v1_systemone_params.V1SystemoneParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=V1SystemoneResponse,
+ )
+
+
+class AsyncV1Resource(AsyncAPIResource):
+ """
+ Beta API for evaluating shared context with typed questions and structured answers. Telnyx manages model selection.
+ """
+
+ @cached_property
+ def with_raw_response(self) -> AsyncV1ResourceWithRawResponse:
+ """
+ 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 AsyncV1ResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncV1ResourceWithStreamingResponse:
+ """
+ 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 AsyncV1ResourceWithStreamingResponse(self)
+
+ async def systemone(
+ self,
+ *,
+ questions: Dict[str, v1_systemone_params.Questions],
+ state: Union[str, Dict[str, object], Iterable[object]],
+ # 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,
+ ) -> V1SystemoneResponse:
+ """
+ **Beta API.** Telnyx controls model selection.
+
+ Evaluate shared context using named choice, noul (yes/no), and score questions.
+ Returns TypeSafe System One-compatible answer shapes, an opaque compatibility
+ identifier, and token usage. See the
+ [decision model guide](https://developers.telnyx.com/docs/inference/decision-models)
+ for examples and compatibility limits.
+
+ The supported request subset requires instructions for every question, string
+ descriptions for criteria (or null for choice descriptions), 1–64 questions, and
+ 2–64 options for choice and score questions. The SDK-supplied model value is
+ ignored and cannot select a model. Other unknown fields are rejected. The
+ endpoint is synchronous and does not stream.
+
+ Use the TypeSafe Python SDK with base_url set to
+ https://api.telnyx.com/v2/ai/typesafe and a Telnyx API key. The SDK appends
+ /v1/systemone. Compatibility covers this operation and the documented request
+ subset; it does not include TypeSafe model listing. Scores describe relative
+ preference, not calibrated correctness.
+
+ Args:
+ questions: Between 1 and 64 named questions. Each key identifies the corresponding answer.
+
+ state: Shared context evaluated by every question.
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ return await self._post(
+ "/ai/typesafe/v1/systemone",
+ body=await async_maybe_transform(
+ {
+ "questions": questions,
+ "state": state,
+ },
+ v1_systemone_params.V1SystemoneParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=V1SystemoneResponse,
+ )
+
+
+class V1ResourceWithRawResponse:
+ def __init__(self, v1: V1Resource) -> None:
+ self._v1 = v1
+
+ self.systemone = to_raw_response_wrapper(
+ v1.systemone,
+ )
+
+
+class AsyncV1ResourceWithRawResponse:
+ def __init__(self, v1: AsyncV1Resource) -> None:
+ self._v1 = v1
+
+ self.systemone = async_to_raw_response_wrapper(
+ v1.systemone,
+ )
+
+
+class V1ResourceWithStreamingResponse:
+ def __init__(self, v1: V1Resource) -> None:
+ self._v1 = v1
+
+ self.systemone = to_streamed_response_wrapper(
+ v1.systemone,
+ )
+
+
+class AsyncV1ResourceWithStreamingResponse:
+ def __init__(self, v1: AsyncV1Resource) -> None:
+ self._v1 = v1
+
+ self.systemone = async_to_streamed_response_wrapper(
+ v1.systemone,
+ )
diff --git a/src/telnyx/resources/bot_challenge.py b/src/telnyx/resources/bot_challenge.py
new file mode 100644
index 000000000..de263a354
--- /dev/null
+++ b/src/telnyx/resources/bot_challenge.py
@@ -0,0 +1,221 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+import httpx
+
+from ..types import bot_challenge_create_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 (
+ 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.bot_challenge_create_response import BotChallengeCreateResponse
+
+__all__ = ["BotChallengeResource", "AsyncBotChallengeResource"]
+
+
+class BotChallengeResource(SyncAPIResource):
+ """Agentic (bot) signup for Telnyx accounts.
+
+ An AI agent solves a reverse-CAPTCHA challenge designed to be easy for LLMs and hard for humans, registers an account, and signs in by consuming a magic link emailed to the account owner. All endpoints are public and unauthenticated; signup endpoints are additionally gated by the freemium feature flags and per-country availability.
+ """
+
+ @cached_property
+ def with_raw_response(self) -> BotChallengeResourceWithRawResponse:
+ """
+ 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 BotChallengeResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> BotChallengeResourceWithStreamingResponse:
+ """
+ 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 BotChallengeResourceWithStreamingResponse(self)
+
+ def create(
+ self,
+ *,
+ llm_model_name: str | Omit = omit,
+ llm_parameter_count: str | Omit = omit,
+ llm_quantization: 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,
+ ) -> BotChallengeCreateResponse:
+ """Generates a reverse-CAPTCHA challenge used to gate the bot signup flow.
+
+ A random
+ active problem is selected from the pool; math problems are returned obfuscated
+ (case randomization, symbol injection, spacing noise) with an unobfuscated
+ rounding instruction appended, while string and binary problems are returned
+ as-is. The response contains a single-use nonce, the problem text, and the
+ current terms-and-conditions and privacy-policy URLs, which must be echoed back
+ on the signup request. Challenges expire after a short window (10 minutes by
+ default) and can only be answered once. This endpoint is public and
+ unauthenticated.
+
+ Args:
+ llm_model_name: Name of the LLM the client is using.
+
+ llm_parameter_count: Parameter count of the client LLM.
+
+ llm_quantization: Quantization of the client LLM.
+
+ 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(
+ "/v2/bot_challenge",
+ body=maybe_transform(
+ {
+ "llm_model_name": llm_model_name,
+ "llm_parameter_count": llm_parameter_count,
+ "llm_quantization": llm_quantization,
+ },
+ bot_challenge_create_params.BotChallengeCreateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=BotChallengeCreateResponse,
+ )
+
+
+class AsyncBotChallengeResource(AsyncAPIResource):
+ """Agentic (bot) signup for Telnyx accounts.
+
+ An AI agent solves a reverse-CAPTCHA challenge designed to be easy for LLMs and hard for humans, registers an account, and signs in by consuming a magic link emailed to the account owner. All endpoints are public and unauthenticated; signup endpoints are additionally gated by the freemium feature flags and per-country availability.
+ """
+
+ @cached_property
+ def with_raw_response(self) -> AsyncBotChallengeResourceWithRawResponse:
+ """
+ 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 AsyncBotChallengeResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncBotChallengeResourceWithStreamingResponse:
+ """
+ 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 AsyncBotChallengeResourceWithStreamingResponse(self)
+
+ async def create(
+ self,
+ *,
+ llm_model_name: str | Omit = omit,
+ llm_parameter_count: str | Omit = omit,
+ llm_quantization: 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,
+ ) -> BotChallengeCreateResponse:
+ """Generates a reverse-CAPTCHA challenge used to gate the bot signup flow.
+
+ A random
+ active problem is selected from the pool; math problems are returned obfuscated
+ (case randomization, symbol injection, spacing noise) with an unobfuscated
+ rounding instruction appended, while string and binary problems are returned
+ as-is. The response contains a single-use nonce, the problem text, and the
+ current terms-and-conditions and privacy-policy URLs, which must be echoed back
+ on the signup request. Challenges expire after a short window (10 minutes by
+ default) and can only be answered once. This endpoint is public and
+ unauthenticated.
+
+ Args:
+ llm_model_name: Name of the LLM the client is using.
+
+ llm_parameter_count: Parameter count of the client LLM.
+
+ llm_quantization: Quantization of the client LLM.
+
+ 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(
+ "/v2/bot_challenge",
+ body=await async_maybe_transform(
+ {
+ "llm_model_name": llm_model_name,
+ "llm_parameter_count": llm_parameter_count,
+ "llm_quantization": llm_quantization,
+ },
+ bot_challenge_create_params.BotChallengeCreateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=BotChallengeCreateResponse,
+ )
+
+
+class BotChallengeResourceWithRawResponse:
+ def __init__(self, bot_challenge: BotChallengeResource) -> None:
+ self._bot_challenge = bot_challenge
+
+ self.create = to_raw_response_wrapper(
+ bot_challenge.create,
+ )
+
+
+class AsyncBotChallengeResourceWithRawResponse:
+ def __init__(self, bot_challenge: AsyncBotChallengeResource) -> None:
+ self._bot_challenge = bot_challenge
+
+ self.create = async_to_raw_response_wrapper(
+ bot_challenge.create,
+ )
+
+
+class BotChallengeResourceWithStreamingResponse:
+ def __init__(self, bot_challenge: BotChallengeResource) -> None:
+ self._bot_challenge = bot_challenge
+
+ self.create = to_streamed_response_wrapper(
+ bot_challenge.create,
+ )
+
+
+class AsyncBotChallengeResourceWithStreamingResponse:
+ def __init__(self, bot_challenge: AsyncBotChallengeResource) -> None:
+ self._bot_challenge = bot_challenge
+
+ self.create = async_to_streamed_response_wrapper(
+ bot_challenge.create,
+ )
diff --git a/src/telnyx/resources/bot_sessions.py b/src/telnyx/resources/bot_sessions.py
new file mode 100644
index 000000000..702ac307f
--- /dev/null
+++ b/src/telnyx/resources/bot_sessions.py
@@ -0,0 +1,223 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+import httpx
+
+from ..types import bot_session_list_params
+from .._types import Body, Query, Headers, NotGiven, not_given
+from .._utils import maybe_transform, async_maybe_transform
+from .._compat import cached_property
+from .._resource import SyncAPIResource, AsyncAPIResource
+from .._response import (
+ to_raw_response_wrapper,
+ to_streamed_response_wrapper,
+ async_to_raw_response_wrapper,
+ async_to_streamed_response_wrapper,
+)
+from .._base_client import make_request_options
+from ..types.bot_session_list_response import BotSessionListResponse
+
+__all__ = ["BotSessionsResource", "AsyncBotSessionsResource"]
+
+
+class BotSessionsResource(SyncAPIResource):
+ """Agentic (bot) signup for Telnyx accounts.
+
+ An AI agent solves a reverse-CAPTCHA challenge designed to be easy for LLMs and hard for humans, registers an account, and signs in by consuming a magic link emailed to the account owner. All endpoints are public and unauthenticated; signup endpoints are additionally gated by the freemium feature flags and per-country availability.
+ """
+
+ @cached_property
+ def with_raw_response(self) -> BotSessionsResourceWithRawResponse:
+ """
+ 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 BotSessionsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> BotSessionsResourceWithStreamingResponse:
+ """
+ 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 BotSessionsResourceWithStreamingResponse(self)
+
+ def list(
+ self,
+ *,
+ email: str,
+ portal_redirect_token: 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,
+ ) -> BotSessionListResponse:
+ """
+ Consumes the one-time portal redirect (magic link) token emailed during bot
+ signup and returns an API session. The token is a UUIDv7 that encodes its
+ creation time; it expires after a configurable validity window (15 minutes by
+ default) and is cleared on first use. Although the action creates a session, the
+ route uses the GET verb because it is opened from an email link. On first use
+ the account is also initialized. For bot signup (freemium) accounts the response
+ is a minimal envelope containing only the `api_v2_token`; accounts that are
+ permitted to use magic links but are not freemium accounts may instead receive
+ an extended session payload when additional steps (such as two-factor
+ authentication or identity verification) are required. This endpoint is public;
+ the magic link token in the query string is the credential.
+
+ Args:
+ email: Email address associated with the magic link token.
+
+ portal_redirect_token: Single-use portal redirect (magic link) token, a UUIDv7 sent to the account
+ owner's email.
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ return self._get(
+ "/v2/bot_sessions",
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {
+ "email": email,
+ "portal_redirect_token": portal_redirect_token,
+ },
+ bot_session_list_params.BotSessionListParams,
+ ),
+ ),
+ cast_to=BotSessionListResponse,
+ )
+
+
+class AsyncBotSessionsResource(AsyncAPIResource):
+ """Agentic (bot) signup for Telnyx accounts.
+
+ An AI agent solves a reverse-CAPTCHA challenge designed to be easy for LLMs and hard for humans, registers an account, and signs in by consuming a magic link emailed to the account owner. All endpoints are public and unauthenticated; signup endpoints are additionally gated by the freemium feature flags and per-country availability.
+ """
+
+ @cached_property
+ def with_raw_response(self) -> AsyncBotSessionsResourceWithRawResponse:
+ """
+ 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 AsyncBotSessionsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncBotSessionsResourceWithStreamingResponse:
+ """
+ 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 AsyncBotSessionsResourceWithStreamingResponse(self)
+
+ async def list(
+ self,
+ *,
+ email: str,
+ portal_redirect_token: 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,
+ ) -> BotSessionListResponse:
+ """
+ Consumes the one-time portal redirect (magic link) token emailed during bot
+ signup and returns an API session. The token is a UUIDv7 that encodes its
+ creation time; it expires after a configurable validity window (15 minutes by
+ default) and is cleared on first use. Although the action creates a session, the
+ route uses the GET verb because it is opened from an email link. On first use
+ the account is also initialized. For bot signup (freemium) accounts the response
+ is a minimal envelope containing only the `api_v2_token`; accounts that are
+ permitted to use magic links but are not freemium accounts may instead receive
+ an extended session payload when additional steps (such as two-factor
+ authentication or identity verification) are required. This endpoint is public;
+ the magic link token in the query string is the credential.
+
+ Args:
+ email: Email address associated with the magic link token.
+
+ portal_redirect_token: Single-use portal redirect (magic link) token, a UUIDv7 sent to the account
+ owner's email.
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ return await self._get(
+ "/v2/bot_sessions",
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=await async_maybe_transform(
+ {
+ "email": email,
+ "portal_redirect_token": portal_redirect_token,
+ },
+ bot_session_list_params.BotSessionListParams,
+ ),
+ ),
+ cast_to=BotSessionListResponse,
+ )
+
+
+class BotSessionsResourceWithRawResponse:
+ def __init__(self, bot_sessions: BotSessionsResource) -> None:
+ self._bot_sessions = bot_sessions
+
+ self.list = to_raw_response_wrapper(
+ bot_sessions.list,
+ )
+
+
+class AsyncBotSessionsResourceWithRawResponse:
+ def __init__(self, bot_sessions: AsyncBotSessionsResource) -> None:
+ self._bot_sessions = bot_sessions
+
+ self.list = async_to_raw_response_wrapper(
+ bot_sessions.list,
+ )
+
+
+class BotSessionsResourceWithStreamingResponse:
+ def __init__(self, bot_sessions: BotSessionsResource) -> None:
+ self._bot_sessions = bot_sessions
+
+ self.list = to_streamed_response_wrapper(
+ bot_sessions.list,
+ )
+
+
+class AsyncBotSessionsResourceWithStreamingResponse:
+ def __init__(self, bot_sessions: AsyncBotSessionsResource) -> None:
+ self._bot_sessions = bot_sessions
+
+ self.list = async_to_streamed_response_wrapper(
+ bot_sessions.list,
+ )
diff --git a/src/telnyx/resources/bot_signup.py b/src/telnyx/resources/bot_signup.py
new file mode 100644
index 000000000..6492d523b
--- /dev/null
+++ b/src/telnyx/resources/bot_signup.py
@@ -0,0 +1,367 @@
+# 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 bot_signup_create_params, bot_signup_resend_magic_link_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 (
+ 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.success_response import SuccessResponse
+
+__all__ = ["BotSignupResource", "AsyncBotSignupResource"]
+
+
+class BotSignupResource(SyncAPIResource):
+ """Agentic (bot) signup for Telnyx accounts.
+
+ An AI agent solves a reverse-CAPTCHA challenge designed to be easy for LLMs and hard for humans, registers an account, and signs in by consuming a magic link emailed to the account owner. All endpoints are public and unauthenticated; signup endpoints are additionally gated by the freemium feature flags and per-country availability.
+ """
+
+ @cached_property
+ def with_raw_response(self) -> BotSignupResourceWithRawResponse:
+ """
+ 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 BotSignupResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> BotSignupResourceWithStreamingResponse:
+ """
+ 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 BotSignupResourceWithStreamingResponse(self)
+
+ def create(
+ self,
+ *,
+ bot_challenge_answer: str,
+ bot_challenge_nonce: str,
+ privacy_policy_url: str,
+ terms_and_conditions_url: str,
+ terms_of_service: Literal[True],
+ email: str | Omit = omit,
+ terms_and_conditions_eu_url: str | Omit = omit,
+ terms_of_service_eu: Literal[True] | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> SuccessResponse:
+ """Creates a freemium Telnyx account through the agentic signup flow.
+
+ The request
+ must carry a valid answer to a previously issued bot challenge
+ (`bot_challenge_nonce` and `bot_challenge_answer`), accept the terms of service,
+ and echo the exact terms-and-conditions and privacy-policy URLs returned by the
+ challenge endpoint. When EU consent enforcement is enabled,
+ `terms_of_service_eu` and `terms_and_conditions_eu_url` are also required. On
+ success a one-time sign-in (magic) link is emailed to the address provided; if
+ the email address belongs to an existing account, a sign-in link is sent instead
+ of creating a duplicate account. `email` may only be omitted when
+ placeholder-email registration is enabled server-side. This endpoint is public
+ and unauthenticated, gated by the freemium feature flags and per-country
+ availability, and subject to per-IP and per-domain registration limits.
+
+ Args:
+ bot_challenge_answer: Answer to the issued bot challenge.
+
+ bot_challenge_nonce: Nonce from a previously issued bot challenge.
+
+ privacy_policy_url: Must exactly match the privacy-policy URL returned by the challenge endpoint.
+
+ terms_and_conditions_url: Must exactly match the terms-and-conditions URL returned by the challenge
+ endpoint.
+
+ terms_of_service: Must be true to accept the terms of service.
+
+ email: Email address for the new account. The magic link is sent here. May only be
+ omitted when placeholder-email registration is enabled server-side.
+
+ terms_and_conditions_eu_url: EU terms-and-conditions URL. Required when EU consent enforcement is enabled.
+
+ terms_of_service_eu: EU terms-of-service acceptance. Required when EU consent enforcement is enabled.
+
+ 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(
+ "/v2/bot_signup",
+ body=maybe_transform(
+ {
+ "bot_challenge_answer": bot_challenge_answer,
+ "bot_challenge_nonce": bot_challenge_nonce,
+ "privacy_policy_url": privacy_policy_url,
+ "terms_and_conditions_url": terms_and_conditions_url,
+ "terms_of_service": terms_of_service,
+ "email": email,
+ "terms_and_conditions_eu_url": terms_and_conditions_eu_url,
+ "terms_of_service_eu": terms_of_service_eu,
+ },
+ bot_signup_create_params.BotSignupCreateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=SuccessResponse,
+ )
+
+ def resend_magic_link(
+ self,
+ *,
+ email: 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,
+ ) -> SuccessResponse:
+ """
+ Resends the one-time sign-in (magic) link for an eligible bot signup account.
+ Eligibility (account exists, was registered through bot signup, is active, and
+ has not exceeded the resend limit or rate window) is evaluated server-side; the
+ response is intentionally uniform and does not reveal whether the account exists
+ or whether a link was actually sent. This endpoint is public and
+ unauthenticated, gated by the freemium feature flags and per-country
+ availability.
+
+ Args:
+ email: Email address of the bot signup account to resend the magic link to.
+
+ 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(
+ "/v2/bot_signup/resend_magic_link",
+ body=maybe_transform({"email": email}, bot_signup_resend_magic_link_params.BotSignupResendMagicLinkParams),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=SuccessResponse,
+ )
+
+
+class AsyncBotSignupResource(AsyncAPIResource):
+ """Agentic (bot) signup for Telnyx accounts.
+
+ An AI agent solves a reverse-CAPTCHA challenge designed to be easy for LLMs and hard for humans, registers an account, and signs in by consuming a magic link emailed to the account owner. All endpoints are public and unauthenticated; signup endpoints are additionally gated by the freemium feature flags and per-country availability.
+ """
+
+ @cached_property
+ def with_raw_response(self) -> AsyncBotSignupResourceWithRawResponse:
+ """
+ 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 AsyncBotSignupResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncBotSignupResourceWithStreamingResponse:
+ """
+ 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 AsyncBotSignupResourceWithStreamingResponse(self)
+
+ async def create(
+ self,
+ *,
+ bot_challenge_answer: str,
+ bot_challenge_nonce: str,
+ privacy_policy_url: str,
+ terms_and_conditions_url: str,
+ terms_of_service: Literal[True],
+ email: str | Omit = omit,
+ terms_and_conditions_eu_url: str | Omit = omit,
+ terms_of_service_eu: Literal[True] | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> SuccessResponse:
+ """Creates a freemium Telnyx account through the agentic signup flow.
+
+ The request
+ must carry a valid answer to a previously issued bot challenge
+ (`bot_challenge_nonce` and `bot_challenge_answer`), accept the terms of service,
+ and echo the exact terms-and-conditions and privacy-policy URLs returned by the
+ challenge endpoint. When EU consent enforcement is enabled,
+ `terms_of_service_eu` and `terms_and_conditions_eu_url` are also required. On
+ success a one-time sign-in (magic) link is emailed to the address provided; if
+ the email address belongs to an existing account, a sign-in link is sent instead
+ of creating a duplicate account. `email` may only be omitted when
+ placeholder-email registration is enabled server-side. This endpoint is public
+ and unauthenticated, gated by the freemium feature flags and per-country
+ availability, and subject to per-IP and per-domain registration limits.
+
+ Args:
+ bot_challenge_answer: Answer to the issued bot challenge.
+
+ bot_challenge_nonce: Nonce from a previously issued bot challenge.
+
+ privacy_policy_url: Must exactly match the privacy-policy URL returned by the challenge endpoint.
+
+ terms_and_conditions_url: Must exactly match the terms-and-conditions URL returned by the challenge
+ endpoint.
+
+ terms_of_service: Must be true to accept the terms of service.
+
+ email: Email address for the new account. The magic link is sent here. May only be
+ omitted when placeholder-email registration is enabled server-side.
+
+ terms_and_conditions_eu_url: EU terms-and-conditions URL. Required when EU consent enforcement is enabled.
+
+ terms_of_service_eu: EU terms-of-service acceptance. Required when EU consent enforcement is enabled.
+
+ 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(
+ "/v2/bot_signup",
+ body=await async_maybe_transform(
+ {
+ "bot_challenge_answer": bot_challenge_answer,
+ "bot_challenge_nonce": bot_challenge_nonce,
+ "privacy_policy_url": privacy_policy_url,
+ "terms_and_conditions_url": terms_and_conditions_url,
+ "terms_of_service": terms_of_service,
+ "email": email,
+ "terms_and_conditions_eu_url": terms_and_conditions_eu_url,
+ "terms_of_service_eu": terms_of_service_eu,
+ },
+ bot_signup_create_params.BotSignupCreateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=SuccessResponse,
+ )
+
+ async def resend_magic_link(
+ self,
+ *,
+ email: 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,
+ ) -> SuccessResponse:
+ """
+ Resends the one-time sign-in (magic) link for an eligible bot signup account.
+ Eligibility (account exists, was registered through bot signup, is active, and
+ has not exceeded the resend limit or rate window) is evaluated server-side; the
+ response is intentionally uniform and does not reveal whether the account exists
+ or whether a link was actually sent. This endpoint is public and
+ unauthenticated, gated by the freemium feature flags and per-country
+ availability.
+
+ Args:
+ email: Email address of the bot signup account to resend the magic link to.
+
+ 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(
+ "/v2/bot_signup/resend_magic_link",
+ body=await async_maybe_transform(
+ {"email": email}, bot_signup_resend_magic_link_params.BotSignupResendMagicLinkParams
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=SuccessResponse,
+ )
+
+
+class BotSignupResourceWithRawResponse:
+ def __init__(self, bot_signup: BotSignupResource) -> None:
+ self._bot_signup = bot_signup
+
+ self.create = to_raw_response_wrapper(
+ bot_signup.create,
+ )
+ self.resend_magic_link = to_raw_response_wrapper(
+ bot_signup.resend_magic_link,
+ )
+
+
+class AsyncBotSignupResourceWithRawResponse:
+ def __init__(self, bot_signup: AsyncBotSignupResource) -> None:
+ self._bot_signup = bot_signup
+
+ self.create = async_to_raw_response_wrapper(
+ bot_signup.create,
+ )
+ self.resend_magic_link = async_to_raw_response_wrapper(
+ bot_signup.resend_magic_link,
+ )
+
+
+class BotSignupResourceWithStreamingResponse:
+ def __init__(self, bot_signup: BotSignupResource) -> None:
+ self._bot_signup = bot_signup
+
+ self.create = to_streamed_response_wrapper(
+ bot_signup.create,
+ )
+ self.resend_magic_link = to_streamed_response_wrapper(
+ bot_signup.resend_magic_link,
+ )
+
+
+class AsyncBotSignupResourceWithStreamingResponse:
+ def __init__(self, bot_signup: AsyncBotSignupResource) -> None:
+ self._bot_signup = bot_signup
+
+ self.create = async_to_streamed_response_wrapper(
+ bot_signup.create,
+ )
+ self.resend_magic_link = async_to_streamed_response_wrapper(
+ bot_signup.resend_magic_link,
+ )
diff --git a/src/telnyx/resources/calls/actions.py b/src/telnyx/resources/calls/actions.py
index fb47700f6..c6c8c5eb2 100644
--- a/src/telnyx/resources/calls/actions.py
+++ b/src/telnyx/resources/calls/actions.py
@@ -4019,11 +4019,12 @@ def transfer(
custom_headers: Custom headers to be added to the SIP INVITE.
- diversion: The number the inbound call being transferred was originally received on, in
- +E164 format. Supplying it lets an unverified non-Telnyx `from` be used as the
- caller id, provided that number is still on an active inbound call to this
- `diversion` number for your account. The `diversion` number itself must be one
- you own or have verified.
+ diversion: The `to` number of an active inbound call, in +E164 format. Telnyx checks
+ whether there is currently an active inbound call where `to` matches this
+ `diversion` value and `from` matches the `from` number supplied for this
+ request. If such a call exists, the `from` number is treated as verified (since
+ it is already on an active inbound call to you) and can be used as the caller id
+ for this outbound call.
early_media: If set to false, early media will not be passed to the originating leg.
@@ -8143,11 +8144,12 @@ async def transfer(
custom_headers: Custom headers to be added to the SIP INVITE.
- diversion: The number the inbound call being transferred was originally received on, in
- +E164 format. Supplying it lets an unverified non-Telnyx `from` be used as the
- caller id, provided that number is still on an active inbound call to this
- `diversion` number for your account. The `diversion` number itself must be one
- you own or have verified.
+ diversion: The `to` number of an active inbound call, in +E164 format. Telnyx checks
+ whether there is currently an active inbound call where `to` matches this
+ `diversion` value and `from` matches the `from` number supplied for this
+ request. If such a call exists, the `from` number is treated as verified (since
+ it is already on an active inbound call to you) and can be used as the caller id
+ for this outbound call.
early_media: If set to false, early media will not be passed to the originating leg.
diff --git a/src/telnyx/resources/calls/calls.py b/src/telnyx/resources/calls/calls.py
index 1b14cf68e..d12e0b6d5 100644
--- a/src/telnyx/resources/calls/calls.py
+++ b/src/telnyx/resources/calls/calls.py
@@ -264,11 +264,12 @@ def dial(
AI-generated. Results are delivered via the `call.deepfake_detection.result`
webhook.
- diversion: The number the inbound call being transferred was originally received on, in
- +E164 format. Supplying it lets an unverified non-Telnyx `from` be used as the
- caller id, provided that number is still on an active inbound call to this
- `diversion` number for your account. The `diversion` number itself must be one
- you own or have verified.
+ diversion: The `to` number of an active inbound call, in +E164 format. Telnyx checks
+ whether there is currently an active inbound call where `to` matches this
+ `diversion` value and `from` matches the `from` number supplied for this
+ request. If such a call exists, the `from` number is treated as verified (since
+ it is already on an active inbound call to you) and can be used as the caller id
+ for this outbound call.
enable_dialogflow: Enables Dialogflow for the current call. The default value is false.
@@ -761,11 +762,12 @@ async def dial(
AI-generated. Results are delivered via the `call.deepfake_detection.result`
webhook.
- diversion: The number the inbound call being transferred was originally received on, in
- +E164 format. Supplying it lets an unverified non-Telnyx `from` be used as the
- caller id, provided that number is still on an active inbound call to this
- `diversion` number for your account. The `diversion` number itself must be one
- you own or have verified.
+ diversion: The `to` number of an active inbound call, in +E164 format. Telnyx checks
+ whether there is currently an active inbound call where `to` matches this
+ `diversion` value and `from` matches the `from` number supplied for this
+ request. If such a call exists, the `from` number is treated as verified (since
+ it is already on an active inbound call to you) and can be used as the caller id
+ for this outbound call.
enable_dialogflow: Enables Dialogflow for the current call. The default value is false.
diff --git a/src/telnyx/resources/compute/compute.py b/src/telnyx/resources/compute/compute.py
index 5a77c3552..819bc2039 100644
--- a/src/telnyx/resources/compute/compute.py
+++ b/src/telnyx/resources/compute/compute.py
@@ -2,7 +2,9 @@
from __future__ import annotations
-from .funcs import (
+from ..._compat import cached_property
+from ..._resource import SyncAPIResource, AsyncAPIResource
+from .funcs.funcs import (
FuncsResource,
AsyncFuncsResource,
FuncsResourceWithRawResponse,
@@ -10,8 +12,6 @@
FuncsResourceWithStreamingResponse,
AsyncFuncsResourceWithStreamingResponse,
)
-from ..._compat import cached_property
-from ..._resource import SyncAPIResource, AsyncAPIResource
__all__ = ["ComputeResource", "AsyncComputeResource"]
diff --git a/src/telnyx/resources/compute/funcs/__init__.py b/src/telnyx/resources/compute/funcs/__init__.py
new file mode 100644
index 000000000..6c19a73cf
--- /dev/null
+++ b/src/telnyx/resources/compute/funcs/__init__.py
@@ -0,0 +1,33 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from .funcs import (
+ FuncsResource,
+ AsyncFuncsResource,
+ FuncsResourceWithRawResponse,
+ AsyncFuncsResourceWithRawResponse,
+ FuncsResourceWithStreamingResponse,
+ AsyncFuncsResourceWithStreamingResponse,
+)
+from .export import (
+ ExportResource,
+ AsyncExportResource,
+ ExportResourceWithRawResponse,
+ AsyncExportResourceWithRawResponse,
+ ExportResourceWithStreamingResponse,
+ AsyncExportResourceWithStreamingResponse,
+)
+
+__all__ = [
+ "ExportResource",
+ "AsyncExportResource",
+ "ExportResourceWithRawResponse",
+ "AsyncExportResourceWithRawResponse",
+ "ExportResourceWithStreamingResponse",
+ "AsyncExportResourceWithStreamingResponse",
+ "FuncsResource",
+ "AsyncFuncsResource",
+ "FuncsResourceWithRawResponse",
+ "AsyncFuncsResourceWithRawResponse",
+ "FuncsResourceWithStreamingResponse",
+ "AsyncFuncsResourceWithStreamingResponse",
+]
diff --git a/src/telnyx/resources/compute/funcs/export.py b/src/telnyx/resources/compute/funcs/export.py
new file mode 100644
index 000000000..269bfaa9b
--- /dev/null
+++ b/src/telnyx/resources/compute/funcs/export.py
@@ -0,0 +1,399 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Dict
+
+import httpx
+
+from ...._types import Body, Query, Headers, NoneType, NotGiven, not_given
+from ...._utils import path_template, maybe_transform, async_maybe_transform
+from ...._compat import cached_property
+from ...._resource import SyncAPIResource, AsyncAPIResource
+from ...._response import (
+ 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.compute.funcs import export_create_params
+from ....types.compute.funcs.func_log_export_config_response import FuncLogExportConfigResponse
+
+__all__ = ["ExportResource", "AsyncExportResource"]
+
+
+class ExportResource(SyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> ExportResourceWithRawResponse:
+ """
+ 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 ExportResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> ExportResourceWithStreamingResponse:
+ """
+ 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 ExportResourceWithStreamingResponse(self)
+
+ def create(
+ self,
+ id: str,
+ *,
+ endpoint: str,
+ headers: Dict[str, str],
+ invocation_export_enabled: bool,
+ runtime_export_enabled: bool,
+ # 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,
+ ) -> FuncLogExportConfigResponse:
+ """
+ Configures the external OTLP endpoint a function's runtime and/or invocation
+ logs are pushed to as they happen. This operation is a **full replace, not a
+ patch**: `endpoint`, `headers`, `runtime_export_enabled`, and
+ `invocation_export_enabled` are all required on every call — omitting any of
+ them is a 422, not "keep the current value". Headers are encrypted at rest and
+ never returned in any response.
+
+ The endpoint must be an HTTPS URL. When export is configured, new log records
+ are converted to OTLP log records and delivered continuously; export never
+ bypasses platform log storage, and delivery retries with a bounded policy while
+ the destination is unreachable. Only logs generated after configuration are
+ exported — there is no historical replay.
+
+ Args:
+ endpoint: HTTPS URL to push logs to
+
+ headers: Headers attached to every export push, as key-value pairs (e.g. an auth token
+ the collector expects). Required even when empty — {} means "no headers".
+ Encrypted at rest; never returned.
+
+ invocation_export_enabled: Export invocation records (one per HTTP request) to this destination
+
+ runtime_export_enabled: Export runtime logs (function stdout/stderr) to this destination
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ if not id:
+ raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
+ return self._put(
+ path_template("/compute/funcs/{id}/logs/export", id=id),
+ body=maybe_transform(
+ {
+ "endpoint": endpoint,
+ "headers": headers,
+ "invocation_export_enabled": invocation_export_enabled,
+ "runtime_export_enabled": runtime_export_enabled,
+ },
+ export_create_params.ExportCreateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=FuncLogExportConfigResponse,
+ )
+
+ def list(
+ self,
+ id: str,
+ *,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> FuncLogExportConfigResponse:
+ """
+ Returns the function's configured log export destination and which log types are
+ exported. Headers are never returned. Returns 404 (error code 10005) when no
+ destination is configured for the function.
+
+ Args:
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ if not id:
+ raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
+ return self._get(
+ path_template("/compute/funcs/{id}/logs/export", id=id),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=FuncLogExportConfigResponse,
+ )
+
+ def delete_all(
+ self,
+ id: str,
+ *,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> None:
+ """
+ Stops exporting a function's logs and removes its destination configuration.
+ Idempotent: deleting when nothing is configured succeeds.
+
+ Args:
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ if not id:
+ raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
+ extra_headers = {"Accept": "*/*", **(extra_headers or {})}
+ return self._delete(
+ path_template("/compute/funcs/{id}/logs/export", id=id),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=NoneType,
+ )
+
+
+class AsyncExportResource(AsyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> AsyncExportResourceWithRawResponse:
+ """
+ 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 AsyncExportResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncExportResourceWithStreamingResponse:
+ """
+ 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 AsyncExportResourceWithStreamingResponse(self)
+
+ async def create(
+ self,
+ id: str,
+ *,
+ endpoint: str,
+ headers: Dict[str, str],
+ invocation_export_enabled: bool,
+ runtime_export_enabled: bool,
+ # 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,
+ ) -> FuncLogExportConfigResponse:
+ """
+ Configures the external OTLP endpoint a function's runtime and/or invocation
+ logs are pushed to as they happen. This operation is a **full replace, not a
+ patch**: `endpoint`, `headers`, `runtime_export_enabled`, and
+ `invocation_export_enabled` are all required on every call — omitting any of
+ them is a 422, not "keep the current value". Headers are encrypted at rest and
+ never returned in any response.
+
+ The endpoint must be an HTTPS URL. When export is configured, new log records
+ are converted to OTLP log records and delivered continuously; export never
+ bypasses platform log storage, and delivery retries with a bounded policy while
+ the destination is unreachable. Only logs generated after configuration are
+ exported — there is no historical replay.
+
+ Args:
+ endpoint: HTTPS URL to push logs to
+
+ headers: Headers attached to every export push, as key-value pairs (e.g. an auth token
+ the collector expects). Required even when empty — {} means "no headers".
+ Encrypted at rest; never returned.
+
+ invocation_export_enabled: Export invocation records (one per HTTP request) to this destination
+
+ runtime_export_enabled: Export runtime logs (function stdout/stderr) to this destination
+
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ if not id:
+ raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
+ return await self._put(
+ path_template("/compute/funcs/{id}/logs/export", id=id),
+ body=await async_maybe_transform(
+ {
+ "endpoint": endpoint,
+ "headers": headers,
+ "invocation_export_enabled": invocation_export_enabled,
+ "runtime_export_enabled": runtime_export_enabled,
+ },
+ export_create_params.ExportCreateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=FuncLogExportConfigResponse,
+ )
+
+ async def list(
+ self,
+ id: str,
+ *,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> FuncLogExportConfigResponse:
+ """
+ Returns the function's configured log export destination and which log types are
+ exported. Headers are never returned. Returns 404 (error code 10005) when no
+ destination is configured for the function.
+
+ Args:
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ if not id:
+ raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
+ return await self._get(
+ path_template("/compute/funcs/{id}/logs/export", id=id),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=FuncLogExportConfigResponse,
+ )
+
+ async def delete_all(
+ self,
+ id: str,
+ *,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> None:
+ """
+ Stops exporting a function's logs and removes its destination configuration.
+ Idempotent: deleting when nothing is configured succeeds.
+
+ Args:
+ extra_headers: Send extra headers
+
+ extra_query: Add additional query parameters to the request
+
+ extra_body: Add additional JSON properties to the request
+
+ timeout: Override the client-level default timeout for this request, in seconds
+ """
+ if not id:
+ raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
+ extra_headers = {"Accept": "*/*", **(extra_headers or {})}
+ return await self._delete(
+ path_template("/compute/funcs/{id}/logs/export", id=id),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=NoneType,
+ )
+
+
+class ExportResourceWithRawResponse:
+ def __init__(self, export: ExportResource) -> None:
+ self._export = export
+
+ self.create = to_raw_response_wrapper(
+ export.create,
+ )
+ self.list = to_raw_response_wrapper(
+ export.list,
+ )
+ self.delete_all = to_raw_response_wrapper(
+ export.delete_all,
+ )
+
+
+class AsyncExportResourceWithRawResponse:
+ def __init__(self, export: AsyncExportResource) -> None:
+ self._export = export
+
+ self.create = async_to_raw_response_wrapper(
+ export.create,
+ )
+ self.list = async_to_raw_response_wrapper(
+ export.list,
+ )
+ self.delete_all = async_to_raw_response_wrapper(
+ export.delete_all,
+ )
+
+
+class ExportResourceWithStreamingResponse:
+ def __init__(self, export: ExportResource) -> None:
+ self._export = export
+
+ self.create = to_streamed_response_wrapper(
+ export.create,
+ )
+ self.list = to_streamed_response_wrapper(
+ export.list,
+ )
+ self.delete_all = to_streamed_response_wrapper(
+ export.delete_all,
+ )
+
+
+class AsyncExportResourceWithStreamingResponse:
+ def __init__(self, export: AsyncExportResource) -> None:
+ self._export = export
+
+ self.create = async_to_streamed_response_wrapper(
+ export.create,
+ )
+ self.list = async_to_streamed_response_wrapper(
+ export.list,
+ )
+ self.delete_all = async_to_streamed_response_wrapper(
+ export.delete_all,
+ )
diff --git a/src/telnyx/resources/compute/funcs.py b/src/telnyx/resources/compute/funcs/funcs.py
similarity index 92%
rename from src/telnyx/resources/compute/funcs.py
rename to src/telnyx/resources/compute/funcs/funcs.py
index 512b8839d..3c62edd12 100644
--- a/src/telnyx/resources/compute/funcs.py
+++ b/src/telnyx/resources/compute/funcs/funcs.py
@@ -8,31 +8,43 @@
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 (
+from .export import (
+ ExportResource,
+ AsyncExportResource,
+ ExportResourceWithRawResponse,
+ AsyncExportResourceWithRawResponse,
+ ExportResourceWithStreamingResponse,
+ AsyncExportResourceWithStreamingResponse,
+)
+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.compute import (
+from ...._base_client import make_request_options
+from ....types.compute import (
func_retrieve_logs_params,
func_retrieve_revisions_params,
func_retrieve_metric_aggregates_params,
)
-from ...types.compute.func_retrieve_logs_response import FuncRetrieveLogsResponse
-from ...types.compute.func_retrieve_revisions_response import FuncRetrieveRevisionsResponse
-from ...types.compute.func_retrieve_ship_inspection_response import FuncRetrieveShipInspectionResponse
-from ...types.compute.func_retrieve_metric_aggregates_response import FuncRetrieveMetricAggregatesResponse
+from ....types.compute.func_retrieve_logs_response import FuncRetrieveLogsResponse
+from ....types.compute.func_retrieve_revisions_response import FuncRetrieveRevisionsResponse
+from ....types.compute.func_retrieve_ship_inspection_response import FuncRetrieveShipInspectionResponse
+from ....types.compute.func_retrieve_metric_aggregates_response import FuncRetrieveMetricAggregatesResponse
__all__ = ["FuncsResource", "AsyncFuncsResource"]
class FuncsResource(SyncAPIResource):
+ @cached_property
+ def export(self) -> ExportResource:
+ return ExportResource(self._client)
+
@cached_property
def with_raw_response(self) -> FuncsResourceWithRawResponse:
"""
@@ -264,6 +276,10 @@ def retrieve_ship_inspection(
class AsyncFuncsResource(AsyncAPIResource):
+ @cached_property
+ def export(self) -> AsyncExportResource:
+ return AsyncExportResource(self._client)
+
@cached_property
def with_raw_response(self) -> AsyncFuncsResourceWithRawResponse:
"""
@@ -511,6 +527,10 @@ def __init__(self, funcs: FuncsResource) -> None:
funcs.retrieve_ship_inspection,
)
+ @cached_property
+ def export(self) -> ExportResourceWithRawResponse:
+ return ExportResourceWithRawResponse(self._funcs.export)
+
class AsyncFuncsResourceWithRawResponse:
def __init__(self, funcs: AsyncFuncsResource) -> None:
@@ -529,6 +549,10 @@ def __init__(self, funcs: AsyncFuncsResource) -> None:
funcs.retrieve_ship_inspection,
)
+ @cached_property
+ def export(self) -> AsyncExportResourceWithRawResponse:
+ return AsyncExportResourceWithRawResponse(self._funcs.export)
+
class FuncsResourceWithStreamingResponse:
def __init__(self, funcs: FuncsResource) -> None:
@@ -547,6 +571,10 @@ def __init__(self, funcs: FuncsResource) -> None:
funcs.retrieve_ship_inspection,
)
+ @cached_property
+ def export(self) -> ExportResourceWithStreamingResponse:
+ return ExportResourceWithStreamingResponse(self._funcs.export)
+
class AsyncFuncsResourceWithStreamingResponse:
def __init__(self, funcs: AsyncFuncsResource) -> None:
@@ -564,3 +592,7 @@ def __init__(self, funcs: AsyncFuncsResource) -> None:
self.retrieve_ship_inspection = async_to_streamed_response_wrapper(
funcs.retrieve_ship_inspection,
)
+
+ @cached_property
+ def export(self) -> AsyncExportResourceWithStreamingResponse:
+ return AsyncExportResourceWithStreamingResponse(self._funcs.export)
diff --git a/src/telnyx/resources/connections.py b/src/telnyx/resources/connections.py
index 91f6fa264..7acb3e9a8 100644
--- a/src/telnyx/resources/connections.py
+++ b/src/telnyx/resources/connections.py
@@ -21,6 +21,7 @@
from .._base_client import AsyncPaginator, make_request_options
from ..types.connection import Connection
from ..types.connection_retrieve_response import ConnectionRetrieveResponse
+from ..types.connection_retrieve_count_response import ConnectionRetrieveCountResponse
from ..types.connection_list_active_calls_response import ConnectionListActiveCallsResponse
__all__ = ["ConnectionsResource", "AsyncConnectionsResource"]
@@ -197,6 +198,29 @@ def list_active_calls(
model=ConnectionListActiveCallsResponse,
)
+ def retrieve_count(
+ 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,
+ ) -> ConnectionRetrieveCountResponse:
+ """
+ Returns the number of connections associated with the authenticated user,
+ grouped by connection type, together with the connection limits that apply to
+ the user. Forward-only connections are excluded from the counts.
+ """
+ return self._get(
+ "/connections/count",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ConnectionRetrieveCountResponse,
+ )
+
class AsyncConnectionsResource(AsyncAPIResource):
@cached_property
@@ -371,6 +395,29 @@ def list_active_calls(
model=ConnectionListActiveCallsResponse,
)
+ async def retrieve_count(
+ 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,
+ ) -> ConnectionRetrieveCountResponse:
+ """
+ Returns the number of connections associated with the authenticated user,
+ grouped by connection type, together with the connection limits that apply to
+ the user. Forward-only connections are excluded from the counts.
+ """
+ return await self._get(
+ "/connections/count",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ConnectionRetrieveCountResponse,
+ )
+
class ConnectionsResourceWithRawResponse:
def __init__(self, connections: ConnectionsResource) -> None:
@@ -385,6 +432,9 @@ def __init__(self, connections: ConnectionsResource) -> None:
self.list_active_calls = to_raw_response_wrapper(
connections.list_active_calls,
)
+ self.retrieve_count = to_raw_response_wrapper(
+ connections.retrieve_count,
+ )
class AsyncConnectionsResourceWithRawResponse:
@@ -400,6 +450,9 @@ def __init__(self, connections: AsyncConnectionsResource) -> None:
self.list_active_calls = async_to_raw_response_wrapper(
connections.list_active_calls,
)
+ self.retrieve_count = async_to_raw_response_wrapper(
+ connections.retrieve_count,
+ )
class ConnectionsResourceWithStreamingResponse:
@@ -415,6 +468,9 @@ def __init__(self, connections: ConnectionsResource) -> None:
self.list_active_calls = to_streamed_response_wrapper(
connections.list_active_calls,
)
+ self.retrieve_count = to_streamed_response_wrapper(
+ connections.retrieve_count,
+ )
class AsyncConnectionsResourceWithStreamingResponse:
@@ -430,3 +486,6 @@ def __init__(self, connections: AsyncConnectionsResource) -> None:
self.list_active_calls = async_to_streamed_response_wrapper(
connections.list_active_calls,
)
+ self.retrieve_count = async_to_streamed_response_wrapper(
+ connections.retrieve_count,
+ )
diff --git a/src/telnyx/resources/detail_records.py b/src/telnyx/resources/detail_records.py
index df6bbafaf..f98825951 100644
--- a/src/telnyx/resources/detail_records.py
+++ b/src/telnyx/resources/detail_records.py
@@ -67,8 +67,19 @@ def list(
filter:
Filter records on a given record attribute and value.
Example:
filter[status]=delivered.
Required: filter[record_type] must be specified.
-
- sort: Specifies the sort order for results.
Example: sort=-created_at
+
The valid filter fields depend on the record_type: filtering by a field
+ that does not exist for the selected record_type is rejected with a 400 error.
+ Call-control and sip-trunking records use started_at, finished_at and
+ answered_at (they have no created_at); messaging records use created_at. To list
+ the fields available for a record_type, use the /v2/detail_records/options
+ endpoint.
+
+ sort: Specifies the sort order for results.
Example: sort=-created_at
The
+ valid sort fields depend on the record_type: sort by a field that does not exist
+ for the selected record_type is rejected with a 400 error. Call-control and
+ sip-trunking records use started_at, finished_at and answered_at (they have no
+ created_at); messaging records use created_at. To list the fields available for
+ a record_type, use the /v2/detail_records/options endpoint.
extra_headers: Send extra headers
@@ -145,8 +156,19 @@ def list(
filter:
Filter records on a given record attribute and value.
Example:
filter[status]=delivered.
Required: filter[record_type] must be specified.
-
- sort: Specifies the sort order for results.
Example: sort=-created_at
+
The valid filter fields depend on the record_type: filtering by a field
+ that does not exist for the selected record_type is rejected with a 400 error.
+ Call-control and sip-trunking records use started_at, finished_at and
+ answered_at (they have no created_at); messaging records use created_at. To list
+ the fields available for a record_type, use the /v2/detail_records/options
+ endpoint.
+
+ sort: Specifies the sort order for results.
Example: sort=-created_at
The
+ valid sort fields depend on the record_type: sort by a field that does not exist
+ for the selected record_type is rejected with a 400 error. Call-control and
+ sip-trunking records use started_at, finished_at and answered_at (they have no
+ created_at); messaging records use created_at. To list the fields available for
+ a record_type, use the /v2/detail_records/options endpoint.
extra_headers: Send extra headers
diff --git a/src/telnyx/resources/email_messages/email_messages.py b/src/telnyx/resources/email_messages/email_messages.py
index c8d444293..574c5efc6 100644
--- a/src/telnyx/resources/email_messages/email_messages.py
+++ b/src/telnyx/resources/email_messages/email_messages.py
@@ -384,9 +384,11 @@ def batch(
) -> EmailMessageBatchResponse:
"""Creates up to 1,000 email messages in a single request.
- Each message is
- validated and sent independently; per-message failures do not affect other
- messages in the batch. All responses use 207 Multi-Status.
+ Request-wide admission
+ checks run first and can reject the whole batch before message creation. After
+ those checks pass, each message is validated and sent independently; item-level
+ failures do not affect other messages, and the processed batch returns 207
+ Multi-Status.
Args:
messages: Array of email messages to send. Up to 1,000 messages per batch request. Each
@@ -891,9 +893,11 @@ async def batch(
) -> EmailMessageBatchResponse:
"""Creates up to 1,000 email messages in a single request.
- Each message is
- validated and sent independently; per-message failures do not affect other
- messages in the batch. All responses use 207 Multi-Status.
+ Request-wide admission
+ checks run first and can reject the whole batch before message creation. After
+ those checks pass, each message is validated and sent independently; item-level
+ failures do not affect other messages, and the processed batch returns 207
+ Multi-Status.
Args:
messages: Array of email messages to send. Up to 1,000 messages per batch request. Each
diff --git a/src/telnyx/resources/machine_payments.py b/src/telnyx/resources/machine_payments.py
new file mode 100644
index 000000000..d8abc8c94
--- /dev/null
+++ b/src/telnyx/resources/machine_payments.py
@@ -0,0 +1,251 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+import httpx
+
+from ..types import machine_payment_account_credit_params
+from .._types import Body, Query, Headers, NotGiven, not_given
+from .._utils import maybe_transform, async_maybe_transform
+from .._compat import cached_property
+from .._resource import SyncAPIResource, AsyncAPIResource
+from .._response import (
+ to_raw_response_wrapper,
+ to_streamed_response_wrapper,
+ async_to_raw_response_wrapper,
+ async_to_streamed_response_wrapper,
+)
+from .._base_client import make_request_options
+from ..types.machine_payment_account_credit_response import MachinePaymentAccountCreditResponse
+
+__all__ = ["MachinePaymentsResource", "AsyncMachinePaymentsResource"]
+
+
+class MachinePaymentsResource(SyncAPIResource):
+ """Machine payment (MPP) account-credit operations.
+
+ Fund your Telnyx account programmatically from a machine or agent using the Machine Payment Protocol, an HTTP-402 flow settled via Stripe or Tempo.
+ """
+
+ @cached_property
+ def with_raw_response(self) -> MachinePaymentsResourceWithRawResponse:
+ """
+ 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 MachinePaymentsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> MachinePaymentsResourceWithStreamingResponse:
+ """
+ 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 MachinePaymentsResourceWithStreamingResponse(self)
+
+ def account_credit(
+ self,
+ *,
+ amount_usd: 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,
+ ) -> MachinePaymentAccountCreditResponse:
+ """
+ Creates an account credit using the Machine Payment Protocol (MPP), an HTTP-402
+ payment flow for machines and agents.
+
+ The flow has two steps. First, send an authenticated request with the
+ `amount_usd` to credit; the response is `402 Payment Required` with one or more
+ payment challenges (for example separate Tempo and Stripe challenges) in the
+ `WWW-Authenticate` header. Second, retry the request with an
+ `Authorization: Payment ...` credential constructed from the challenge; on
+ success the response includes the credited transaction and a `Payment-Receipt`
+ header.
+
+ The credited account is never chosen by the request body: the initial request
+ credits the account of the authenticated user, and a paid retry credits the
+ account bound to the verified payment credential. The amount must be within the
+ configured bounds (by default between 5.00 and 500.00 USD).
+
+ Successful paid retries are idempotent — when Rails reaches its
+ duplicate-transaction lookup for an already-recorded payment, it returns the
+ existing transaction with `created: false` instead of crediting the account
+ again. This deduplication applies to successful fulfillment: re-sending the same
+ Stripe credential may instead be rejected by the upstream provider as an
+ idempotent replay and return `402 Payment Required` rather than the existing
+ transaction.
+
+ > **Warning: the payment credential is bound to a specific Telnyx account ID.**
+ > A payment is captured before the bound account is validated. If the credential
+ > names an account that is missing, suspended, blocked, cancelled, dormant, or
+ > ineligible for the tier, the payment is captured but **no account is
+ > credited**. If the credential names a different but eligible account, that
+ > account is credited — the service does not compare it against the payer's
+ > account. There is **no automatic refund**: if the captured payment does not
+ > credit the intended account, contact Telnyx support for remediation.
+
+ Args:
+ amount_usd: Amount to credit in USD, as a decimal string with up to two fractional digits
+ (by default between 5.00 and 500.00). The request body is required on the
+ initial challenge request and remains required on a paid retry, where you
+ re-send the identical body plus the payment credential — the credential, not the
+ body, selects the payment, and the retried body is not re-validated.
+
+ 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(
+ "/machine-payments/account-credit",
+ body=maybe_transform(
+ {"amount_usd": amount_usd}, machine_payment_account_credit_params.MachinePaymentAccountCreditParams
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=MachinePaymentAccountCreditResponse,
+ )
+
+
+class AsyncMachinePaymentsResource(AsyncAPIResource):
+ """Machine payment (MPP) account-credit operations.
+
+ Fund your Telnyx account programmatically from a machine or agent using the Machine Payment Protocol, an HTTP-402 flow settled via Stripe or Tempo.
+ """
+
+ @cached_property
+ def with_raw_response(self) -> AsyncMachinePaymentsResourceWithRawResponse:
+ """
+ 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 AsyncMachinePaymentsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncMachinePaymentsResourceWithStreamingResponse:
+ """
+ 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 AsyncMachinePaymentsResourceWithStreamingResponse(self)
+
+ async def account_credit(
+ self,
+ *,
+ amount_usd: 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,
+ ) -> MachinePaymentAccountCreditResponse:
+ """
+ Creates an account credit using the Machine Payment Protocol (MPP), an HTTP-402
+ payment flow for machines and agents.
+
+ The flow has two steps. First, send an authenticated request with the
+ `amount_usd` to credit; the response is `402 Payment Required` with one or more
+ payment challenges (for example separate Tempo and Stripe challenges) in the
+ `WWW-Authenticate` header. Second, retry the request with an
+ `Authorization: Payment ...` credential constructed from the challenge; on
+ success the response includes the credited transaction and a `Payment-Receipt`
+ header.
+
+ The credited account is never chosen by the request body: the initial request
+ credits the account of the authenticated user, and a paid retry credits the
+ account bound to the verified payment credential. The amount must be within the
+ configured bounds (by default between 5.00 and 500.00 USD).
+
+ Successful paid retries are idempotent — when Rails reaches its
+ duplicate-transaction lookup for an already-recorded payment, it returns the
+ existing transaction with `created: false` instead of crediting the account
+ again. This deduplication applies to successful fulfillment: re-sending the same
+ Stripe credential may instead be rejected by the upstream provider as an
+ idempotent replay and return `402 Payment Required` rather than the existing
+ transaction.
+
+ > **Warning: the payment credential is bound to a specific Telnyx account ID.**
+ > A payment is captured before the bound account is validated. If the credential
+ > names an account that is missing, suspended, blocked, cancelled, dormant, or
+ > ineligible for the tier, the payment is captured but **no account is
+ > credited**. If the credential names a different but eligible account, that
+ > account is credited — the service does not compare it against the payer's
+ > account. There is **no automatic refund**: if the captured payment does not
+ > credit the intended account, contact Telnyx support for remediation.
+
+ Args:
+ amount_usd: Amount to credit in USD, as a decimal string with up to two fractional digits
+ (by default between 5.00 and 500.00). The request body is required on the
+ initial challenge request and remains required on a paid retry, where you
+ re-send the identical body plus the payment credential — the credential, not the
+ body, selects the payment, and the retried body is not re-validated.
+
+ 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(
+ "/machine-payments/account-credit",
+ body=await async_maybe_transform(
+ {"amount_usd": amount_usd}, machine_payment_account_credit_params.MachinePaymentAccountCreditParams
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=MachinePaymentAccountCreditResponse,
+ )
+
+
+class MachinePaymentsResourceWithRawResponse:
+ def __init__(self, machine_payments: MachinePaymentsResource) -> None:
+ self._machine_payments = machine_payments
+
+ self.account_credit = to_raw_response_wrapper(
+ machine_payments.account_credit,
+ )
+
+
+class AsyncMachinePaymentsResourceWithRawResponse:
+ def __init__(self, machine_payments: AsyncMachinePaymentsResource) -> None:
+ self._machine_payments = machine_payments
+
+ self.account_credit = async_to_raw_response_wrapper(
+ machine_payments.account_credit,
+ )
+
+
+class MachinePaymentsResourceWithStreamingResponse:
+ def __init__(self, machine_payments: MachinePaymentsResource) -> None:
+ self._machine_payments = machine_payments
+
+ self.account_credit = to_streamed_response_wrapper(
+ machine_payments.account_credit,
+ )
+
+
+class AsyncMachinePaymentsResourceWithStreamingResponse:
+ def __init__(self, machine_payments: AsyncMachinePaymentsResource) -> None:
+ self._machine_payments = machine_payments
+
+ self.account_credit = async_to_streamed_response_wrapper(
+ machine_payments.account_credit,
+ )
diff --git a/src/telnyx/resources/noise_suppression_engines.py b/src/telnyx/resources/noise_suppression_engines.py
new file mode 100644
index 000000000..331e6e61f
--- /dev/null
+++ b/src/telnyx/resources/noise_suppression_engines.py
@@ -0,0 +1,153 @@
+# 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.noise_suppression_engine_list_response import NoiseSuppressionEngineListResponse
+
+__all__ = ["NoiseSuppressionEnginesResource", "AsyncNoiseSuppressionEnginesResource"]
+
+
+class NoiseSuppressionEnginesResource(SyncAPIResource):
+ """
+ Noise suppression engines that can be selected when configuring noise suppression on voice connections.
+ """
+
+ @cached_property
+ def with_raw_response(self) -> NoiseSuppressionEnginesResourceWithRawResponse:
+ """
+ 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 NoiseSuppressionEnginesResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> NoiseSuppressionEnginesResourceWithStreamingResponse:
+ """
+ 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 NoiseSuppressionEnginesResourceWithStreamingResponse(self)
+
+ def list(
+ self,
+ *,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> NoiseSuppressionEngineListResponse:
+ """
+ Returns all noise suppression engines available to the authenticated user.
+ Engines gated behind a feature flag are included only when the flag is enabled
+ for the user's account. Results are not paginated; the number of engines is
+ expected to remain small.
+ """
+ return self._get(
+ "/noise_suppression_engines",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=NoiseSuppressionEngineListResponse,
+ )
+
+
+class AsyncNoiseSuppressionEnginesResource(AsyncAPIResource):
+ """
+ Noise suppression engines that can be selected when configuring noise suppression on voice connections.
+ """
+
+ @cached_property
+ def with_raw_response(self) -> AsyncNoiseSuppressionEnginesResourceWithRawResponse:
+ """
+ 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 AsyncNoiseSuppressionEnginesResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncNoiseSuppressionEnginesResourceWithStreamingResponse:
+ """
+ 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 AsyncNoiseSuppressionEnginesResourceWithStreamingResponse(self)
+
+ async def list(
+ self,
+ *,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> NoiseSuppressionEngineListResponse:
+ """
+ Returns all noise suppression engines available to the authenticated user.
+ Engines gated behind a feature flag are included only when the flag is enabled
+ for the user's account. Results are not paginated; the number of engines is
+ expected to remain small.
+ """
+ return await self._get(
+ "/noise_suppression_engines",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=NoiseSuppressionEngineListResponse,
+ )
+
+
+class NoiseSuppressionEnginesResourceWithRawResponse:
+ def __init__(self, noise_suppression_engines: NoiseSuppressionEnginesResource) -> None:
+ self._noise_suppression_engines = noise_suppression_engines
+
+ self.list = to_raw_response_wrapper(
+ noise_suppression_engines.list,
+ )
+
+
+class AsyncNoiseSuppressionEnginesResourceWithRawResponse:
+ def __init__(self, noise_suppression_engines: AsyncNoiseSuppressionEnginesResource) -> None:
+ self._noise_suppression_engines = noise_suppression_engines
+
+ self.list = async_to_raw_response_wrapper(
+ noise_suppression_engines.list,
+ )
+
+
+class NoiseSuppressionEnginesResourceWithStreamingResponse:
+ def __init__(self, noise_suppression_engines: NoiseSuppressionEnginesResource) -> None:
+ self._noise_suppression_engines = noise_suppression_engines
+
+ self.list = to_streamed_response_wrapper(
+ noise_suppression_engines.list,
+ )
+
+
+class AsyncNoiseSuppressionEnginesResourceWithStreamingResponse:
+ def __init__(self, noise_suppression_engines: AsyncNoiseSuppressionEnginesResource) -> None:
+ self._noise_suppression_engines = noise_suppression_engines
+
+ self.list = async_to_streamed_response_wrapper(
+ noise_suppression_engines.list,
+ )
diff --git a/src/telnyx/resources/speech_to_text.py b/src/telnyx/resources/speech_to_text.py
index cbad154af..222dd39d1 100644
--- a/src/telnyx/resources/speech_to_text.py
+++ b/src/telnyx/resources/speech_to_text.py
@@ -193,6 +193,7 @@ def retrieve_transcription(
"speechmatics/standard",
"soniox/stt-rt-v4",
"nvidia/parakeet-v3",
+ "omi-health/omi-med-stt-v1",
"humain/realtime",
"reson8/turns",
"cohere/ar-stt",
@@ -465,6 +466,7 @@ async def retrieve_transcription(
"speechmatics/standard",
"soniox/stt-rt-v4",
"nvidia/parakeet-v3",
+ "omi-health/omi-med-stt-v1",
"humain/realtime",
"reson8/turns",
"cohere/ar-stt",
diff --git a/src/telnyx/resources/texml/__init__.py b/src/telnyx/resources/texml/__init__.py
index e5cfbfc32..20315ac4f 100644
--- a/src/telnyx/resources/texml/__init__.py
+++ b/src/telnyx/resources/texml/__init__.py
@@ -1,5 +1,13 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+from .calls import (
+ CallsResource,
+ AsyncCallsResource,
+ CallsResourceWithRawResponse,
+ AsyncCallsResourceWithRawResponse,
+ CallsResourceWithStreamingResponse,
+ AsyncCallsResourceWithStreamingResponse,
+)
from .texml import (
TexmlResource,
AsyncTexmlResource,
@@ -18,6 +26,12 @@
)
__all__ = [
+ "CallsResource",
+ "AsyncCallsResource",
+ "CallsResourceWithRawResponse",
+ "AsyncCallsResourceWithRawResponse",
+ "CallsResourceWithStreamingResponse",
+ "AsyncCallsResourceWithStreamingResponse",
"AccountsResource",
"AsyncAccountsResource",
"AccountsResourceWithRawResponse",
diff --git a/src/telnyx/resources/texml/accounts/conferences/participants.py b/src/telnyx/resources/texml/accounts/conferences/participants.py
index bd05c3979..4834d3ccb 100644
--- a/src/telnyx/resources/texml/accounts/conferences/participants.py
+++ b/src/telnyx/resources/texml/accounts/conferences/participants.py
@@ -278,7 +278,14 @@ def participants(
from_: str | Omit = omit,
label: str | Omit = omit,
machine_detection: Literal["Enable", "DetectMessageEnd"] | Omit = omit,
+ machine_detection_beep_max_frequency: int | Omit = omit,
+ machine_detection_beep_min_frequency: int | Omit = omit,
+ machine_detection_beep_min_tone_duration: int | Omit = omit,
machine_detection_beep_profile: Literal["both", "freq_only"] | Omit = omit,
+ machine_detection_beep_spectral_confirmation: bool | Omit = omit,
+ machine_detection_beep_spectral_min_purity: float | Omit = omit,
+ machine_detection_beep_spectral_reject_fax_cng: bool | Omit = omit,
+ machine_detection_beep_spectral_window: int | Omit = omit,
machine_detection_silence_timeout: int | Omit = omit,
machine_detection_speech_end_threshold: int | Omit = omit,
machine_detection_speech_threshold: int | Omit = omit,
@@ -391,11 +398,36 @@ def participants(
identified. Use `DetectMessageEnd`, if you would like to leave a message on an
answering machine.
+ machine_detection_beep_max_frequency: Highest frequency, in Hz, that a tone can reach and still be treated as a beep.
+ Only used when MachineDetection is enabled.
+
+ machine_detection_beep_min_frequency: Lowest frequency, in Hz, that a tone must reach to be treated as a beep. Raising
+ it above 480 excludes North American ringback (440 + 480 Hz), which can
+ otherwise be reported as a beep when the `freq_only` profile is in use. Only
+ used when MachineDetection is enabled.
+
+ machine_detection_beep_min_tone_duration: Shortest tone, in milliseconds, that can be treated as a beep. Raising it
+ rejects brief tones such as call-progress blips. Only used when MachineDetection
+ is enabled.
+
machine_detection_beep_profile: Selects which detectors must validate a beep. `both` requires the amplitude and
frequency detectors to agree. `freq_only` uses the frequency detector alone, for
beeps whose volume is too unsteady for the default profile. Only used when
MachineDetection is enabled.
+ machine_detection_beep_spectral_confirmation: When enabled, a candidate beep must pass an additional spectral check before it
+ is reported. Only used when MachineDetection is enabled.
+
+ machine_detection_beep_spectral_min_purity: Minimum spectral purity, from 0 to 1, for a tone to be treated as a beep.
+ Raising it rejects mixed tones such as ringback, which combines two frequencies.
+ Only used when MachineDetection is enabled.
+
+ machine_detection_beep_spectral_reject_fax_cng: When enabled, the fax CNG tone is rejected rather than reported as a beep. Only
+ used when MachineDetection is enabled.
+
+ machine_detection_beep_spectral_window: Length of the spectral confirmation window, in milliseconds. Only used when
+ MachineDetection is enabled.
+
machine_detection_silence_timeout: If initial silence duration is greater than this value, consider it a machine.
Ignored when `premium` detection is used.
@@ -502,7 +534,14 @@ def participants(
"from_": from_,
"label": label,
"machine_detection": machine_detection,
+ "machine_detection_beep_max_frequency": machine_detection_beep_max_frequency,
+ "machine_detection_beep_min_frequency": machine_detection_beep_min_frequency,
+ "machine_detection_beep_min_tone_duration": machine_detection_beep_min_tone_duration,
"machine_detection_beep_profile": machine_detection_beep_profile,
+ "machine_detection_beep_spectral_confirmation": machine_detection_beep_spectral_confirmation,
+ "machine_detection_beep_spectral_min_purity": machine_detection_beep_spectral_min_purity,
+ "machine_detection_beep_spectral_reject_fax_cng": machine_detection_beep_spectral_reject_fax_cng,
+ "machine_detection_beep_spectral_window": machine_detection_beep_spectral_window,
"machine_detection_silence_timeout": machine_detection_silence_timeout,
"machine_detection_speech_end_threshold": machine_detection_speech_end_threshold,
"machine_detection_speech_threshold": machine_detection_speech_threshold,
@@ -827,7 +866,14 @@ async def participants(
from_: str | Omit = omit,
label: str | Omit = omit,
machine_detection: Literal["Enable", "DetectMessageEnd"] | Omit = omit,
+ machine_detection_beep_max_frequency: int | Omit = omit,
+ machine_detection_beep_min_frequency: int | Omit = omit,
+ machine_detection_beep_min_tone_duration: int | Omit = omit,
machine_detection_beep_profile: Literal["both", "freq_only"] | Omit = omit,
+ machine_detection_beep_spectral_confirmation: bool | Omit = omit,
+ machine_detection_beep_spectral_min_purity: float | Omit = omit,
+ machine_detection_beep_spectral_reject_fax_cng: bool | Omit = omit,
+ machine_detection_beep_spectral_window: int | Omit = omit,
machine_detection_silence_timeout: int | Omit = omit,
machine_detection_speech_end_threshold: int | Omit = omit,
machine_detection_speech_threshold: int | Omit = omit,
@@ -940,11 +986,36 @@ async def participants(
identified. Use `DetectMessageEnd`, if you would like to leave a message on an
answering machine.
+ machine_detection_beep_max_frequency: Highest frequency, in Hz, that a tone can reach and still be treated as a beep.
+ Only used when MachineDetection is enabled.
+
+ machine_detection_beep_min_frequency: Lowest frequency, in Hz, that a tone must reach to be treated as a beep. Raising
+ it above 480 excludes North American ringback (440 + 480 Hz), which can
+ otherwise be reported as a beep when the `freq_only` profile is in use. Only
+ used when MachineDetection is enabled.
+
+ machine_detection_beep_min_tone_duration: Shortest tone, in milliseconds, that can be treated as a beep. Raising it
+ rejects brief tones such as call-progress blips. Only used when MachineDetection
+ is enabled.
+
machine_detection_beep_profile: Selects which detectors must validate a beep. `both` requires the amplitude and
frequency detectors to agree. `freq_only` uses the frequency detector alone, for
beeps whose volume is too unsteady for the default profile. Only used when
MachineDetection is enabled.
+ machine_detection_beep_spectral_confirmation: When enabled, a candidate beep must pass an additional spectral check before it
+ is reported. Only used when MachineDetection is enabled.
+
+ machine_detection_beep_spectral_min_purity: Minimum spectral purity, from 0 to 1, for a tone to be treated as a beep.
+ Raising it rejects mixed tones such as ringback, which combines two frequencies.
+ Only used when MachineDetection is enabled.
+
+ machine_detection_beep_spectral_reject_fax_cng: When enabled, the fax CNG tone is rejected rather than reported as a beep. Only
+ used when MachineDetection is enabled.
+
+ machine_detection_beep_spectral_window: Length of the spectral confirmation window, in milliseconds. Only used when
+ MachineDetection is enabled.
+
machine_detection_silence_timeout: If initial silence duration is greater than this value, consider it a machine.
Ignored when `premium` detection is used.
@@ -1051,7 +1122,14 @@ async def participants(
"from_": from_,
"label": label,
"machine_detection": machine_detection,
+ "machine_detection_beep_max_frequency": machine_detection_beep_max_frequency,
+ "machine_detection_beep_min_frequency": machine_detection_beep_min_frequency,
+ "machine_detection_beep_min_tone_duration": machine_detection_beep_min_tone_duration,
"machine_detection_beep_profile": machine_detection_beep_profile,
+ "machine_detection_beep_spectral_confirmation": machine_detection_beep_spectral_confirmation,
+ "machine_detection_beep_spectral_min_purity": machine_detection_beep_spectral_min_purity,
+ "machine_detection_beep_spectral_reject_fax_cng": machine_detection_beep_spectral_reject_fax_cng,
+ "machine_detection_beep_spectral_window": machine_detection_beep_spectral_window,
"machine_detection_silence_timeout": machine_detection_silence_timeout,
"machine_detection_speech_end_threshold": machine_detection_speech_end_threshold,
"machine_detection_speech_threshold": machine_detection_speech_threshold,
diff --git a/src/telnyx/resources/texml/calls.py b/src/telnyx/resources/texml/calls.py
new file mode 100644
index 000000000..c6ff7c9df
--- /dev/null
+++ b/src/telnyx/resources/texml/calls.py
@@ -0,0 +1,233 @@
+# 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.texml import call_create_params
+from ..._base_client import make_request_options
+from ...types.texml.call_create_response import CallCreateResponse
+
+__all__ = ["CallsResource", "AsyncCallsResource"]
+
+
+class CallsResource(SyncAPIResource):
+ """TeXML REST Commands"""
+
+ @cached_property
+ def with_raw_response(self) -> CallsResourceWithRawResponse:
+ """
+ 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 CallsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> CallsResourceWithStreamingResponse:
+ """
+ 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 CallsResourceWithStreamingResponse(self)
+
+ def create(
+ self,
+ connection_id: str,
+ *,
+ from_: str,
+ to: str,
+ method: Literal["GET", "POST"] | Omit = omit,
+ texml: str | Omit = omit,
+ url: 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,
+ ) -> CallCreateResponse:
+ """
+ Initiate an outbound TeXML call using a TeXML application connection ID, not an
+ account SID. Request parameter names are case-sensitive. From and To are
+ required; Texml supplies inline instructions and Url overrides the application
+ XML request URL. When neither is supplied, the application configuration
+ supplies the instructions. The response is a flat call object without a data
+ wrapper.
+
+ Args:
+ from_: The E.164-formatted phone number or SIP URI to present as the caller.
+
+ to: The E.164-formatted phone number or SIP URI to call.
+
+ method: HTTP method used to retrieve TeXML instructions from Url.
+
+ texml: Inline TeXML instructions to execute when the call is answered.
+
+ url: The URL from which to retrieve TeXML instructions. Overrides the TeXML
+ application XML request URL.
+
+ 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 connection_id:
+ raise ValueError(f"Expected a non-empty value for `connection_id` but received {connection_id!r}")
+ return self._post(
+ path_template("/texml/calls/{connection_id}", connection_id=connection_id),
+ body=maybe_transform(
+ {
+ "from_": from_,
+ "to": to,
+ "method": method,
+ "texml": texml,
+ "url": url,
+ },
+ call_create_params.CallCreateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=CallCreateResponse,
+ )
+
+
+class AsyncCallsResource(AsyncAPIResource):
+ """TeXML REST Commands"""
+
+ @cached_property
+ def with_raw_response(self) -> AsyncCallsResourceWithRawResponse:
+ """
+ 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 AsyncCallsResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncCallsResourceWithStreamingResponse:
+ """
+ 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 AsyncCallsResourceWithStreamingResponse(self)
+
+ async def create(
+ self,
+ connection_id: str,
+ *,
+ from_: str,
+ to: str,
+ method: Literal["GET", "POST"] | Omit = omit,
+ texml: str | Omit = omit,
+ url: 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,
+ ) -> CallCreateResponse:
+ """
+ Initiate an outbound TeXML call using a TeXML application connection ID, not an
+ account SID. Request parameter names are case-sensitive. From and To are
+ required; Texml supplies inline instructions and Url overrides the application
+ XML request URL. When neither is supplied, the application configuration
+ supplies the instructions. The response is a flat call object without a data
+ wrapper.
+
+ Args:
+ from_: The E.164-formatted phone number or SIP URI to present as the caller.
+
+ to: The E.164-formatted phone number or SIP URI to call.
+
+ method: HTTP method used to retrieve TeXML instructions from Url.
+
+ texml: Inline TeXML instructions to execute when the call is answered.
+
+ url: The URL from which to retrieve TeXML instructions. Overrides the TeXML
+ application XML request URL.
+
+ 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 connection_id:
+ raise ValueError(f"Expected a non-empty value for `connection_id` but received {connection_id!r}")
+ return await self._post(
+ path_template("/texml/calls/{connection_id}", connection_id=connection_id),
+ body=await async_maybe_transform(
+ {
+ "from_": from_,
+ "to": to,
+ "method": method,
+ "texml": texml,
+ "url": url,
+ },
+ call_create_params.CallCreateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=CallCreateResponse,
+ )
+
+
+class CallsResourceWithRawResponse:
+ def __init__(self, calls: CallsResource) -> None:
+ self._calls = calls
+
+ self.create = to_raw_response_wrapper(
+ calls.create,
+ )
+
+
+class AsyncCallsResourceWithRawResponse:
+ def __init__(self, calls: AsyncCallsResource) -> None:
+ self._calls = calls
+
+ self.create = async_to_raw_response_wrapper(
+ calls.create,
+ )
+
+
+class CallsResourceWithStreamingResponse:
+ def __init__(self, calls: CallsResource) -> None:
+ self._calls = calls
+
+ self.create = to_streamed_response_wrapper(
+ calls.create,
+ )
+
+
+class AsyncCallsResourceWithStreamingResponse:
+ def __init__(self, calls: AsyncCallsResource) -> None:
+ self._calls = calls
+
+ self.create = async_to_streamed_response_wrapper(
+ calls.create,
+ )
diff --git a/src/telnyx/resources/texml/texml.py b/src/telnyx/resources/texml/texml.py
index bbb107605..3364bf4f2 100644
--- a/src/telnyx/resources/texml/texml.py
+++ b/src/telnyx/resources/texml/texml.py
@@ -7,6 +7,14 @@
import httpx
+from .calls import (
+ CallsResource,
+ AsyncCallsResource,
+ CallsResourceWithRawResponse,
+ AsyncCallsResourceWithRawResponse,
+ CallsResourceWithStreamingResponse,
+ AsyncCallsResourceWithStreamingResponse,
+)
from ...types import texml_secrets_params, texml_initiate_ai_call_params
from ..._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given
from ..._utils import path_template, maybe_transform, async_maybe_transform
@@ -36,6 +44,11 @@
class TexmlResource(SyncAPIResource):
"""TeXML REST Commands"""
+ @cached_property
+ def calls(self) -> CallsResource:
+ """TeXML REST Commands"""
+ return CallsResource(self._client)
+
@cached_property
def accounts(self) -> AccountsResource:
"""TeXML REST Commands"""
@@ -79,7 +92,14 @@ def initiate_ai_call(
custom_headers: Iterable[texml_initiate_ai_call_params.CustomHeader] | Omit = omit,
detection_mode: Literal["Premium", "Regular", "PremiumCallScreening"] | Omit = omit,
machine_detection: Literal["Enable", "Disable", "DetectMessageEnd"] | Omit = omit,
+ machine_detection_beep_max_frequency: int | Omit = omit,
+ machine_detection_beep_min_frequency: int | Omit = omit,
+ machine_detection_beep_min_tone_duration: int | Omit = omit,
machine_detection_beep_profile: Literal["both", "freq_only"] | Omit = omit,
+ machine_detection_beep_spectral_confirmation: bool | Omit = omit,
+ machine_detection_beep_spectral_min_purity: float | Omit = omit,
+ machine_detection_beep_spectral_reject_fax_cng: bool | Omit = omit,
+ machine_detection_beep_spectral_window: int | Omit = omit,
machine_detection_prompt_end_timeout: int | Omit = omit,
machine_detection_silence_timeout: int | Omit = omit,
machine_detection_speech_end_threshold: int | Omit = omit,
@@ -172,11 +192,36 @@ def initiate_ai_call(
machine_detection: Enables Answering Machine Detection.
+ machine_detection_beep_max_frequency: Highest frequency, in Hz, that a tone can reach and still be treated as a beep.
+ Only used when MachineDetection is enabled.
+
+ machine_detection_beep_min_frequency: Lowest frequency, in Hz, that a tone must reach to be treated as a beep. Raising
+ it above 480 excludes North American ringback (440 + 480 Hz), which can
+ otherwise be reported as a beep when the `freq_only` profile is in use. Only
+ used when MachineDetection is enabled.
+
+ machine_detection_beep_min_tone_duration: Shortest tone, in milliseconds, that can be treated as a beep. Raising it
+ rejects brief tones such as call-progress blips. Only used when MachineDetection
+ is enabled.
+
machine_detection_beep_profile: Selects which detectors must validate a beep. `both` requires the amplitude and
frequency detectors to agree. `freq_only` uses the frequency detector alone, for
beeps whose volume is too unsteady for the default profile. Only used when
MachineDetection is enabled.
+ machine_detection_beep_spectral_confirmation: When enabled, a candidate beep must pass an additional spectral check before it
+ is reported. Only used when MachineDetection is enabled.
+
+ machine_detection_beep_spectral_min_purity: Minimum spectral purity, from 0 to 1, for a tone to be treated as a beep.
+ Raising it rejects mixed tones such as ringback, which combines two frequencies.
+ Only used when MachineDetection is enabled.
+
+ machine_detection_beep_spectral_reject_fax_cng: When enabled, the fax CNG tone is rejected rather than reported as a beep. Only
+ used when MachineDetection is enabled.
+
+ machine_detection_beep_spectral_window: Length of the spectral confirmation window, in milliseconds. Only used when
+ MachineDetection is enabled.
+
machine_detection_prompt_end_timeout: Silence duration threshold after a call screening prompt before ending prompt
detection, in milliseconds. Used when `DetectionMode` is `PremiumCallScreening`.
@@ -278,7 +323,14 @@ def initiate_ai_call(
"custom_headers": custom_headers,
"detection_mode": detection_mode,
"machine_detection": machine_detection,
+ "machine_detection_beep_max_frequency": machine_detection_beep_max_frequency,
+ "machine_detection_beep_min_frequency": machine_detection_beep_min_frequency,
+ "machine_detection_beep_min_tone_duration": machine_detection_beep_min_tone_duration,
"machine_detection_beep_profile": machine_detection_beep_profile,
+ "machine_detection_beep_spectral_confirmation": machine_detection_beep_spectral_confirmation,
+ "machine_detection_beep_spectral_min_purity": machine_detection_beep_spectral_min_purity,
+ "machine_detection_beep_spectral_reject_fax_cng": machine_detection_beep_spectral_reject_fax_cng,
+ "machine_detection_beep_spectral_window": machine_detection_beep_spectral_window,
"machine_detection_prompt_end_timeout": machine_detection_prompt_end_timeout,
"machine_detection_silence_timeout": machine_detection_silence_timeout,
"machine_detection_speech_end_threshold": machine_detection_speech_end_threshold,
@@ -365,6 +417,11 @@ def secrets(
class AsyncTexmlResource(AsyncAPIResource):
"""TeXML REST Commands"""
+ @cached_property
+ def calls(self) -> AsyncCallsResource:
+ """TeXML REST Commands"""
+ return AsyncCallsResource(self._client)
+
@cached_property
def accounts(self) -> AsyncAccountsResource:
"""TeXML REST Commands"""
@@ -408,7 +465,14 @@ async def initiate_ai_call(
custom_headers: Iterable[texml_initiate_ai_call_params.CustomHeader] | Omit = omit,
detection_mode: Literal["Premium", "Regular", "PremiumCallScreening"] | Omit = omit,
machine_detection: Literal["Enable", "Disable", "DetectMessageEnd"] | Omit = omit,
+ machine_detection_beep_max_frequency: int | Omit = omit,
+ machine_detection_beep_min_frequency: int | Omit = omit,
+ machine_detection_beep_min_tone_duration: int | Omit = omit,
machine_detection_beep_profile: Literal["both", "freq_only"] | Omit = omit,
+ machine_detection_beep_spectral_confirmation: bool | Omit = omit,
+ machine_detection_beep_spectral_min_purity: float | Omit = omit,
+ machine_detection_beep_spectral_reject_fax_cng: bool | Omit = omit,
+ machine_detection_beep_spectral_window: int | Omit = omit,
machine_detection_prompt_end_timeout: int | Omit = omit,
machine_detection_silence_timeout: int | Omit = omit,
machine_detection_speech_end_threshold: int | Omit = omit,
@@ -501,11 +565,36 @@ async def initiate_ai_call(
machine_detection: Enables Answering Machine Detection.
+ machine_detection_beep_max_frequency: Highest frequency, in Hz, that a tone can reach and still be treated as a beep.
+ Only used when MachineDetection is enabled.
+
+ machine_detection_beep_min_frequency: Lowest frequency, in Hz, that a tone must reach to be treated as a beep. Raising
+ it above 480 excludes North American ringback (440 + 480 Hz), which can
+ otherwise be reported as a beep when the `freq_only` profile is in use. Only
+ used when MachineDetection is enabled.
+
+ machine_detection_beep_min_tone_duration: Shortest tone, in milliseconds, that can be treated as a beep. Raising it
+ rejects brief tones such as call-progress blips. Only used when MachineDetection
+ is enabled.
+
machine_detection_beep_profile: Selects which detectors must validate a beep. `both` requires the amplitude and
frequency detectors to agree. `freq_only` uses the frequency detector alone, for
beeps whose volume is too unsteady for the default profile. Only used when
MachineDetection is enabled.
+ machine_detection_beep_spectral_confirmation: When enabled, a candidate beep must pass an additional spectral check before it
+ is reported. Only used when MachineDetection is enabled.
+
+ machine_detection_beep_spectral_min_purity: Minimum spectral purity, from 0 to 1, for a tone to be treated as a beep.
+ Raising it rejects mixed tones such as ringback, which combines two frequencies.
+ Only used when MachineDetection is enabled.
+
+ machine_detection_beep_spectral_reject_fax_cng: When enabled, the fax CNG tone is rejected rather than reported as a beep. Only
+ used when MachineDetection is enabled.
+
+ machine_detection_beep_spectral_window: Length of the spectral confirmation window, in milliseconds. Only used when
+ MachineDetection is enabled.
+
machine_detection_prompt_end_timeout: Silence duration threshold after a call screening prompt before ending prompt
detection, in milliseconds. Used when `DetectionMode` is `PremiumCallScreening`.
@@ -607,7 +696,14 @@ async def initiate_ai_call(
"custom_headers": custom_headers,
"detection_mode": detection_mode,
"machine_detection": machine_detection,
+ "machine_detection_beep_max_frequency": machine_detection_beep_max_frequency,
+ "machine_detection_beep_min_frequency": machine_detection_beep_min_frequency,
+ "machine_detection_beep_min_tone_duration": machine_detection_beep_min_tone_duration,
"machine_detection_beep_profile": machine_detection_beep_profile,
+ "machine_detection_beep_spectral_confirmation": machine_detection_beep_spectral_confirmation,
+ "machine_detection_beep_spectral_min_purity": machine_detection_beep_spectral_min_purity,
+ "machine_detection_beep_spectral_reject_fax_cng": machine_detection_beep_spectral_reject_fax_cng,
+ "machine_detection_beep_spectral_window": machine_detection_beep_spectral_window,
"machine_detection_prompt_end_timeout": machine_detection_prompt_end_timeout,
"machine_detection_silence_timeout": machine_detection_silence_timeout,
"machine_detection_speech_end_threshold": machine_detection_speech_end_threshold,
@@ -702,6 +798,11 @@ def __init__(self, texml: TexmlResource) -> None:
texml.secrets,
)
+ @cached_property
+ def calls(self) -> CallsResourceWithRawResponse:
+ """TeXML REST Commands"""
+ return CallsResourceWithRawResponse(self._texml.calls)
+
@cached_property
def accounts(self) -> AccountsResourceWithRawResponse:
"""TeXML REST Commands"""
@@ -719,6 +820,11 @@ def __init__(self, texml: AsyncTexmlResource) -> None:
texml.secrets,
)
+ @cached_property
+ def calls(self) -> AsyncCallsResourceWithRawResponse:
+ """TeXML REST Commands"""
+ return AsyncCallsResourceWithRawResponse(self._texml.calls)
+
@cached_property
def accounts(self) -> AsyncAccountsResourceWithRawResponse:
"""TeXML REST Commands"""
@@ -736,6 +842,11 @@ def __init__(self, texml: TexmlResource) -> None:
texml.secrets,
)
+ @cached_property
+ def calls(self) -> CallsResourceWithStreamingResponse:
+ """TeXML REST Commands"""
+ return CallsResourceWithStreamingResponse(self._texml.calls)
+
@cached_property
def accounts(self) -> AccountsResourceWithStreamingResponse:
"""TeXML REST Commands"""
@@ -753,6 +864,11 @@ def __init__(self, texml: AsyncTexmlResource) -> None:
texml.secrets,
)
+ @cached_property
+ def calls(self) -> AsyncCallsResourceWithStreamingResponse:
+ """TeXML REST Commands"""
+ return AsyncCallsResourceWithStreamingResponse(self._texml.calls)
+
@cached_property
def accounts(self) -> AsyncAccountsResourceWithStreamingResponse:
"""TeXML REST Commands"""
diff --git a/src/telnyx/resources/voice_clones.py b/src/telnyx/resources/voice_clones.py
index b8fd5aabf..a686b5bbc 100644
--- a/src/telnyx/resources/voice_clones.py
+++ b/src/telnyx/resources/voice_clones.py
@@ -257,8 +257,10 @@ def create_from_upload(
"""Creates a new voice clone by uploading an audio file directly.
Supported
- formats: WAV, MP3, FLAC, OGG, M4A. For best results, provide 5–10 seconds of
- clear speech. Maximum file size: 5MB for Telnyx, 20MB for Minimax.
+ formats: WAV, MP3, FLAC, OGG, M4A. For best results, provide 5–60 seconds of
+ clear speech (Ultra accepts up to 60 seconds; Qwen3TTS auto-trims to 10 seconds;
+ Minimax accepts up to 5 minutes). Maximum file size: 5MB for Telnyx, 20MB for
+ Minimax.
Args:
voice_clone_upload_request: Multipart form data for creating a voice clone from a direct audio upload.
@@ -540,8 +542,10 @@ async def create_from_upload(
"""Creates a new voice clone by uploading an audio file directly.
Supported
- formats: WAV, MP3, FLAC, OGG, M4A. For best results, provide 5–10 seconds of
- clear speech. Maximum file size: 5MB for Telnyx, 20MB for Minimax.
+ formats: WAV, MP3, FLAC, OGG, M4A. For best results, provide 5–60 seconds of
+ clear speech (Ultra accepts up to 60 seconds; Qwen3TTS auto-trims to 10 seconds;
+ Minimax accepts up to 5 minutes). Maximum file size: 5MB for Telnyx, 20MB for
+ Minimax.
Args:
voice_clone_upload_request: Multipart form data for creating a voice clone from a direct audio upload.
diff --git a/src/telnyx/types/__init__.py b/src/telnyx/types/__init__.py
index 8b22e9ea8..3a40e6fdb 100644
--- a/src/telnyx/types/__init__.py
+++ b/src/telnyx/types/__init__.py
@@ -161,6 +161,7 @@
from .room_list_params import RoomListParams as RoomListParams
from .sip_header_param import SipHeaderParam as SipHeaderParam
from .stt_service_type import SttServiceType as SttServiceType
+from .success_response import SuccessResponse as SuccessResponse
from .user_requirement import UserRequirement as UserRequirement
from .voice_clone_data import VoiceCloneData as VoiceCloneData
from .webhook_delivery import WebhookDelivery as WebhookDelivery
@@ -354,6 +355,7 @@
from .address_delete_response import AddressDeleteResponse as AddressDeleteResponse
from .audit_event_list_params import AuditEventListParams as AuditEventListParams
from .authentication_provider import AuthenticationProvider as AuthenticationProvider
+from .bot_session_list_params import BotSessionListParams as BotSessionListParams
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
@@ -403,6 +405,7 @@
from .whatsapp_reaction_param import WhatsappReactionParam as WhatsappReactionParam
from .attachment_request_param import AttachmentRequestParam as AttachmentRequestParam
from .azure_configuration_data import AzureConfigurationData as AzureConfigurationData
+from .bot_signup_create_params import BotSignupCreateParams as BotSignupCreateParams
from .call_control_application import CallControlApplication as CallControlApplication
from .call_event_list_response import CallEventListResponse as CallEventListResponse
from .channel_zone_list_params import ChannelZoneListParams as ChannelZoneListParams
@@ -445,6 +448,7 @@
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 .bot_session_list_response import BotSessionListResponse as BotSessionListResponse
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
@@ -469,6 +473,7 @@
from .message_retrieve_response import MessageRetrieveResponse as MessageRetrieveResponse
from .message_schedule_response import MessageScheduleResponse as MessageScheduleResponse
from .message_whatsapp_response import MessageWhatsappResponse as MessageWhatsappResponse
+from .messaging_inbound_message import MessagingInboundMessage as MessagingInboundMessage
from .network_retrieve_response import NetworkRetrieveResponse as NetworkRetrieveResponse
from .number_order_phone_number import NumberOrderPhoneNumber as NumberOrderPhoneNumber
from .oauth_introspect_response import OAuthIntrospectResponse as OAuthIntrospectResponse
@@ -532,6 +537,7 @@
from .access_ip_range_list_params import AccessIPRangeListParams as AccessIPRangeListParams
from .billing_group_create_params import BillingGroupCreateParams as BillingGroupCreateParams
from .billing_group_update_params import BillingGroupUpdateParams as BillingGroupUpdateParams
+from .bot_challenge_create_params import BotChallengeCreateParams as BotChallengeCreateParams
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
@@ -629,6 +635,7 @@
from .billing_group_create_response import BillingGroupCreateResponse as BillingGroupCreateResponse
from .billing_group_delete_response import BillingGroupDeleteResponse as BillingGroupDeleteResponse
from .billing_group_update_response import BillingGroupUpdateResponse as BillingGroupUpdateResponse
+from .bot_challenge_create_response import BotChallengeCreateResponse as BotChallengeCreateResponse
from .bulk_sim_card_action_detailed import BulkSimCardActionDetailed as BulkSimCardActionDetailed
from .call_left_queue_webhook_event import CallLeftQueueWebhookEvent as CallLeftQueueWebhookEvent
from .call_reason_validate_response import CallReasonValidateResponse as CallReasonValidateResponse
@@ -873,13 +880,13 @@
from .call_recording_transcription_saved import CallRecordingTranscriptionSaved as CallRecordingTranscriptionSaved
from .call_refer_completed_webhook_event import CallReferCompletedWebhookEvent as CallReferCompletedWebhookEvent
from .conference_participant_speak_ended import ConferenceParticipantSpeakEnded as ConferenceParticipantSpeakEnded
+from .connection_retrieve_count_response import ConnectionRetrieveCountResponse as ConnectionRetrieveCountResponse
from .country_coverage_retrieve_response import CountryCoverageRetrieveResponse as CountryCoverageRetrieveResponse
from .email_block_retrieve_events_params import EmailBlockRetrieveEventsParams as EmailBlockRetrieveEventsParams
from .email_block_retrieve_export_params import EmailBlockRetrieveExportParams as EmailBlockRetrieveExportParams
from .global_ip_assignment_update_params import GlobalIPAssignmentUpdateParams as GlobalIPAssignmentUpdateParams
from .global_ip_health_check_list_params import GlobalIPHealthCheckListParams as GlobalIPHealthCheckListParams
from .integration_secret_create_response import IntegrationSecretCreateResponse as IntegrationSecretCreateResponse
-from .messaging_outbound_message_payload import MessagingOutboundMessagePayload as MessagingOutboundMessagePayload
from .messaging_url_domain_list_response import MessagingURLDomainListResponse as MessagingURLDomainListResponse
from .mobile_push_credential_list_params import MobilePushCredentialListParams as MobilePushCredentialListParams
from .notification_channel_create_params import NotificationChannelCreateParams as NotificationChannelCreateParams
@@ -906,6 +913,7 @@
from .wireless_blocklist_update_response import WirelessBlocklistUpdateResponse as WirelessBlocklistUpdateResponse
from .wireless_retrieve_regions_response import WirelessRetrieveRegionsResponse as WirelessRetrieveRegionsResponse
from .authentication_provider_list_params import AuthenticationProviderListParams as AuthenticationProviderListParams
+from .bot_signup_resend_magic_link_params import BotSignupResendMagicLinkParams as BotSignupResendMagicLinkParams
from .call_machine_premium_greeting_ended import CallMachinePremiumGreetingEnded as CallMachinePremiumGreetingEnded
from .call_payment_progress_webhook_event import CallPaymentProgressWebhookEvent as CallPaymentProgressWebhookEvent
from .call_playback_started_webhook_event import CallPlaybackStartedWebhookEvent as CallPlaybackStartedWebhookEvent
@@ -1041,6 +1049,9 @@
from .inexplicit_number_order_create_params import (
InexplicitNumberOrderCreateParams as InexplicitNumberOrderCreateParams,
)
+from .machine_payment_account_credit_params import (
+ MachinePaymentAccountCreditParams as MachinePaymentAccountCreditParams,
+)
from .messaging_hosted_number_update_params import (
MessagingHostedNumberUpdateParams as MessagingHostedNumberUpdateParams,
)
@@ -1136,6 +1147,9 @@
from .messaging_profile_metric_list_response import (
MessagingProfileMetricListResponse as MessagingProfileMetricListResponse,
)
+from .noise_suppression_engine_list_response import (
+ NoiseSuppressionEngineListResponse as NoiseSuppressionEngineListResponse,
+)
from .notification_channel_retrieve_response import (
NotificationChannelRetrieveResponse as NotificationChannelRetrieveResponse,
)
@@ -1220,6 +1234,9 @@
from .inexplicit_number_order_create_response import (
InexplicitNumberOrderCreateResponse as InexplicitNumberOrderCreateResponse,
)
+from .machine_payment_account_credit_response import (
+ MachinePaymentAccountCreditResponse as MachinePaymentAccountCreditResponse,
+)
from .messaging_hosted_number_delete_response import (
MessagingHostedNumberDeleteResponse as MessagingHostedNumberDeleteResponse,
)
diff --git a/src/telnyx/types/ai/__init__.py b/src/telnyx/types/ai/__init__.py
index bbd64274b..76a0e26eb 100644
--- a/src/telnyx/types/ai/__init__.py
+++ b/src/telnyx/types/ai/__init__.py
@@ -97,7 +97,6 @@
from .collection import Collection as Collection
from .mcp_server import McpServer as McpServer
from .speak_node import SpeakNode as SpeakNode
- from .hangup_tool import HangupTool as HangupTool
from .integration import Integration as Integration
from .conversation import Conversation as Conversation
from .external_llm import ExternalLlm as ExternalLlm
@@ -146,6 +145,7 @@
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 .audio_transcription_response_word import AudioTranscriptionResponseWord as AudioTranscriptionResponseWord
from .embedding_similarity_search_response import (
EmbeddingSimilaritySearchResponse as EmbeddingSimilaritySearchResponse,
)
@@ -204,10 +204,6 @@ def __getattr__(name: str) -> Any:
from .flow_node import FlowNode
return FlowNode
- if name == "HangupTool":
- from .hangup_tool import HangupTool
-
- return HangupTool
if name == "HangupToolParams":
from .hangup_tool_params import HangupToolParams
@@ -304,6 +300,10 @@ def __getattr__(name: str) -> Any:
from .assistant_send_sms_response import AssistantSendSMSResponse
return AssistantSendSMSResponse
+ if name == "AudioTranscriptionResponseWord":
+ from .audio_transcription_response_word import AudioTranscriptionResponseWord
+
+ return AudioTranscriptionResponseWord
if name == "AudioTranscribeResponse":
from .audio_transcribe_response import AudioTranscribeResponse
diff --git a/src/telnyx/types/ai/assistant_create_params.py b/src/telnyx/types/ai/assistant_create_params.py
index e579df2d1..16f2788bf 100644
--- a/src/telnyx/types/ai/assistant_create_params.py
+++ b/src/telnyx/types/ai/assistant_create_params.py
@@ -155,10 +155,10 @@ class AssistantCreateParams(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.
+ conversation ends, allowing it to execute final tool calls such as sending a
+ summary or updating a record via webhook or function tools. Integration and MCP
+ server tools are not available post-conversation; call-control tools (e.g.
+ hangup, transfer) are also unavailable. Beta feature.
"""
privacy_settings: PrivacySettingsParam
diff --git a/src/telnyx/types/ai/assistant_tool.py b/src/telnyx/types/ai/assistant_tool.py
index f3079b625..44e036d40 100644
--- a/src/telnyx/types/ai/assistant_tool.py
+++ b/src/telnyx/types/ai/assistant_tool.py
@@ -9,20 +9,23 @@
from ..._utils import PropertyInfo
from ..._models import BaseModel
-from .hangup_tool import HangupTool
from .retrieval_tool import RetrievalTool
from .pay_tool_params import PayToolParams
+from .hangup_tool_params import HangupToolParams
+from .openai.function_definition import FunctionDefinition
from .update_dynamic_variables_tool_params import UpdateDynamicVariablesToolParams
from .inference_embedding_webhook_tool_params import InferenceEmbeddingWebhookToolParams
__all__ = [
"AssistantTool",
+ "Function",
"ClientSideTool",
"ClientSideToolClientSideTool",
"ClientSideToolClientSideToolParameters",
"Handoff",
"HandoffHandoff",
"HandoffHandoffAIAssistant",
+ "Hangup",
"Transfer",
"TransferTransfer",
"TransferTransferTargetsTargetsList",
@@ -53,6 +56,23 @@
]
+class Function(BaseModel):
+ function: FunctionDefinition
+
+ type: Literal["function"]
+
+ shared: Optional[bool] = None
+ """Whether this tool comes from the shared Tools Library.
+
+ Responses merge shared tools into `tools` with `shared: true`; inline tools
+ carry `shared: false`. Read-only: set by the server, not accepted in requests.
+ When updating an assistant, omit `shared: true` tools from the request `tools`
+ array and manage them through `tool_ids` instead — re-sending their definitions
+ creates an inline duplicate (rejected with error code 10015 when the type allows
+ only one instance per assistant).
+ """
+
+
class ClientSideToolClientSideToolParameters(BaseModel):
"""The parameters the tool accepts, described as a JSON Schema object.
@@ -89,6 +109,17 @@ class ClientSideTool(BaseModel):
type: Literal["client_side_tool"]
+ shared: Optional[bool] = None
+ """Whether this tool comes from the shared Tools Library.
+
+ Responses merge shared tools into `tools` with `shared: true`; inline tools
+ carry `shared: false`. Read-only: set by the server, not accepted in requests.
+ When updating an assistant, omit `shared: true` tools from the request `tools`
+ array and manage them through `tool_ids` instead — re-sending their definitions
+ creates an inline duplicate (rejected with error code 10015 when the type allows
+ only one instance per assistant).
+ """
+
class HandoffHandoffAIAssistant(BaseModel):
id: str
@@ -120,6 +151,34 @@ class Handoff(BaseModel):
type: Literal["handoff"]
+ shared: Optional[bool] = None
+ """Whether this tool comes from the shared Tools Library.
+
+ Responses merge shared tools into `tools` with `shared: true`; inline tools
+ carry `shared: false`. Read-only: set by the server, not accepted in requests.
+ When updating an assistant, omit `shared: true` tools from the request `tools`
+ array and manage them through `tool_ids` instead — re-sending their definitions
+ creates an inline duplicate (rejected with error code 10015 when the type allows
+ only one instance per assistant).
+ """
+
+
+class Hangup(BaseModel):
+ hangup: HangupToolParams
+
+ type: Literal["hangup"]
+
+ shared: Optional[bool] = None
+ """Whether this tool comes from the shared Tools Library.
+
+ Responses merge shared tools into `tools` with `shared: true`; inline tools
+ carry `shared: false`. Read-only: set by the server, not accepted in requests.
+ When updating an assistant, omit `shared: true` tools from the request `tools`
+ array and manage them through `tool_ids` instead — re-sending their definitions
+ creates an inline duplicate (rejected with error code 10015 when the type allows
+ only one instance per assistant).
+ """
+
class TransferTransferTargetsTargetsList(BaseModel):
to: str
@@ -345,6 +404,17 @@ class Transfer(BaseModel):
type: Literal["transfer"]
+ shared: Optional[bool] = None
+ """Whether this tool comes from the shared Tools Library.
+
+ Responses merge shared tools into `tools` with `shared: true`; inline tools
+ carry `shared: false`. Read-only: set by the server, not accepted in requests.
+ When updating an assistant, omit `shared: true` tools from the request `tools`
+ array and manage them through `tool_ids` instead — re-sending their definitions
+ creates an inline duplicate (rejected with error code 10015 when the type allows
+ only one instance per assistant).
+ """
+
class InviteInviteCustomHeader(BaseModel):
name: Optional[str] = None
@@ -418,6 +488,17 @@ class Invite(BaseModel):
type: Literal["invite"]
+ shared: Optional[bool] = None
+ """Whether this tool comes from the shared Tools Library.
+
+ Responses merge shared tools into `tools` with `shared: true`; inline tools
+ carry `shared: false`. Read-only: set by the server, not accepted in requests.
+ When updating an assistant, omit `shared: true` tools from the request `tools`
+ array and manage them through `tool_ids` instead — re-sending their definitions
+ creates an inline duplicate (rejected with error code 10015 when the type allows
+ only one instance per assistant).
+ """
+
class ReferReferTarget(BaseModel):
name: str
@@ -479,12 +560,34 @@ class Refer(BaseModel):
type: Literal["refer"]
+ shared: Optional[bool] = None
+ """Whether this tool comes from the shared Tools Library.
+
+ Responses merge shared tools into `tools` with `shared: true`; inline tools
+ carry `shared: false`. Read-only: set by the server, not accepted in requests.
+ When updating an assistant, omit `shared: true` tools from the request `tools`
+ array and manage them through `tool_ids` instead — re-sending their definitions
+ creates an inline duplicate (rejected with error code 10015 when the type allows
+ only one instance per assistant).
+ """
+
class SendDtmf(BaseModel):
send_dtmf: Dict[str, object]
type: Literal["send_dtmf"]
+ shared: Optional[bool] = None
+ """Whether this tool comes from the shared Tools Library.
+
+ Responses merge shared tools into `tools` with `shared: true`; inline tools
+ carry `shared: false`. Read-only: set by the server, not accepted in requests.
+ When updating an assistant, omit `shared: true` tools from the request `tools`
+ array and manage them through `tool_ids` instead — re-sending their definitions
+ creates an inline duplicate (rejected with error code 10015 when the type allows
+ only one instance per assistant).
+ """
+
class SendMessageSendMessage(BaseModel):
message_template: Optional[str] = None
@@ -518,6 +621,17 @@ class SendMessage(BaseModel):
type: Literal["send_message"]
+ shared: Optional[bool] = None
+ """Whether this tool comes from the shared Tools Library.
+
+ Responses merge shared tools into `tools` with `shared: true`; inline tools
+ carry `shared: false`. Read-only: set by the server, not accepted in requests.
+ When updating an assistant, omit `shared: true` tools from the request `tools`
+ array and manage them through `tool_ids` instead — re-sending their definitions
+ creates an inline duplicate (rejected with error code 10015 when the type allows
+ only one instance per assistant).
+ """
+
class SkipTurnSkipTurn(BaseModel):
description: Optional[str] = None
@@ -529,6 +643,17 @@ class SkipTurn(BaseModel):
type: Literal["skip_turn"]
+ shared: Optional[bool] = None
+ """Whether this tool comes from the shared Tools Library.
+
+ Responses merge shared tools into `tools` with `shared: true`; inline tools
+ carry `shared: false`. Read-only: set by the server, not accepted in requests.
+ When updating an assistant, omit `shared: true` tools from the request `tools`
+ array and manage them through `tool_ids` instead — re-sending their definitions
+ creates an inline duplicate (rejected with error code 10015 when the type allows
+ only one instance per assistant).
+ """
+
class Pay(BaseModel):
"""
@@ -539,6 +664,17 @@ class Pay(BaseModel):
type: Literal["pay"]
+ shared: Optional[bool] = None
+ """Whether this tool comes from the shared Tools Library.
+
+ Responses merge shared tools into `tools` with `shared: true`; inline tools
+ carry `shared: false`. Read-only: set by the server, not accepted in requests.
+ When updating an assistant, omit `shared: true` tools from the request `tools`
+ array and manage them through `tool_ids` instead — re-sending their definitions
+ creates an inline duplicate (rejected with error code 10015 when the type allows
+ only one instance per assistant).
+ """
+
class UpdateDynamicVariables(BaseModel):
"""
@@ -550,14 +686,26 @@ class UpdateDynamicVariables(BaseModel):
update_dynamic_variables: UpdateDynamicVariablesToolParams
"""Configuration for an update_dynamic_variables tool."""
+ shared: Optional[bool] = None
+ """Whether this tool comes from the shared Tools Library.
+
+ Responses merge shared tools into `tools` with `shared: true`; inline tools
+ carry `shared: false`. Read-only: set by the server, not accepted in requests.
+ When updating an assistant, omit `shared: true` tools from the request `tools`
+ array and manage them through `tool_ids` instead — re-sending their definitions
+ creates an inline duplicate (rejected with error code 10015 when the type allows
+ only one instance per assistant).
+ """
+
AssistantTool: TypeAlias = Annotated[
Union[
+ Function,
InferenceEmbeddingWebhookToolParams,
ClientSideTool,
RetrievalTool,
Handoff,
- HangupTool,
+ Hangup,
Transfer,
Invite,
Refer,
diff --git a/src/telnyx/types/ai/assistant_tool_param.py b/src/telnyx/types/ai/assistant_tool_param.py
index 753c15155..c0a52352d 100644
--- a/src/telnyx/types/ai/assistant_tool_param.py
+++ b/src/telnyx/types/ai/assistant_tool_param.py
@@ -6,20 +6,23 @@
from typing_extensions import Literal, Required, TypeAlias, TypedDict
from ..._types import SequenceNotStr
-from .hangup_tool_param import HangupToolParam
from .retrieval_tool_param import RetrievalToolParam
from .pay_tool_params_param import PayToolParamsParam
+from .hangup_tool_params_param import HangupToolParamsParam
+from .openai.function_definition_param import FunctionDefinitionParam
from .update_dynamic_variables_tool_params_param import UpdateDynamicVariablesToolParamsParam
from .inference_embedding_webhook_tool_params_param import InferenceEmbeddingWebhookToolParamsParam
__all__ = [
"AssistantToolParam",
+ "Function",
"ClientSideTool",
"ClientSideToolClientSideTool",
"ClientSideToolClientSideToolParameters",
"Handoff",
"HandoffHandoff",
"HandoffHandoffAIAssistant",
+ "Hangup",
"Transfer",
"TransferTransfer",
"TransferTransferTargetsTargetsList",
@@ -50,6 +53,12 @@
]
+class Function(TypedDict, total=False):
+ function: Required[FunctionDefinitionParam]
+
+ type: Required[Literal["function"]]
+
+
class ClientSideToolClientSideToolParameters(TypedDict, total=False):
"""The parameters the tool accepts, described as a JSON Schema object.
@@ -118,6 +127,12 @@ class Handoff(TypedDict, total=False):
type: Required[Literal["handoff"]]
+class Hangup(TypedDict, total=False):
+ hangup: Required[HangupToolParamsParam]
+
+ type: Required[Literal["hangup"]]
+
+
class TransferTransferTargetsTargetsList(TypedDict, total=False):
to: Required[str]
"""The destination number or SIP URI of the call."""
@@ -549,11 +564,12 @@ class UpdateDynamicVariables(TypedDict, total=False):
AssistantToolParam: TypeAlias = Union[
+ Function,
InferenceEmbeddingWebhookToolParamsParam,
ClientSideTool,
RetrievalToolParam,
Handoff,
- HangupToolParam,
+ Hangup,
Transfer,
Invite,
Refer,
diff --git a/src/telnyx/types/ai/assistant_update_params.py b/src/telnyx/types/ai/assistant_update_params.py
index 0ea5158a4..962ac6a57 100644
--- a/src/telnyx/types/ai/assistant_update_params.py
+++ b/src/telnyx/types/ai/assistant_update_params.py
@@ -155,10 +155,10 @@ class AssistantUpdateParams(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.
+ conversation ends, allowing it to execute final tool calls such as sending a
+ summary or updating a record via webhook or function tools. Integration and MCP
+ server tools are not available post-conversation; call-control tools (e.g.
+ hangup, transfer) are also unavailable. Beta feature.
"""
privacy_settings: PrivacySettingsParam
@@ -180,14 +180,25 @@ class AssistantUpdateParams(TypedDict, total=False):
tool_ids: SequenceNotStr[str]
"""IDs of shared tools to attach to the assistant.
- New integrations should prefer `tool_ids` over inline `tools`.
+ New integrations should prefer `tool_ids` over inline `tools`. On update, a sent
+ `tool_ids` array fully replaces the assistant's attached shared tools; omit the
+ field to leave them unchanged. Single-instance tool types are counted across
+ inline `tools` and `tool_ids` combined, so attaching a shared tool of such a
+ type when an instance already exists returns HTTP 400 with error code 10015.
"""
tools: Iterable[AssistantToolParam]
"""Deprecated for new integrations.
Inline tool definitions available to the assistant. Prefer `tool_ids` to attach
- shared tools created with the AI Tools endpoints.
+ shared tools created with the AI Tools endpoints. On update, a sent `tools`
+ array fully replaces the assistant's inline tools; omit the field to leave the
+ inline tools unchanged. Each tool type except `function`, `webhook`, and
+ `client_side_tool` allows at most one instance per assistant, counted across
+ inline `tools` and shared `tool_ids` combined — sending a duplicate of such a
+ type returns HTTP 400 with error code 10015. Responses merge shared tools into
+ `tools` with `shared: true`; when updating, omit those tools from the `tools`
+ array and manage them through `tool_ids` instead.
"""
transcription: TranscriptionSettingsParam
diff --git a/src/telnyx/types/ai/assistants/version_update_params.py b/src/telnyx/types/ai/assistants/version_update_params.py
index 66a52f5b6..cf2f14132 100644
--- a/src/telnyx/types/ai/assistants/version_update_params.py
+++ b/src/telnyx/types/ai/assistants/version_update_params.py
@@ -157,10 +157,10 @@ class VersionUpdateParams(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.
+ conversation ends, allowing it to execute final tool calls such as sending a
+ summary or updating a record via webhook or function tools. Integration and MCP
+ server tools are not available post-conversation; call-control tools (e.g.
+ hangup, transfer) are also unavailable. Beta feature.
"""
privacy_settings: PrivacySettingsParam
@@ -176,14 +176,25 @@ class VersionUpdateParams(TypedDict, total=False):
tool_ids: SequenceNotStr[str]
"""IDs of shared tools to attach to the assistant.
- New integrations should prefer `tool_ids` over inline `tools`.
+ New integrations should prefer `tool_ids` over inline `tools`. On update, a sent
+ `tool_ids` array fully replaces the assistant's attached shared tools; omit the
+ field to leave them unchanged. Single-instance tool types are counted across
+ inline `tools` and `tool_ids` combined, so attaching a shared tool of such a
+ type when an instance already exists returns HTTP 400 with error code 10015.
"""
tools: Iterable[AssistantToolParam]
"""Deprecated for new integrations.
Inline tool definitions available to the assistant. Prefer `tool_ids` to attach
- shared tools created with the AI Tools endpoints.
+ shared tools created with the AI Tools endpoints. On update, a sent `tools`
+ array fully replaces the assistant's inline tools; omit the field to leave the
+ inline tools unchanged. Each tool type except `function`, `webhook`, and
+ `client_side_tool` allows at most one instance per assistant, counted across
+ inline `tools` and shared `tool_ids` combined — sending a duplicate of such a
+ type returns HTTP 400 with error code 10015. Responses merge shared tools into
+ `tools` with `shared: true`; when updating, omit those tools from the `tools`
+ array and manage them through `tool_ids` instead.
"""
transcription: TranscriptionSettingsParam
diff --git a/src/telnyx/types/ai/audio_transcribe_params.py b/src/telnyx/types/ai/audio_transcribe_params.py
index 15264e9b3..f21406ed5 100644
--- a/src/telnyx/types/ai/audio_transcribe_params.py
+++ b/src/telnyx/types/ai/audio_transcribe_params.py
@@ -12,43 +12,64 @@
class AudioTranscribeParams(TypedDict, total=False):
- model: Required[Literal["distil-whisper/distil-large-v2", "openai/whisper-large-v3-turbo", "deepgram/nova-3"]]
+ model: Required[
+ Literal[
+ "distil-whisper/distil-large-v2",
+ "openai/whisper-large-v3-turbo",
+ "deepgram/nova-2",
+ "deepgram/nova-2-medical",
+ "deepgram/nova-3",
+ "deepgram/nova-3-medical",
+ "nvidia/parakeet-v3",
+ "omi-health/omi-med-stt-v1",
+ ]
+ ]
"""ID of the model to use.
`distil-whisper/distil-large-v2` is lower latency but English-only.
`openai/whisper-large-v3-turbo` is multi-lingual but slightly higher latency.
- `deepgram/nova-3` supports English variants (en, en-US, en-GB, en-AU, en-NZ,
- en-IN) and only accepts mp3/wav files.
+ The `deepgram/*` models only accept mp3/wav files: `deepgram/nova-3` covers ~49
+ languages plus `multi` and `deepgram/nova-2` covers ~33, while the `-medical`
+ variants are tuned for clinical vocabulary and accept English only (`en` and its
+ regional variants, e.g. `en-US`, `en-GB`). `nvidia/parakeet-v3` is multilingual
+ with automatic language detection; `omi-health/omi-med-stt-v1` is a medical
+ model, English only.
"""
file: FileTypes
"""
The audio file object to transcribe, in one of these formats: flac, mp3, mp4,
mpeg, mpga, m4a, ogg, wav, or webm. File uploads are limited to 100 MB. Cannot
- be used together with `file_url`. Note: `deepgram/nova-3` only supports mp3 and
- wav formats.
+ be used together with `file_url`. Note: the `deepgram/*` models only support mp3
+ and wav formats.
"""
file_url: str
"""
Link to audio file in one of these formats: flac, mp3, mp4, mpeg, mpga, m4a,
ogg, wav, or webm. Support for hosted files is limited to 100MB. Cannot be used
- together with `file`. Note: `deepgram/nova-3` only supports mp3 and wav formats.
+ together with `file`. Note: the `deepgram/*` models only support mp3 and wav
+ formats.
"""
language: str
"""The language of the audio to be transcribed.
- For `deepgram/nova-3`, only English variants are supported: `en`, `en-US`,
- `en-GB`, `en-AU`, `en-NZ`, `en-IN`. For `openai/whisper-large-v3-turbo`,
- supports multiple languages. `distil-whisper/distil-large-v2` does not support
- language parameter.
+ `deepgram/nova-3` supports ~49 languages plus `multi`, and `deepgram/nova-2`
+ supports ~33 plus `multi`; the `-medical` variants are English only (`en` and
+ its regional variants, e.g. `en-US`, `en-GB`). Deepgram models validate on the
+ base language and forward the full tag, so regional variants such as `de-CH` and
+ `pt-BR` are accepted where the base language is supported; an unsupported
+ language returns a 400. For `openai/whisper-large-v3-turbo`, supports multiple
+ languages. `distil-whisper/distil-large-v2` does not support language parameter.
+ `nvidia/parakeet-v3` detects the language automatically;
+ `omi-health/omi-med-stt-v1` is English only.
"""
model_config: Dict[str, object]
"""Additional model-specific configuration parameters.
- Only allowed with `deepgram/nova-3` model. Can include Deepgram-specific options
+ Only allowed with the `deepgram/*` models. Can include Deepgram-specific options
such as `smart_format`, `punctuate`, `diarize`, `utterance`, `numerals`, and
`language`. If `language` is provided both as a top-level parameter and in
`model_config`, the top-level parameter takes precedence.
diff --git a/src/telnyx/types/ai/audio_transcribe_response.py b/src/telnyx/types/ai/audio_transcribe_response.py
index fcc5007ab..05ac29854 100644
--- a/src/telnyx/types/ai/audio_transcribe_response.py
+++ b/src/telnyx/types/ai/audio_transcribe_response.py
@@ -5,8 +5,9 @@
from typing import List, Optional
from ..._models import BaseModel
+from .audio_transcription_response_word import AudioTranscriptionResponseWord
-__all__ = ["AudioTranscribeResponse", "Segment", "Word"]
+__all__ = ["AudioTranscribeResponse", "Segment"]
class Segment(BaseModel):
@@ -22,33 +23,25 @@ class Segment(BaseModel):
text: str
"""Text content of the segment."""
+ speakers: Optional[List[int]] = None
+ """Speaker indices heard in this segment.
-class Word(BaseModel):
- """Word-level timing detail.
-
- Only present when using `deepgram/nova-3` with `model_config` options that enable word timestamps.
+ Returned by the `deepgram/*` models when `diarize` is enabled via
+ `model_config`.
"""
- end: float
- """End time of the word in seconds."""
-
- start: float
- """Start time of the word in seconds."""
+ words: Optional[List[AudioTranscriptionResponseWord]] = None
+ """Word-level timing detail for this segment.
- word: str
- """The transcribed word."""
-
- confidence: Optional[float] = None
- """Confidence score for the word (0.0 to 1.0)."""
-
- speaker: Optional[int] = None
- """Speaker index. Only present when diarization is enabled via `model_config`."""
+ Returned by the `deepgram/*` models when word-level output is enabled via
+ `model_config`.
+ """
class AudioTranscribeResponse(BaseModel):
"""Response fields vary by model.
- `distil-whisper/distil-large-v2` returns `text`, `duration`, and `segments` in `verbose_json` mode. `openai/whisper-large-v3-turbo` returns `text` only. `deepgram/nova-3` returns `text` and, depending on `model_config`, may include `words` with per-word timestamps and speaker labels.
+ `distil-whisper/distil-large-v2` returns `text`, `duration`, and `segments` in `verbose_json` mode. `openai/whisper-large-v3-turbo` returns `text` only. The `deepgram/*` models return `text` and, depending on `model_config`, may include `words` with per-word timestamps and speaker labels. The Parakeet models (`nvidia/parakeet-v3`, `omi-health/omi-med-stt-v1`) return `text` only.
"""
text: str
@@ -57,7 +50,7 @@ class AudioTranscribeResponse(BaseModel):
duration: Optional[float] = None
"""The duration of the audio file in seconds.
- Returned by `distil-whisper/distil-large-v2` and `deepgram/nova-3` when
+ Returned by `distil-whisper/distil-large-v2` and the `deepgram/*` models when
`response_format` is `verbose_json`. Not returned by
`openai/whisper-large-v3-turbo`.
"""
@@ -65,13 +58,14 @@ class AudioTranscribeResponse(BaseModel):
segments: Optional[List[Segment]] = None
"""Segments of the transcribed text and their corresponding details.
- Returned by `distil-whisper/distil-large-v2` when `response_format` is
- `verbose_json`. Not returned by `openai/whisper-large-v3-turbo`.
+ Returned by `distil-whisper/distil-large-v2` and the `deepgram/*` models when
+ `response_format` is `verbose_json`; Deepgram segments also carry nested `words`
+ and `speakers`. Not returned by `openai/whisper-large-v3-turbo`.
"""
- words: Optional[List[Word]] = None
+ words: Optional[List[AudioTranscriptionResponseWord]] = None
"""Word-level timestamps and optional speaker labels.
- Only returned by `deepgram/nova-3` when word-level output is enabled via
+ Only returned by the `deepgram/*` models when word-level output is enabled via
`model_config`.
"""
diff --git a/src/telnyx/types/ai/audio_transcription_response_word.py b/src/telnyx/types/ai/audio_transcription_response_word.py
new file mode 100644
index 000000000..5062e74fd
--- /dev/null
+++ b/src/telnyx/types/ai/audio_transcription_response_word.py
@@ -0,0 +1,43 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Optional
+
+from ..._models import BaseModel
+
+__all__ = ["AudioTranscriptionResponseWord"]
+
+
+class AudioTranscriptionResponseWord(BaseModel):
+ """Word-level timing detail.
+
+ Only present when using a `deepgram/*` model with `model_config` options that enable word timestamps.
+ """
+
+ end: float
+ """End time of the word in seconds."""
+
+ start: float
+ """Start time of the word in seconds."""
+
+ word: str
+ """The transcribed word."""
+
+ confidence: Optional[float] = None
+ """Confidence score for the word (0.0 to 1.0)."""
+
+ punctuated_word: Optional[str] = None
+ """The transcribed word with punctuation and capitalisation applied.
+
+ Only present when `punctuate` or `smart_format` is enabled via `model_config`.
+ """
+
+ speaker: Optional[int] = None
+ """Speaker index. Only present when diarization is enabled via `model_config`."""
+
+ speaker_confidence: Optional[float] = None
+ """Confidence score for the speaker assignment (0.0 to 1.0).
+
+ Only present when diarization is enabled via `model_config`.
+ """
diff --git a/src/telnyx/types/ai/hangup_tool.py b/src/telnyx/types/ai/hangup_tool.py
deleted file mode 100644
index 45be91d2e..000000000
--- a/src/telnyx/types/ai/hangup_tool.py
+++ /dev/null
@@ -1,16 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing_extensions import Literal
-
-from ..._models import BaseModel
-from .hangup_tool_params import HangupToolParams
-
-__all__ = ["HangupTool"]
-
-
-class HangupTool(BaseModel):
- hangup: HangupToolParams
-
- type: Literal["hangup"]
diff --git a/src/telnyx/types/ai/inference_embedding.py b/src/telnyx/types/ai/inference_embedding.py
index 373c03b9e..e03d12d0a 100644
--- a/src/telnyx/types/ai/inference_embedding.py
+++ b/src/telnyx/types/ai/inference_embedding.py
@@ -156,10 +156,10 @@ class InferenceEmbedding(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.
+ conversation ends, allowing it to execute final tool calls such as sending a
+ summary or updating a record via webhook or function tools. Integration and MCP
+ server tools are not available post-conversation; call-control tools (e.g.
+ hangup, transfer) are also unavailable. Beta feature.
"""
privacy_settings: Optional[PrivacySettings] = None
@@ -176,10 +176,14 @@ class InferenceEmbedding(BaseModel):
telephony_settings: Optional[TelephonySettings] = None
tools: Optional[List[AssistantTool]] = None
- """Deprecated for new integrations.
-
- Inline tool definitions available to the assistant. Prefer `tool_ids` to attach
- shared tools created with the AI Tools endpoints.
+ """The assistant's tools.
+
+ Responses merge the assistant's shared Tools Library tools into this array
+ alongside inline tools, each flagged `shared: true`; inline tools carry
+ `shared: false`. On update, a sent `tools` array fully replaces the inline tools
+ only — shared tools stay attached unless `tool_ids` changes. Each tool type
+ except `function`, `webhook`, and `client_side_tool` allows at most one instance
+ per assistant across both sources.
"""
transcription: Optional[TranscriptionSettings] = None
diff --git a/src/telnyx/types/ai/inference_embedding_interruption_settings.py b/src/telnyx/types/ai/inference_embedding_interruption_settings.py
index 501c7b3ee..b08c6d478 100644
--- a/src/telnyx/types/ai/inference_embedding_interruption_settings.py
+++ b/src/telnyx/types/ai/inference_embedding_interruption_settings.py
@@ -21,6 +21,12 @@ class InferenceEmbeddingInterruptionSettings(BaseModel):
enable: Optional[bool] = None
"""Whether users can interrupt the assistant while it is speaking."""
+ interrupt_prediction_threshold: Optional[float] = None
+ """Interrupt-prediction sensitivity, from 0.0 to 1.0.
+
+ Set to null or 0.0 to disable interrupt prediction.
+ """
+
start_speaking_plan: Optional[StartSpeakingPlan] = None
"""Controls when the assistant starts speaking after the user stops.
diff --git a/src/telnyx/types/ai/inference_embedding_interruption_settings_param.py b/src/telnyx/types/ai/inference_embedding_interruption_settings_param.py
index 25a9c7678..31917d7f4 100644
--- a/src/telnyx/types/ai/inference_embedding_interruption_settings_param.py
+++ b/src/telnyx/types/ai/inference_embedding_interruption_settings_param.py
@@ -2,6 +2,7 @@
from __future__ import annotations
+from typing import Optional
from typing_extensions import TypedDict
from .start_speaking_plan_param import StartSpeakingPlanParam
@@ -20,6 +21,12 @@ class InferenceEmbeddingInterruptionSettingsParam(TypedDict, total=False):
enable: bool
"""Whether users can interrupt the assistant while it is speaking."""
+ interrupt_prediction_threshold: Optional[float]
+ """Interrupt-prediction sensitivity, from 0.0 to 1.0.
+
+ Set to null or 0.0 to disable interrupt prediction.
+ """
+
start_speaking_plan: StartSpeakingPlanParam
"""Controls when the assistant starts speaking after the user stops.
diff --git a/src/telnyx/types/ai/inference_embedding_webhook_tool_params.py b/src/telnyx/types/ai/inference_embedding_webhook_tool_params.py
index 1b2058268..6a4f28a0c 100644
--- a/src/telnyx/types/ai/inference_embedding_webhook_tool_params.py
+++ b/src/telnyx/types/ai/inference_embedding_webhook_tool_params.py
@@ -234,3 +234,14 @@ class InferenceEmbeddingWebhookToolParams(BaseModel):
type: Literal["webhook"]
webhook: Webhook
+
+ shared: Optional[bool] = None
+ """Whether this tool comes from the shared Tools Library.
+
+ Responses merge shared tools into `tools` with `shared: true`; inline tools
+ carry `shared: false`. Read-only: set by the server, not accepted in requests.
+ When updating an assistant, omit `shared: true` tools from the request `tools`
+ array and manage them through `tool_ids` instead — re-sending their definitions
+ creates an inline duplicate (rejected with error code 10015 when the type allows
+ only one instance per assistant).
+ """
diff --git a/src/telnyx/types/ai/openai/__init__.py b/src/telnyx/types/ai/openai/__init__.py
index 80295a1de..56bec554a 100644
--- a/src/telnyx/types/ai/openai/__init__.py
+++ b/src/telnyx/types/ai/openai/__init__.py
@@ -4,11 +4,13 @@
from typing import TYPE_CHECKING, Any
+from .function_definition_param import FunctionDefinitionParam as FunctionDefinitionParam
from .chat_create_completion_params import ChatCreateCompletionParams as ChatCreateCompletionParams
from .chat_create_completion_response import ChatCreateCompletionResponse as ChatCreateCompletionResponse
from .embedding_create_embeddings_params import EmbeddingCreateEmbeddingsParams as EmbeddingCreateEmbeddingsParams
if TYPE_CHECKING:
+ from .function_definition import FunctionDefinition as FunctionDefinition
from .embedding_create_embeddings_response import (
EmbeddingCreateEmbeddingsResponse as EmbeddingCreateEmbeddingsResponse,
)
@@ -26,4 +28,8 @@ def __getattr__(name: str) -> Any:
from .embedding_list_embedding_models_response import EmbeddingListEmbeddingModelsResponse
return EmbeddingListEmbeddingModelsResponse
+ if name == "FunctionDefinition":
+ from .function_definition import FunctionDefinition
+
+ return FunctionDefinition
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
diff --git a/src/telnyx/types/ai/openai/chat_create_completion_params.py b/src/telnyx/types/ai/openai/chat_create_completion_params.py
index 4570e5a4d..8595202f5 100644
--- a/src/telnyx/types/ai/openai/chat_create_completion_params.py
+++ b/src/telnyx/types/ai/openai/chat_create_completion_params.py
@@ -7,6 +7,7 @@
from ...._types import SequenceNotStr
from ..bucket_ids_param import BucketIDsParam
+from .function_definition_param import FunctionDefinitionParam
__all__ = [
"ChatCreateCompletionParams",
@@ -19,7 +20,6 @@
"ResponseFormatResponseFormatJsonSchemaParamJsonSchema",
"Tool",
"ToolFunction",
- "ToolFunctionFunction",
"ToolRetrieval",
]
@@ -267,16 +267,8 @@ class ResponseFormatResponseFormatJsonSchemaParam(TypedDict, total=False):
]
-class ToolFunctionFunction(TypedDict, total=False):
- name: Required[str]
-
- description: str
-
- parameters: Dict[str, object]
-
-
class ToolFunction(TypedDict, total=False):
- function: Required[ToolFunctionFunction]
+ function: Required[FunctionDefinitionParam]
type: Required[Literal["function"]]
diff --git a/src/telnyx/types/ai/openai/function_definition.py b/src/telnyx/types/ai/openai/function_definition.py
new file mode 100644
index 000000000..9bf12a6b3
--- /dev/null
+++ b/src/telnyx/types/ai/openai/function_definition.py
@@ -0,0 +1,17 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Dict, Optional
+
+from ...._models import BaseModel
+
+__all__ = ["FunctionDefinition"]
+
+
+class FunctionDefinition(BaseModel):
+ name: str
+
+ description: Optional[str] = None
+
+ parameters: Optional[Dict[str, object]] = None
diff --git a/src/telnyx/types/ai/openai/function_definition_param.py b/src/telnyx/types/ai/openai/function_definition_param.py
new file mode 100644
index 000000000..24ed5fafe
--- /dev/null
+++ b/src/telnyx/types/ai/openai/function_definition_param.py
@@ -0,0 +1,16 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Dict
+from typing_extensions import Required, TypedDict
+
+__all__ = ["FunctionDefinitionParam"]
+
+
+class FunctionDefinitionParam(TypedDict, total=False):
+ name: Required[str]
+
+ description: str
+
+ parameters: Dict[str, object]
diff --git a/src/telnyx/types/ai/post_conversation_settings.py b/src/telnyx/types/ai/post_conversation_settings.py
index b94996352..efeb64840 100644
--- a/src/telnyx/types/ai/post_conversation_settings.py
+++ b/src/telnyx/types/ai/post_conversation_settings.py
@@ -12,7 +12,7 @@
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.
+ When enabled, the assistant receives one additional LLM turn after the conversation ends, allowing it to execute final tool calls such as sending a summary or updating a record via webhook or function tools. Integration and MCP server tools are not available post-conversation; call-control tools (e.g. hangup, transfer) are also unavailable. Beta feature.
"""
enabled: Optional[bool] = None
diff --git a/src/telnyx/types/ai/post_conversation_settings_req_param.py b/src/telnyx/types/ai/post_conversation_settings_req_param.py
index 1198ac715..db59ab67b 100644
--- a/src/telnyx/types/ai/post_conversation_settings_req_param.py
+++ b/src/telnyx/types/ai/post_conversation_settings_req_param.py
@@ -10,7 +10,7 @@
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.
+ When enabled, the assistant receives one additional LLM turn after the conversation ends, allowing it to execute final tool calls such as sending a summary or updating a record via webhook or function tools. Integration and MCP server tools are not available post-conversation; call-control tools (e.g. hangup, transfer) are also unavailable. Beta feature.
"""
enabled: bool
diff --git a/src/telnyx/types/ai/privacy_settings.py b/src/telnyx/types/ai/privacy_settings.py
index e950304f0..976d29356 100644
--- a/src/telnyx/types/ai/privacy_settings.py
+++ b/src/telnyx/types/ai/privacy_settings.py
@@ -19,3 +19,19 @@ class PrivacySettings(BaseModel):
you have set at the account, number, or application level. All such external
settings remain in force regardless of your selection here.
"""
+
+ in_transit_data_locality: Optional[bool] = None
+ """
+ Requires every model call made for a web chat turn to be received and served
+ inside your organization's data-locality region, rather than only stored there.
+ Applies to web chat only — voice and messaging assistants are unaffected.
+ Enabling it requires a data-locality region with in-region inference (USA, EU,
+ AUS, UAE; see
+ [Inference regions](https://developers.telnyx.com/docs/inference/models/regions))
+ and Telnyx-hosted models for the assistant, its fallback, and any
+ conversation-flow node that overrides the model; the request is rejected
+ otherwise. Once enabled, send chat requests to your region's API hostname: a
+ request entering the platform in another region is rejected rather than
+ forwarded, because forwarding it would already have moved the content across the
+ border. Defaults to false.
+ """
diff --git a/src/telnyx/types/ai/privacy_settings_param.py b/src/telnyx/types/ai/privacy_settings_param.py
index a9b492577..b22c41547 100644
--- a/src/telnyx/types/ai/privacy_settings_param.py
+++ b/src/telnyx/types/ai/privacy_settings_param.py
@@ -17,3 +17,19 @@ class PrivacySettingsParam(TypedDict, total=False):
you have set at the account, number, or application level. All such external
settings remain in force regardless of your selection here.
"""
+
+ in_transit_data_locality: bool
+ """
+ Requires every model call made for a web chat turn to be received and served
+ inside your organization's data-locality region, rather than only stored there.
+ Applies to web chat only — voice and messaging assistants are unaffected.
+ Enabling it requires a data-locality region with in-region inference (USA, EU,
+ AUS, UAE; see
+ [Inference regions](https://developers.telnyx.com/docs/inference/models/regions))
+ and Telnyx-hosted models for the assistant, its fallback, and any
+ conversation-flow node that overrides the model; the request is rejected
+ otherwise. Once enabled, send chat requests to your region's API hostname: a
+ request entering the platform in another region is rejected rather than
+ forwarded, because forwarding it would already have moved the content across the
+ border. Defaults to false.
+ """
diff --git a/src/telnyx/types/ai/retrieval_tool.py b/src/telnyx/types/ai/retrieval_tool.py
index f07729e26..f4e36911b 100644
--- a/src/telnyx/types/ai/retrieval_tool.py
+++ b/src/telnyx/types/ai/retrieval_tool.py
@@ -2,6 +2,7 @@
from __future__ import annotations
+from typing import Optional
from typing_extensions import Literal
from ..._models import BaseModel
@@ -14,3 +15,14 @@ class RetrievalTool(BaseModel):
retrieval: BucketIDs
type: Literal["retrieval"]
+
+ shared: Optional[bool] = None
+ """Whether this tool comes from the shared Tools Library.
+
+ Responses merge shared tools into `tools` with `shared: true`; inline tools
+ carry `shared: false`. Read-only: set by the server, not accepted in requests.
+ When updating an assistant, omit `shared: true` tools from the request `tools`
+ array and manage them through `tool_ids` instead — re-sending their definitions
+ creates an inline duplicate (rejected with error code 10015 when the type allows
+ only one instance per assistant).
+ """
diff --git a/src/telnyx/types/ai/telephony_settings.py b/src/telnyx/types/ai/telephony_settings.py
index 5e64f5302..98128bc92 100644
--- a/src/telnyx/types/ai/telephony_settings.py
+++ b/src/telnyx/types/ai/telephony_settings.py
@@ -20,14 +20,40 @@
class NoiseSuppressionConfig(BaseModel):
"""Configuration for noise suppression.
- Only applicable when noise_suppression is 'deepfilternet'.
+ Applicable fields depend on the engine: 'attenuation_limit' and 'mode' only when noise_suppression is 'deepfilternet'; 'family', 'size' and 'enhancement_level' only when noise_suppression is 'aicoustics'.
"""
attenuation_limit: Optional[int] = None
- """Attenuation limit for noise suppression. Range: 0-100."""
+ """Attenuation limit for noise suppression.
+
+ Range: 0-100. Only applicable when noise_suppression is 'deepfilternet'.
+ """
+
+ enhancement_level: Optional[float] = None
+ """AiCoustics enhancement intensity.
+
+ Range: 0-1. Only applicable when noise_suppression is 'aicoustics'.
+ """
+
+ family: Optional[Literal["quail"]] = None
+ """AiCoustics model family optimized for Voice AI and STT.
+
+ Only applicable when noise_suppression is 'aicoustics'.
+ """
mode: Optional[Literal["advanced"]] = None
- """Mode for noise suppression configuration."""
+ """Mode for noise suppression configuration.
+
+ Only applicable when noise_suppression is 'deepfilternet'.
+ """
+
+ size: Optional[Literal["vf", "vf_2_0_l"]] = None
+ """AiCoustics model size.
+
+ 'vf' tracks the latest model release; 'vf_2_0_l' is pinned to version 2.0 for
+ consistent, predictable behavior. Only applicable when noise_suppression is
+ 'aicoustics'.
+ """
class RecordingSettings(BaseModel):
@@ -127,16 +153,19 @@ class TelephonySettings(BaseModel):
bridged the call.
"""
- noise_suppression: Optional[Literal["krisp", "deepfilternet", "disabled"]] = None
+ noise_suppression: Optional[Literal["aicoustics", "krisp", "deepfilternet", "disabled"]] = None
"""The noise suppression engine to use.
- Use 'disabled' to turn off noise suppression.
+ 'aicoustics' is STT-optimized and recommended for AI assistants (configure
+ through noise_suppression_config). Use 'disabled' to turn off noise suppression.
"""
noise_suppression_config: Optional[NoiseSuppressionConfig] = None
"""Configuration for noise suppression.
- Only applicable when noise_suppression is 'deepfilternet'.
+ Applicable fields depend on the engine: 'attenuation_limit' and 'mode' only when
+ noise_suppression is 'deepfilternet'; 'family', 'size' and 'enhancement_level'
+ only when noise_suppression is 'aicoustics'.
"""
recording_settings: Optional[RecordingSettings] = None
diff --git a/src/telnyx/types/ai/telephony_settings_param.py b/src/telnyx/types/ai/telephony_settings_param.py
index 24348ded3..6c9091b87 100644
--- a/src/telnyx/types/ai/telephony_settings_param.py
+++ b/src/telnyx/types/ai/telephony_settings_param.py
@@ -17,14 +17,40 @@
class NoiseSuppressionConfig(TypedDict, total=False):
"""Configuration for noise suppression.
- Only applicable when noise_suppression is 'deepfilternet'.
+ Applicable fields depend on the engine: 'attenuation_limit' and 'mode' only when noise_suppression is 'deepfilternet'; 'family', 'size' and 'enhancement_level' only when noise_suppression is 'aicoustics'.
"""
attenuation_limit: int
- """Attenuation limit for noise suppression. Range: 0-100."""
+ """Attenuation limit for noise suppression.
+
+ Range: 0-100. Only applicable when noise_suppression is 'deepfilternet'.
+ """
+
+ enhancement_level: float
+ """AiCoustics enhancement intensity.
+
+ Range: 0-1. Only applicable when noise_suppression is 'aicoustics'.
+ """
+
+ family: Literal["quail"]
+ """AiCoustics model family optimized for Voice AI and STT.
+
+ Only applicable when noise_suppression is 'aicoustics'.
+ """
mode: Literal["advanced"]
- """Mode for noise suppression configuration."""
+ """Mode for noise suppression configuration.
+
+ Only applicable when noise_suppression is 'deepfilternet'.
+ """
+
+ size: Literal["vf", "vf_2_0_l"]
+ """AiCoustics model size.
+
+ 'vf' tracks the latest model release; 'vf_2_0_l' is pinned to version 2.0 for
+ consistent, predictable behavior. Only applicable when noise_suppression is
+ 'aicoustics'.
+ """
class RecordingSettings(TypedDict, total=False):
@@ -124,16 +150,19 @@ class TelephonySettingsParam(TypedDict, total=False):
bridged the call.
"""
- noise_suppression: Literal["krisp", "deepfilternet", "disabled"]
+ noise_suppression: Literal["aicoustics", "krisp", "deepfilternet", "disabled"]
"""The noise suppression engine to use.
- Use 'disabled' to turn off noise suppression.
+ 'aicoustics' is STT-optimized and recommended for AI assistants (configure
+ through noise_suppression_config). Use 'disabled' to turn off noise suppression.
"""
noise_suppression_config: NoiseSuppressionConfig
"""Configuration for noise suppression.
- Only applicable when noise_suppression is 'deepfilternet'.
+ Applicable fields depend on the engine: 'attenuation_limit' and 'mode' only when
+ noise_suppression is 'deepfilternet'; 'family', 'size' and 'enhancement_level'
+ only when noise_suppression is 'aicoustics'.
"""
recording_settings: RecordingSettings
diff --git a/src/telnyx/types/ai/transcription_settings.py b/src/telnyx/types/ai/transcription_settings.py
index 961e55888..62a458d9e 100644
--- a/src/telnyx/types/ai/transcription_settings.py
+++ b/src/telnyx/types/ai/transcription_settings.py
@@ -46,11 +46,13 @@ class TranscriptionSettings(BaseModel):
"deepgram/nova-3",
"deepgram/nova-2",
"azure/fast",
+ "assemblyai/universal-3-5-pro",
"assemblyai/universal-streaming",
"xai/grok-stt",
"soniox/stt-rt-v4",
"soniox/stt-rt-v5",
"nvidia/parakeet-v3",
+ "omi-health/omi-med-stt-v1",
"humain/realtime",
"reson8/turns",
"cohere/ar-stt",
@@ -66,14 +68,17 @@ class TranscriptionSettings(BaseModel):
- `deepgram/nova-3` is multilingual with automatic language detection.
- `deepgram/nova-2` is Deepgram's previous-generation multilingual model.
- `azure/fast` is a multilingual Azure transcription model.
- - `assemblyai/universal-streaming` is a multilingual streaming model with
- configurable turn detection.
+ - `assemblyai/universal-3-5-pro` is a multilingual streaming model with
+ configurable turn detection. The legacy alias `assemblyai/universal-streaming`
+ is still accepted and resolves to the same model.
- `xai/grok-stt` is a multilingual Grok STT model.
- `soniox/stt-rt-v4` and `soniox/stt-rt-v5` are multilingual streaming models
with automatic language detection, configurable endpointing, term biasing
(`context`), and `language_hints`.
- `nvidia/parakeet-v3` is a multilingual transcription model with automatic
language detection.
+ - `omi-health/omi-med-stt-v1` is an English-only medical transcription model
+ (Parakeet-based).
- `humain/realtime` is a streaming model with native Arabic and Arabic/English
code-switching support.
- `reson8/turns` is a turn-based streaming model covering 10 European languages
diff --git a/src/telnyx/types/ai/transcription_settings_config.py b/src/telnyx/types/ai/transcription_settings_config.py
index e404ef4fc..e613da93b 100644
--- a/src/telnyx/types/ai/transcription_settings_config.py
+++ b/src/telnyx/types/ai/transcription_settings_config.py
@@ -37,10 +37,10 @@ class TranscriptionSettingsConfig(BaseModel):
"""
end_of_turn_confidence_threshold: Optional[float] = None
- """Available only for assemblyai/universal-streaming.
-
- Confidence level required to trigger an end of turn. Higher values require more
- certainty before ending a turn.
+ """
+ Available only for assemblyai/universal-3-5-pro (and its legacy alias
+ assemblyai/universal-streaming). Confidence level required to trigger an end of
+ turn. Higher values require more certainty before ending a turn.
"""
eot_threshold: Optional[float] = None
@@ -90,16 +90,17 @@ class TranscriptionSettingsConfig(BaseModel):
"""
max_turn_silence: Optional[int] = None
- """Available only for assemblyai/universal-streaming.
-
- Maximum duration of silence in milliseconds before forcing an end of turn.
+ """
+ Available only for assemblyai/universal-3-5-pro (and its legacy alias
+ assemblyai/universal-streaming). Maximum duration of silence in milliseconds
+ before forcing an end of turn.
"""
min_turn_silence: Optional[int] = None
- """Available only for assemblyai/universal-streaming.
-
- Minimum duration of silence in milliseconds before a turn can end. Must be less
- than or equal to max_turn_silence.
+ """
+ Available only for assemblyai/universal-3-5-pro (and its legacy alias
+ assemblyai/universal-streaming). Minimum duration of silence in milliseconds
+ before a turn can end. Must be less than or equal to max_turn_silence.
"""
numerals: Optional[bool] = None
diff --git a/src/telnyx/types/ai/transcription_settings_config_param.py b/src/telnyx/types/ai/transcription_settings_config_param.py
index b6300fed0..6ebe64270 100644
--- a/src/telnyx/types/ai/transcription_settings_config_param.py
+++ b/src/telnyx/types/ai/transcription_settings_config_param.py
@@ -37,10 +37,10 @@ class TranscriptionSettingsConfigParam(TypedDict, total=False):
"""
end_of_turn_confidence_threshold: float
- """Available only for assemblyai/universal-streaming.
-
- Confidence level required to trigger an end of turn. Higher values require more
- certainty before ending a turn.
+ """
+ Available only for assemblyai/universal-3-5-pro (and its legacy alias
+ assemblyai/universal-streaming). Confidence level required to trigger an end of
+ turn. Higher values require more certainty before ending a turn.
"""
eot_threshold: float
@@ -90,16 +90,17 @@ class TranscriptionSettingsConfigParam(TypedDict, total=False):
"""
max_turn_silence: int
- """Available only for assemblyai/universal-streaming.
-
- Maximum duration of silence in milliseconds before forcing an end of turn.
+ """
+ Available only for assemblyai/universal-3-5-pro (and its legacy alias
+ assemblyai/universal-streaming). Maximum duration of silence in milliseconds
+ before forcing an end of turn.
"""
min_turn_silence: int
- """Available only for assemblyai/universal-streaming.
-
- Minimum duration of silence in milliseconds before a turn can end. Must be less
- than or equal to max_turn_silence.
+ """
+ Available only for assemblyai/universal-3-5-pro (and its legacy alias
+ assemblyai/universal-streaming). Minimum duration of silence in milliseconds
+ before a turn can end. Must be less than or equal to max_turn_silence.
"""
numerals: bool
diff --git a/src/telnyx/types/ai/transcription_settings_param.py b/src/telnyx/types/ai/transcription_settings_param.py
index 59b9b92e6..6635850e4 100644
--- a/src/telnyx/types/ai/transcription_settings_param.py
+++ b/src/telnyx/types/ai/transcription_settings_param.py
@@ -43,11 +43,13 @@ class TranscriptionSettingsParam(TypedDict, total=False):
"deepgram/nova-3",
"deepgram/nova-2",
"azure/fast",
+ "assemblyai/universal-3-5-pro",
"assemblyai/universal-streaming",
"xai/grok-stt",
"soniox/stt-rt-v4",
"soniox/stt-rt-v5",
"nvidia/parakeet-v3",
+ "omi-health/omi-med-stt-v1",
"humain/realtime",
"reson8/turns",
"cohere/ar-stt",
@@ -62,14 +64,17 @@ class TranscriptionSettingsParam(TypedDict, total=False):
- `deepgram/nova-3` is multilingual with automatic language detection.
- `deepgram/nova-2` is Deepgram's previous-generation multilingual model.
- `azure/fast` is a multilingual Azure transcription model.
- - `assemblyai/universal-streaming` is a multilingual streaming model with
- configurable turn detection.
+ - `assemblyai/universal-3-5-pro` is a multilingual streaming model with
+ configurable turn detection. The legacy alias `assemblyai/universal-streaming`
+ is still accepted and resolves to the same model.
- `xai/grok-stt` is a multilingual Grok STT model.
- `soniox/stt-rt-v4` and `soniox/stt-rt-v5` are multilingual streaming models
with automatic language detection, configurable endpointing, term biasing
(`context`), and `language_hints`.
- `nvidia/parakeet-v3` is a multilingual transcription model with automatic
language detection.
+ - `omi-health/omi-med-stt-v1` is an English-only medical transcription model
+ (Parakeet-based).
- `humain/realtime` is a streaming model with native Arabic and Arabic/English
code-switching support.
- `reson8/turns` is a turn-based streaming model covering 10 European languages
diff --git a/src/telnyx/types/ai/typesafe/__init__.py b/src/telnyx/types/ai/typesafe/__init__.py
new file mode 100644
index 000000000..490bc05e9
--- /dev/null
+++ b/src/telnyx/types/ai/typesafe/__init__.py
@@ -0,0 +1,18 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import TYPE_CHECKING, Any
+
+from .v1_systemone_params import V1SystemoneParams as V1SystemoneParams
+
+if TYPE_CHECKING:
+ from .v1_systemone_response import V1SystemoneResponse as V1SystemoneResponse
+
+
+def __getattr__(name: str) -> Any:
+ if name == "V1SystemoneResponse":
+ from .v1_systemone_response import V1SystemoneResponse
+
+ return V1SystemoneResponse
+ raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
diff --git a/src/telnyx/types/ai/typesafe/v1_systemone_params.py b/src/telnyx/types/ai/typesafe/v1_systemone_params.py
new file mode 100644
index 000000000..4c54d1636
--- /dev/null
+++ b/src/telnyx/types/ai/typesafe/v1_systemone_params.py
@@ -0,0 +1,91 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Dict, Union, Iterable, Optional
+from typing_extensions import Literal, Required, TypeAlias, TypedDict
+
+from ...._types import SequenceNotStr
+
+__all__ = [
+ "V1SystemoneParams",
+ "Questions",
+ "QuestionsDecisionModelChoiceQuestion",
+ "QuestionsDecisionModelNoulQuestion",
+ "QuestionsDecisionModelNoulQuestionCriteria",
+ "QuestionsDecisionModelScoreQuestion",
+]
+
+
+class V1SystemoneParams(TypedDict, total=False):
+ questions: Required[Dict[str, Questions]]
+ """Between 1 and 64 named questions. Each key identifies the corresponding answer."""
+
+ state: Required[Union[str, Dict[str, object], Iterable[object]]]
+ """Shared context evaluated by every question."""
+
+
+class QuestionsDecisionModelChoiceQuestion(TypedDict, total=False):
+ """Select one of the supplied options."""
+
+ criteria: Required[Dict[str, Optional[str]]]
+ """Between 2 and 64 option keys mapped to description strings or null.
+
+ A null description uses the option key as its text.
+ """
+
+ instructions: Required[Union[str, Dict[str, object], Iterable[object]]]
+ """Required instructions describing what to decide about the shared state."""
+
+ type: Required[Literal["choice"]]
+ """Question type."""
+
+
+class QuestionsDecisionModelNoulQuestionCriteria(TypedDict, total=False):
+ """Optional descriptions for the positive and negative outcomes.
+
+ Descriptions must be strings.
+ """
+
+ false: str
+ """Description of the negative outcome."""
+
+ true: str
+ """Description of the positive outcome."""
+
+
+class QuestionsDecisionModelNoulQuestion(TypedDict, total=False):
+ """Evaluate a yes/no question. Omit criteria to use Yes and No descriptions."""
+
+ instructions: Required[Union[str, Dict[str, object], Iterable[object]]]
+ """Required instructions describing what to decide about the shared state."""
+
+ type: Required[Literal["noul"]]
+ """Question type."""
+
+ criteria: QuestionsDecisionModelNoulQuestionCriteria
+ """Optional descriptions for the positive and negative outcomes.
+
+ Descriptions must be strings.
+ """
+
+
+class QuestionsDecisionModelScoreQuestion(TypedDict, total=False):
+ """Rate the state against an ordered rubric."""
+
+ criteria: Required[SequenceNotStr[str]]
+ """Between 2 and 64 description strings in ascending score order.
+
+ Indices start at zero.
+ """
+
+ instructions: Required[Union[str, Dict[str, object], Iterable[object]]]
+ """Required instructions describing what to decide about the shared state."""
+
+ type: Required[Literal["score"]]
+ """Question type."""
+
+
+Questions: TypeAlias = Union[
+ QuestionsDecisionModelChoiceQuestion, QuestionsDecisionModelNoulQuestion, QuestionsDecisionModelScoreQuestion
+]
diff --git a/src/telnyx/types/ai/typesafe/v1_systemone_response.py b/src/telnyx/types/ai/typesafe/v1_systemone_response.py
new file mode 100644
index 000000000..3af00de36
--- /dev/null
+++ b/src/telnyx/types/ai/typesafe/v1_systemone_response.py
@@ -0,0 +1,131 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Dict, Union
+from typing_extensions import Literal, Annotated, TypeAlias
+
+from ...._utils import PropertyInfo
+from ...._models import BaseModel
+
+__all__ = [
+ "V1SystemoneResponse",
+ "Answers",
+ "AnswersDecisionModelChoiceAnswer",
+ "AnswersDecisionModelNoulAnswer",
+ "AnswersDecisionModelScoreAnswer",
+ "Usage",
+]
+
+
+class AnswersDecisionModelChoiceAnswer(BaseModel):
+ """A selected option and the distribution across all supplied option keys."""
+
+ choice: str
+ """The option key with the highest relative score.
+
+ Ties favor the first option in request order.
+ """
+
+ confidence: float
+ """
+ Normalized entropy confidence: 1 - H(p) / ln(N), where H(p) = -sum(p \\** ln(p))
+ and N is the number of options. Zero indicates a uniform distribution; one
+ indicates concentration on one option. This is neither the winning probability
+ nor calibrated correctness.
+ """
+
+ probabilities: Dict[str, float]
+ """
+ Relative scores normalized across the supplied options, summing approximately
+ to 1. These are not calibrated probabilities of correctness.
+ """
+
+ type: Literal["choice"]
+ """Answer type."""
+
+
+class AnswersDecisionModelNoulAnswer(BaseModel):
+ """A yes/no score with no separate confidence or probabilities fields."""
+
+ noul: float
+ """Score of the positive outcome.
+
+ Values near 1 favor yes; values near 0 favor no. This is a number, not a
+ Boolean, and is not calibrated correctness.
+ """
+
+ type: Literal["noul"]
+ """Answer type."""
+
+
+class AnswersDecisionModelScoreAnswer(BaseModel):
+ """An expected rating over the ordered criteria."""
+
+ confidence: float
+ """
+ Normalized entropy confidence: 1 - H(p) / ln(N), where H(p) = -sum(p \\** ln(p))
+ and N is the number of options. Zero indicates a uniform distribution; one
+ indicates concentration on one option. This is neither the winning probability
+ nor calibrated correctness.
+ """
+
+ legend: Dict[str, str]
+ """
+ Criterion descriptions keyed by stringified zero-based indices, such as "0",
+ "1", and "2".
+ """
+
+ probabilities: Dict[str, float]
+ """Relative scores keyed by the same stringified indices as legend."""
+
+ score: float
+ """Expected zero-based criterion index: sum(index \\** probability).
+
+ Ranges from 0 to N-1 for N criteria; fractional values are valid.
+ """
+
+ type: Literal["score"]
+ """Answer type."""
+
+
+Answers: TypeAlias = Annotated[
+ Union[AnswersDecisionModelChoiceAnswer, AnswersDecisionModelNoulAnswer, AnswersDecisionModelScoreAnswer],
+ PropertyInfo(discriminator="type"),
+]
+
+
+class Usage(BaseModel):
+ """Token usage for the completed evaluation."""
+
+ input_tokens: int
+ """
+ Input tokens processed, including shared-context preparation and question
+ evaluation. This can exceed the token count of the unique input text.
+ """
+
+ output_tokens: int
+ """Output tokens used for the evaluation, including shared-context preparation."""
+
+
+class V1SystemoneResponse(BaseModel):
+ """A complete synchronous evaluation.
+
+ Answers are returned directly without a data wrapper.
+ """
+
+ answers: Dict[str, Answers]
+ """Answers keyed by exactly the question IDs in the request.
+
+ Each answer type matches its question.
+ """
+
+ model: str
+ """
+ Opaque Telnyx-controlled identifier retained for TypeSafe SDK response
+ compatibility. It is not a selectable model name or a guarantee of a particular
+ underlying model.
+ """
+
+ usage: Usage
+ """Token usage for the completed evaluation."""
diff --git a/src/telnyx/types/bot_challenge_create_params.py b/src/telnyx/types/bot_challenge_create_params.py
new file mode 100644
index 000000000..da769d5aa
--- /dev/null
+++ b/src/telnyx/types/bot_challenge_create_params.py
@@ -0,0 +1,18 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import TypedDict
+
+__all__ = ["BotChallengeCreateParams"]
+
+
+class BotChallengeCreateParams(TypedDict, total=False):
+ llm_model_name: str
+ """Name of the LLM the client is using."""
+
+ llm_parameter_count: str
+ """Parameter count of the client LLM."""
+
+ llm_quantization: str
+ """Quantization of the client LLM."""
diff --git a/src/telnyx/types/bot_challenge_create_response.py b/src/telnyx/types/bot_challenge_create_response.py
new file mode 100644
index 000000000..463bf4572
--- /dev/null
+++ b/src/telnyx/types/bot_challenge_create_response.py
@@ -0,0 +1,41 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Optional
+from typing_extensions import Literal
+
+from .._models import BaseModel
+
+__all__ = ["BotChallengeCreateResponse", "Data"]
+
+
+class Data(BaseModel):
+ challenge_type: Literal["math", "string", "binary"]
+ """Type of challenge."""
+
+ nonce: str
+ """Single-use challenge identifier.
+
+ Submit it as `bot_challenge_nonce` on the signup request.
+ """
+
+ privacy_policy_url: str
+ """Current privacy-policy URL. Echo this back on the signup request."""
+
+ problem: str
+ """Problem text to solve.
+
+ Math problems are obfuscated and end with an unobfuscated rounding instruction;
+ string and binary problems are returned as-is.
+ """
+
+ terms_and_conditions_url: str
+ """Current terms-and-conditions URL. Echo this back on the signup request."""
+
+ precision: Optional[int] = None
+ """Decimal places expected in the answer. Present only for math challenges."""
+
+
+class BotChallengeCreateResponse(BaseModel):
+ data: Data
diff --git a/src/telnyx/types/bot_session_list_params.py b/src/telnyx/types/bot_session_list_params.py
new file mode 100644
index 000000000..2c97820a4
--- /dev/null
+++ b/src/telnyx/types/bot_session_list_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
+
+__all__ = ["BotSessionListParams"]
+
+
+class BotSessionListParams(TypedDict, total=False):
+ email: Required[str]
+ """Email address associated with the magic link token."""
+
+ portal_redirect_token: Required[str]
+ """
+ Single-use portal redirect (magic link) token, a UUIDv7 sent to the account
+ owner's email.
+ """
diff --git a/src/telnyx/types/bot_session_list_response.py b/src/telnyx/types/bot_session_list_response.py
new file mode 100644
index 000000000..185b5e607
--- /dev/null
+++ b/src/telnyx/types/bot_session_list_response.py
@@ -0,0 +1,19 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from .._models import BaseModel
+
+__all__ = ["BotSessionListResponse", "Data"]
+
+
+class Data(BaseModel):
+ api_v2_token: str
+ """API v2 session token for the signed-in user.
+
+ Use it as a bearer token on authenticated endpoints.
+ """
+
+
+class BotSessionListResponse(BaseModel):
+ data: Data
diff --git a/src/telnyx/types/bot_signup_create_params.py b/src/telnyx/types/bot_signup_create_params.py
new file mode 100644
index 000000000..0a93f7e71
--- /dev/null
+++ b/src/telnyx/types/bot_signup_create_params.py
@@ -0,0 +1,43 @@
+# 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__ = ["BotSignupCreateParams"]
+
+
+class BotSignupCreateParams(TypedDict, total=False):
+ bot_challenge_answer: Required[str]
+ """Answer to the issued bot challenge."""
+
+ bot_challenge_nonce: Required[str]
+ """Nonce from a previously issued bot challenge."""
+
+ privacy_policy_url: Required[str]
+ """Must exactly match the privacy-policy URL returned by the challenge endpoint."""
+
+ terms_and_conditions_url: Required[str]
+ """
+ Must exactly match the terms-and-conditions URL returned by the challenge
+ endpoint.
+ """
+
+ terms_of_service: Required[Literal[True]]
+ """Must be true to accept the terms of service."""
+
+ email: str
+ """Email address for the new account.
+
+ The magic link is sent here. May only be omitted when placeholder-email
+ registration is enabled server-side.
+ """
+
+ terms_and_conditions_eu_url: str
+ """EU terms-and-conditions URL. Required when EU consent enforcement is enabled."""
+
+ terms_of_service_eu: Literal[True]
+ """EU terms-of-service acceptance.
+
+ Required when EU consent enforcement is enabled.
+ """
diff --git a/src/telnyx/types/bot_signup_resend_magic_link_params.py b/src/telnyx/types/bot_signup_resend_magic_link_params.py
new file mode 100644
index 000000000..a549170c3
--- /dev/null
+++ b/src/telnyx/types/bot_signup_resend_magic_link_params.py
@@ -0,0 +1,12 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Required, TypedDict
+
+__all__ = ["BotSignupResendMagicLinkParams"]
+
+
+class BotSignupResendMagicLinkParams(TypedDict, total=False):
+ email: Required[str]
+ """Email address of the bot signup account to resend the magic link to."""
diff --git a/src/telnyx/types/call_dial_params.py b/src/telnyx/types/call_dial_params.py
index 00e5bafb4..713fe8ea6 100644
--- a/src/telnyx/types/call_dial_params.py
+++ b/src/telnyx/types/call_dial_params.py
@@ -159,12 +159,13 @@ class CallDialParams(TypedDict, total=False):
dialogflow_config: DialogflowConfigParam
diversion: str
- """
- The number the inbound call being transferred was originally received on, in
- +E164 format. Supplying it lets an unverified non-Telnyx `from` be used as the
- caller id, provided that number is still on an active inbound call to this
- `diversion` number for your account. The `diversion` number itself must be one
- you own or have verified.
+ """The `to` number of an active inbound call, in +E164 format.
+
+ Telnyx checks whether there is currently an active inbound call where `to`
+ matches this `diversion` value and `from` matches the `from` number supplied for
+ this request. If such a call exists, the `from` number is treated as verified
+ (since it is already on an active inbound call to you) and can be used as the
+ caller id for this outbound call.
"""
enable_dialogflow: bool
@@ -456,6 +457,52 @@ class AnsweringMachineDetectionConfig(TypedDict, total=False):
default profile.
"""
+ beep_max_frequency_hz: int
+ """Highest frequency, in Hz, that a tone can reach and still be treated as a beep.
+
+ Only used when beep detection is active.
+ """
+
+ beep_min_frequency_hz: int
+ """Lowest frequency, in Hz, that a tone must reach to be treated as a beep.
+
+ Raising it above 480 excludes North American ringback (440 + 480 Hz), which can
+ otherwise be reported as a beep when the `freq_only` profile is in use. Only
+ used when beep detection is active.
+ """
+
+ beep_min_tone_duration_millis: int
+ """Shortest tone, in milliseconds, that can be treated as a beep.
+
+ Raising it rejects brief tones such as call-progress blips. Only used when beep
+ detection is active.
+ """
+
+ beep_spectral_confirmation: bool
+ """
+ When enabled, a candidate beep must pass an additional spectral check before it
+ is reported. Only used when beep detection is active.
+ """
+
+ beep_spectral_min_purity: float
+ """Minimum spectral purity, from 0 to 1, for a tone to be treated as a beep.
+
+ Raising it rejects mixed tones such as ringback, which combines two frequencies.
+ Only used when beep detection is active.
+ """
+
+ beep_spectral_reject_fax_cng: bool
+ """When enabled, the fax CNG tone is rejected rather than reported as a beep.
+
+ Only used when beep detection is active.
+ """
+
+ beep_spectral_window_millis: int
+ """Length of the spectral confirmation window, in milliseconds.
+
+ Only used when beep detection is active.
+ """
+
between_words_silence_millis: int
"""Maximum threshold for silence between words."""
diff --git a/src/telnyx/types/calls/action_transfer_params.py b/src/telnyx/types/calls/action_transfer_params.py
index 68e8f2495..33634f182 100644
--- a/src/telnyx/types/calls/action_transfer_params.py
+++ b/src/telnyx/types/calls/action_transfer_params.py
@@ -72,12 +72,13 @@ class ActionTransferParams(TypedDict, total=False):
"""Custom headers to be added to the SIP INVITE."""
diversion: str
- """
- The number the inbound call being transferred was originally received on, in
- +E164 format. Supplying it lets an unverified non-Telnyx `from` be used as the
- caller id, provided that number is still on an active inbound call to this
- `diversion` number for your account. The `diversion` number itself must be one
- you own or have verified.
+ """The `to` number of an active inbound call, in +E164 format.
+
+ Telnyx checks whether there is currently an active inbound call where `to`
+ matches this `diversion` value and `from` matches the `from` number supplied for
+ this request. If such a call exists, the `from` number is treated as verified
+ (since it is already on an active inbound call to you) and can be used as the
+ caller id for this outbound call.
"""
early_media: bool
@@ -310,6 +311,52 @@ class AnsweringMachineDetectionConfig(TypedDict, total=False):
default profile.
"""
+ beep_max_frequency_hz: int
+ """Highest frequency, in Hz, that a tone can reach and still be treated as a beep.
+
+ Only used when beep detection is active.
+ """
+
+ beep_min_frequency_hz: int
+ """Lowest frequency, in Hz, that a tone must reach to be treated as a beep.
+
+ Raising it above 480 excludes North American ringback (440 + 480 Hz), which can
+ otherwise be reported as a beep when the `freq_only` profile is in use. Only
+ used when beep detection is active.
+ """
+
+ beep_min_tone_duration_millis: int
+ """Shortest tone, in milliseconds, that can be treated as a beep.
+
+ Raising it rejects brief tones such as call-progress blips. Only used when beep
+ detection is active.
+ """
+
+ beep_spectral_confirmation: bool
+ """
+ When enabled, a candidate beep must pass an additional spectral check before it
+ is reported. Only used when beep detection is active.
+ """
+
+ beep_spectral_min_purity: float
+ """Minimum spectral purity, from 0 to 1, for a tone to be treated as a beep.
+
+ Raising it rejects mixed tones such as ringback, which combines two frequencies.
+ Only used when beep detection is active.
+ """
+
+ beep_spectral_reject_fax_cng: bool
+ """When enabled, the fax CNG tone is rejected rather than reported as a beep.
+
+ Only used when beep detection is active.
+ """
+
+ beep_spectral_window_millis: int
+ """Length of the spectral confirmation window, in milliseconds.
+
+ Only used when beep detection is active.
+ """
+
between_words_silence_millis: int
"""Maximum threshold for silence between words."""
diff --git a/src/telnyx/types/calls/transcription_config_param.py b/src/telnyx/types/calls/transcription_config_param.py
index 23276c809..bc30d2f30 100644
--- a/src/telnyx/types/calls/transcription_config_param.py
+++ b/src/telnyx/types/calls/transcription_config_param.py
@@ -23,18 +23,19 @@ class TranscriptionConfigParam(TypedDict, total=False):
language-specific hints `en`, `es`, `fr`, `de`, `hi`, `ru`, `pt`, `ja`, `it`,
and `nl`. For `soniox/stt-rt-v4`, `auto` omits the language hint and lets Soniox
auto-detect; ISO 639-1 codes (e.g. `en`, `es`) bias detection toward that
- language. For `assemblyai/universal-streaming`, `auto` (or unset) enables native
- multilingual code-switching; ISO 639-1 codes (`en`, `es`, `de`, `fr`, `pt`,
- `it`, `tr`, `nl`, `sv`, `no`, `da`, `fi`, `hi`, `vi`, `ar`, `he`, `ja`, `zh`)
- bias the session to that language. For `humain/realtime`, supported values are
- `ar`, `en`, `codeswitch` (Arabic/English code-switching), and `auto` (resolves
- server-side to code-switching). Unlike other models, `humain/realtime` does not
- fall back to `auto` when `language` is omitted — omitting it applies `en`
- instead. For `reson8/turns`, supported values are `auto` (or unset) for
- automatic language detection, and the language codes `nl`, `en`, `fr`, `fy`,
- `de`, `it`, `pl`, `pt`, `es`, and `sv` to fix the transcription language. For
- `cohere/ar-stt`, supported values are `ar` and `en`; unlike other models, this
- model does not auto-detect and defaults to `ar` when `language` is omitted.
+ language. For `assemblyai/universal-3-5-pro` (and its legacy alias
+ `assemblyai/universal-streaming`), `auto` (or unset) enables native multilingual
+ code-switching; ISO 639-1 codes (`en`, `es`, `de`, `fr`, `pt`, `it`, `tr`, `nl`,
+ `sv`, `no`, `da`, `fi`, `hi`, `vi`, `ar`, `he`, `ja`, `zh`) bias the session to
+ that language. For `humain/realtime`, supported values are `ar`, `en`,
+ `codeswitch` (Arabic/English code-switching), and `auto` (resolves server-side
+ to code-switching). Unlike other models, `humain/realtime` does not fall back to
+ `auto` when `language` is omitted — omitting it applies `en` instead. For
+ `reson8/turns`, supported values are `auto` (or unset) for automatic language
+ detection, and the language codes `nl`, `en`, `fr`, `fy`, `de`, `it`, `pl`,
+ `pt`, `es`, and `sv` to fix the transcription language. For `cohere/ar-stt`,
+ supported values are `ar` and `en`; unlike other models, this model does not
+ auto-detect and defaults to `ar` when `language` is omitted.
"""
model: Literal[
@@ -44,10 +45,12 @@ class TranscriptionConfigParam(TypedDict, total=False):
"deepgram/nova-2",
"speechmatics/standard",
"speechmatics/enhanced",
+ "assemblyai/universal-3-5-pro",
"assemblyai/universal-streaming",
"xai/grok-stt",
"soniox/stt-rt-v4",
"nvidia/parakeet-v3",
+ "omi-health/omi-med-stt-v1",
"humain/realtime",
"reson8/turns",
"cohere/ar-stt",
@@ -65,12 +68,16 @@ class TranscriptionConfigParam(TypedDict, total=False):
- `deepgram/nova-3` and `deepgram/nova-2` for live streaming transcription.
- `speechmatics/standard` and `speechmatics/enhanced` for live streaming
transcription.
- - `assemblyai/universal-streaming` for live streaming transcription.
+ - `assemblyai/universal-3-5-pro` for live streaming transcription. The legacy
+ alias `assemblyai/universal-streaming` is still accepted and resolves to the
+ same model.
- `xai/grok-stt` for live streaming transcription.
- `soniox/stt-rt-v4` for live streaming multilingual transcription with
automatic language detection.
- `nvidia/parakeet-v3` for multilingual transcription with automatic language
detection.
+ - `omi-health/omi-med-stt-v1` for English-only medical transcription
+ (Parakeet-based).
- `humain/realtime` for live streaming transcription with native Arabic and
Arabic/English code-switching support.
- `reson8/turns` for live streaming turn-based transcription of 10 European
diff --git a/src/telnyx/types/calls/transcription_engine_assemblyai_config_param.py b/src/telnyx/types/calls/transcription_engine_assemblyai_config_param.py
index b5f62f193..ab6ba0fcd 100644
--- a/src/telnyx/types/calls/transcription_engine_assemblyai_config_param.py
+++ b/src/telnyx/types/calls/transcription_engine_assemblyai_config_param.py
@@ -17,5 +17,9 @@ class TranscriptionEngineAssemblyaiConfigParam(TypedDict, total=False):
transcription_engine: Literal["AssemblyAI"]
"""Engine identifier for AssemblyAI transcription service"""
- transcription_model: Literal["assemblyai/universal-streaming"]
- """The model to use for transcription."""
+ transcription_model: Literal["assemblyai/universal-3-5-pro", "assemblyai/universal-streaming"]
+ """The model to use for transcription.
+
+ `assemblyai/universal-streaming` is a legacy alias of
+ `assemblyai/universal-3-5-pro` and resolves to the same model.
+ """
diff --git a/src/telnyx/types/calls/transcription_engine_parakeet_config_param.py b/src/telnyx/types/calls/transcription_engine_parakeet_config_param.py
index b15bce9b7..58b99a7f6 100644
--- a/src/telnyx/types/calls/transcription_engine_parakeet_config_param.py
+++ b/src/telnyx/types/calls/transcription_engine_parakeet_config_param.py
@@ -17,5 +17,5 @@ class TranscriptionEngineParakeetConfigParam(TypedDict, total=False):
transcription_engine: Literal["Parakeet"]
"""Engine identifier for Parakeet transcription service"""
- transcription_model: Literal["nvidia/parakeet-v3"]
+ transcription_model: Literal["nvidia/parakeet-v3", "omi-health/omi-med-stt-v1"]
"""The model to use for transcription."""
diff --git a/src/telnyx/types/compute/funcs/__init__.py b/src/telnyx/types/compute/funcs/__init__.py
new file mode 100644
index 000000000..25b036650
--- /dev/null
+++ b/src/telnyx/types/compute/funcs/__init__.py
@@ -0,0 +1,18 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import TYPE_CHECKING, Any
+
+from .export_create_params import ExportCreateParams as ExportCreateParams
+
+if TYPE_CHECKING:
+ from .func_log_export_config_response import FuncLogExportConfigResponse as FuncLogExportConfigResponse
+
+
+def __getattr__(name: str) -> Any:
+ if name == "FuncLogExportConfigResponse":
+ from .func_log_export_config_response import FuncLogExportConfigResponse
+
+ return FuncLogExportConfigResponse
+ raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
diff --git a/src/telnyx/types/compute/funcs/export_create_params.py b/src/telnyx/types/compute/funcs/export_create_params.py
new file mode 100644
index 000000000..3ead0ec86
--- /dev/null
+++ b/src/telnyx/types/compute/funcs/export_create_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 import Dict
+from typing_extensions import Required, TypedDict
+
+__all__ = ["ExportCreateParams"]
+
+
+class ExportCreateParams(TypedDict, total=False):
+ endpoint: Required[str]
+ """HTTPS URL to push logs to"""
+
+ headers: Required[Dict[str, str]]
+ """Headers attached to every export push, as key-value pairs (e.g.
+
+ an auth token the collector expects). Required even when empty — {} means "no
+ headers". Encrypted at rest; never returned.
+ """
+
+ invocation_export_enabled: Required[bool]
+ """Export invocation records (one per HTTP request) to this destination"""
+
+ runtime_export_enabled: Required[bool]
+ """Export runtime logs (function stdout/stderr) to this destination"""
diff --git a/src/telnyx/types/compute/funcs/func_log_export_config_response.py b/src/telnyx/types/compute/funcs/func_log_export_config_response.py
new file mode 100644
index 000000000..6f766f3a6
--- /dev/null
+++ b/src/telnyx/types/compute/funcs/func_log_export_config_response.py
@@ -0,0 +1,51 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Optional
+from datetime import datetime
+from typing_extensions import Literal
+
+from ...._models import BaseModel
+
+__all__ = ["FuncLogExportConfigResponse", "Data"]
+
+
+class Data(BaseModel):
+ """Metadata-only view of a function's log export destination.
+
+ Header values are write-only (encrypted server-side) and never appear in any response.
+ """
+
+ id: Optional[str] = None
+ """Configuration record ID"""
+
+ created_at: Optional[datetime] = None
+
+ enabled: Optional[bool] = None
+ """Whether export is enabled for this function"""
+
+ endpoint: Optional[str] = None
+ """HTTPS OTLP endpoint URL logs are pushed to"""
+
+ func_id: Optional[str] = None
+ """Function ID this configuration belongs to"""
+
+ invocation_export_enabled: Optional[bool] = None
+ """Whether invocation records (one per HTTP request) are exported"""
+
+ record_type: Optional[Literal["compute_func_log_export_config"]] = None
+
+ runtime_export_enabled: Optional[bool] = None
+ """Whether runtime logs (function stdout/stderr) are exported"""
+
+ updated_at: Optional[datetime] = None
+
+
+class FuncLogExportConfigResponse(BaseModel):
+ data: Optional[Data] = None
+ """Metadata-only view of a function's log export destination.
+
+ Header values are write-only (encrypted server-side) and never appear in any
+ response.
+ """
diff --git a/src/telnyx/types/connection_retrieve_count_response.py b/src/telnyx/types/connection_retrieve_count_response.py
new file mode 100644
index 000000000..0af1a1de6
--- /dev/null
+++ b/src/telnyx/types/connection_retrieve_count_response.py
@@ -0,0 +1,105 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Union
+from typing_extensions import TypeAlias
+
+from .._models import BaseModel
+
+__all__ = [
+ "ConnectionRetrieveCountResponse",
+ "Data",
+ "DataCounts",
+ "DataLimits",
+ "DataLimitsGlobalConnectionLimit",
+ "DataLimitsPerTypeConnectionLimits",
+]
+
+
+class DataCounts(BaseModel):
+ """Counts of the authenticated user's connections, grouped by connection type.
+
+ Forward-only connections are excluded.
+ """
+
+ call_control_applications: int
+ """Number of Call Control applications."""
+
+ credential_connections: int
+ """Number of credential connections."""
+
+ external_connections: int
+ """Number of external connections."""
+
+ fax_connections: int
+ """Number of Fax applications."""
+
+ fqdn_connections: int
+ """Number of FQDN connections."""
+
+ ip_connections: int
+ """Number of IP connections."""
+
+ microsoft_teams_sbc_connections: int
+ """Number of Microsoft Teams SBC (direct routing) connections."""
+
+ mobile_voice_connections: int
+ """Number of mobile voice (IMS) connections."""
+
+ operator_connect_connections: int
+ """Number of Microsoft Operator Connect connections."""
+
+ texml_applications: int
+ """Number of TeXML applications."""
+
+ third_party_provider_connections: int
+ """Number of third-party provider connections."""
+
+ uac_connections: int
+ """Number of UAC connections."""
+
+ zoom_sbc_connections: int
+ """Number of Zoom SBC connections."""
+
+
+class DataLimitsGlobalConnectionLimit(BaseModel):
+ global_limit: int
+ """Maximum total number of connections allowed, when a global limit applies."""
+
+
+class DataLimitsPerTypeConnectionLimits(BaseModel):
+ standard_limit: int
+ """Maximum number of standard connections allowed, when per-type limits apply."""
+
+ texml_limit: int
+ """Maximum number of TeXML applications allowed, when per-type limits apply."""
+
+ uac_limit: int
+ """Maximum number of UAC connections allowed, when per-type limits apply."""
+
+
+DataLimits: TypeAlias = Union[DataLimitsGlobalConnectionLimit, DataLimitsPerTypeConnectionLimits]
+
+
+class Data(BaseModel):
+ counts: DataCounts
+ """Counts of the authenticated user's connections, grouped by connection type.
+
+ Forward-only connections are excluded.
+ """
+
+ limits: DataLimits
+ """Connection limits that apply to the user.
+
+ Contains a single global_limit when a global connection limit applies, or
+ per-type limits (standard_limit, texml_limit and uac_limit) when the user has
+ per-type connection count capabilities.
+ """
+
+ record_type: str
+ """Identifies the type of the resource."""
+
+
+class ConnectionRetrieveCountResponse(BaseModel):
+ data: Data
diff --git a/src/telnyx/types/detail_record_list_params.py b/src/telnyx/types/detail_record_list_params.py
index 7e2f7092a..c6db15fbf 100644
--- a/src/telnyx/types/detail_record_list_params.py
+++ b/src/telnyx/types/detail_record_list_params.py
@@ -15,7 +15,12 @@ class DetailRecordListParams(TypedDict, total=False):
"""Filter records on a given record attribute and value.
Example: filter[status]=delivered.
Required: filter[record_type] must
- be specified.
+ be specified.
The valid filter fields depend on the record_type: filtering
+ by a field that does not exist for the selected record_type is rejected with a
+ 400 error. Call-control and sip-trunking records use started_at, finished_at and
+ answered_at (they have no created_at); messaging records use created_at. To list
+ the fields available for a record_type, use the /v2/detail_records/options
+ endpoint.
"""
page_number: Annotated[int, PropertyInfo(alias="page[number]")]
@@ -23,13 +28,21 @@ class DetailRecordListParams(TypedDict, total=False):
page_size: Annotated[int, PropertyInfo(alias="page[size]")]
sort: SequenceNotStr[str]
- """Specifies the sort order for results.
Example: sort=-created_at"""
+ """Specifies the sort order for results.
+
+
Example: sort=-created_at
The valid sort fields depend on the
+ record_type: sort by a field that does not exist for the selected record_type is
+ rejected with a 400 error. Call-control and sip-trunking records use started_at,
+ finished_at and answered_at (they have no created_at); messaging records use
+ created_at. To list the fields available for a record_type, use the
+ /v2/detail_records/options endpoint.
+ """
class Filter(TypedDict, total=False, extra_items=object): # type: ignore[call-arg]
"""Filter records on a given record attribute and value.
-
Example: filter[status]=delivered.
Required: filter[record_type] must be specified.
+
Example: filter[status]=delivered.
Required: filter[record_type] must be specified.
The valid filter fields depend on the record_type: filtering by a field that does not exist for the selected record_type is rejected with a 400 error. Call-control and sip-trunking records use started_at, finished_at and answered_at (they have no created_at); messaging records use created_at. To list the fields available for a record_type, use the /v2/detail_records/options endpoint.
"""
record_type: Required[
diff --git a/src/telnyx/types/inbound_message_webhook_event.py b/src/telnyx/types/inbound_message_webhook_event.py
index bb52b55b6..97116b7f6 100644
--- a/src/telnyx/types/inbound_message_webhook_event.py
+++ b/src/telnyx/types/inbound_message_webhook_event.py
@@ -3,30 +3,12 @@
from __future__ import annotations
from typing import Optional
-from datetime import datetime
-from typing_extensions import Literal
from .._models import BaseModel
-from .messaging_inbound_message_payload import MessagingInboundMessagePayload
+from .messaging_inbound_message import MessagingInboundMessage
-__all__ = ["InboundMessageWebhookEvent", "Data"]
-
-
-class Data(BaseModel):
- id: Optional[str] = None
- """Identifies the type of resource."""
-
- event_type: Optional[Literal["message.received"]] = None
- """The type of event being delivered."""
-
- occurred_at: Optional[datetime] = None
- """ISO 8601 formatted date indicating when the resource was created."""
-
- payload: Optional[MessagingInboundMessagePayload] = None
-
- record_type: Optional[Literal["event"]] = None
- """Identifies the type of the resource."""
+__all__ = ["InboundMessageWebhookEvent"]
class InboundMessageWebhookEvent(BaseModel):
- data: Optional[Data] = None
+ data: Optional[MessagingInboundMessage] = None
diff --git a/src/telnyx/types/inbound_message_webhook_event1.py b/src/telnyx/types/inbound_message_webhook_event1.py
index bb52b55b6..97116b7f6 100644
--- a/src/telnyx/types/inbound_message_webhook_event1.py
+++ b/src/telnyx/types/inbound_message_webhook_event1.py
@@ -3,30 +3,12 @@
from __future__ import annotations
from typing import Optional
-from datetime import datetime
-from typing_extensions import Literal
from .._models import BaseModel
-from .messaging_inbound_message_payload import MessagingInboundMessagePayload
+from .messaging_inbound_message import MessagingInboundMessage
-__all__ = ["InboundMessageWebhookEvent", "Data"]
-
-
-class Data(BaseModel):
- id: Optional[str] = None
- """Identifies the type of resource."""
-
- event_type: Optional[Literal["message.received"]] = None
- """The type of event being delivered."""
-
- occurred_at: Optional[datetime] = None
- """ISO 8601 formatted date indicating when the resource was created."""
-
- payload: Optional[MessagingInboundMessagePayload] = None
-
- record_type: Optional[Literal["event"]] = None
- """Identifies the type of the resource."""
+__all__ = ["InboundMessageWebhookEvent"]
class InboundMessageWebhookEvent(BaseModel):
- data: Optional[Data] = None
+ data: Optional[MessagingInboundMessage] = None
diff --git a/src/telnyx/types/machine_payment_account_credit_params.py b/src/telnyx/types/machine_payment_account_credit_params.py
new file mode 100644
index 000000000..cb1b922f2
--- /dev/null
+++ b/src/telnyx/types/machine_payment_account_credit_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
+
+__all__ = ["MachinePaymentAccountCreditParams"]
+
+
+class MachinePaymentAccountCreditParams(TypedDict, total=False):
+ amount_usd: Required[str]
+ """
+ Amount to credit in USD, as a decimal string with up to two fractional digits
+ (by default between 5.00 and 500.00). The request body is required on the
+ initial challenge request and remains required on a paid retry, where you
+ re-send the identical body plus the payment credential — the credential, not the
+ body, selects the payment, and the retried body is not re-validated.
+ """
diff --git a/src/telnyx/types/machine_payment_account_credit_response.py b/src/telnyx/types/machine_payment_account_credit_response.py
new file mode 100644
index 000000000..8ff9de0d2
--- /dev/null
+++ b/src/telnyx/types/machine_payment_account_credit_response.py
@@ -0,0 +1,87 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Optional
+from datetime import datetime
+from typing_extensions import Literal
+
+from .._models import BaseModel
+
+__all__ = ["MachinePaymentAccountCreditResponse", "Data"]
+
+
+class Data(BaseModel):
+ """An account-credit transaction settled through the Machine Payment Protocol."""
+
+ id: str
+ """Unique identifier of the account-credit transaction."""
+
+ account_id: str
+ """Identifier of the credited Telnyx account.
+
+ Derived from the authenticated user on the initial request and from the verified
+ payment credential on a paid retry — never from the request body.
+ """
+
+ amount: str
+ """Credited amount as a decimal string with two fractional digits."""
+
+ currency: str
+ """ISO 4217 currency code of the credited amount (currently always USD)."""
+
+ payment_source: Literal["machine_payment"]
+ """
+ Payment source identifier distinguishing machine payments from other
+ account-credit sources.
+ """
+
+ record_type: Literal["machine_payment_account_credit"]
+ """Record type identifier."""
+
+ created: Optional[bool] = None
+ """
+ True when this response created a new account credit, false when an existing
+ transaction was returned for a duplicate paid retry.
+ """
+
+ created_at: Optional[datetime] = None
+ """ISO 8601 timestamp when the transaction was created."""
+
+ mpp_resource: Optional[str] = None
+ """
+ Machine Payment Protocol resource identifier the payment credential was bound
+ to.
+ """
+
+ payment_intent_id: Optional[str] = None
+ """Stripe PaymentIntent identifier for Stripe settlements.
+
+ Absent for Tempo settlements.
+ """
+
+ payment_method: Optional[Literal["stripe_spt", "tempo_usdc"]] = None
+ """
+ Payment method used by the provider: `stripe_spt` for Stripe Shared Payment
+ Token payments, `tempo_usdc` for Tempo USDC payments.
+ """
+
+ provider: Optional[Literal["stripe", "tempo"]] = None
+ """Upstream payment provider that settled the payment."""
+
+ receipt_reference: Optional[str] = None
+ """
+ Provider receipt reference: the Stripe PaymentIntent identifier for Stripe
+ settlements, or the on-chain transaction hash for Tempo settlements.
+ """
+
+ status: Optional[Literal["new", "processing", "settled", "expired", "invalid"]] = None
+ """Status of the transaction.
+
+ Successful machine payment credits are recorded as `settled`.
+ """
+
+
+class MachinePaymentAccountCreditResponse(BaseModel):
+ data: Optional[Data] = None
+ """An account-credit transaction settled through the Machine Payment Protocol."""
diff --git a/src/telnyx/types/message_retrieve_group_messages_response.py b/src/telnyx/types/message_retrieve_group_messages_response.py
index 93bec037a..a18163d7a 100644
--- a/src/telnyx/types/message_retrieve_group_messages_response.py
+++ b/src/telnyx/types/message_retrieve_group_messages_response.py
@@ -5,10 +5,10 @@
from typing import List, Optional
from .._models import BaseModel
-from .messaging_outbound_message_payload import MessagingOutboundMessagePayload
+from .outbound_message_payload import OutboundMessagePayload
__all__ = ["MessageRetrieveGroupMessagesResponse"]
class MessageRetrieveGroupMessagesResponse(BaseModel):
- data: Optional[List[MessagingOutboundMessagePayload]] = None
+ data: Optional[List[OutboundMessagePayload]] = None
diff --git a/src/telnyx/types/message_retrieve_response.py b/src/telnyx/types/message_retrieve_response.py
index d916e98a7..4e02bab4c 100644
--- a/src/telnyx/types/message_retrieve_response.py
+++ b/src/telnyx/types/message_retrieve_response.py
@@ -7,13 +7,13 @@
from .._utils import PropertyInfo
from .._models import BaseModel
+from .outbound_message_payload import OutboundMessagePayload
from .messaging_inbound_message_payload import MessagingInboundMessagePayload
-from .messaging_outbound_message_payload import MessagingOutboundMessagePayload
__all__ = ["MessageRetrieveResponse", "Data"]
Data: TypeAlias = Annotated[
- Union[MessagingOutboundMessagePayload, MessagingInboundMessagePayload], PropertyInfo(discriminator="direction")
+ Union[OutboundMessagePayload, MessagingInboundMessagePayload], PropertyInfo(discriminator="direction")
]
diff --git a/src/telnyx/types/message_schedule_response.py b/src/telnyx/types/message_schedule_response.py
index 97f415575..40168708d 100644
--- a/src/telnyx/types/message_schedule_response.py
+++ b/src/telnyx/types/message_schedule_response.py
@@ -5,10 +5,10 @@
from typing import Optional
from .._models import BaseModel
-from .messaging_outbound_message_payload import MessagingOutboundMessagePayload
+from .outbound_message_payload import OutboundMessagePayload
__all__ = ["MessageScheduleResponse"]
class MessageScheduleResponse(BaseModel):
- data: Optional[MessagingOutboundMessagePayload] = None
+ data: Optional[OutboundMessagePayload] = None
diff --git a/src/telnyx/types/message_send_group_mms_response.py b/src/telnyx/types/message_send_group_mms_response.py
index a3d805ba6..c7f539daa 100644
--- a/src/telnyx/types/message_send_group_mms_response.py
+++ b/src/telnyx/types/message_send_group_mms_response.py
@@ -5,10 +5,10 @@
from typing import Optional
from .._models import BaseModel
-from .messaging_outbound_message_payload import MessagingOutboundMessagePayload
+from .outbound_message_payload import OutboundMessagePayload
__all__ = ["MessageSendGroupMmsResponse"]
class MessageSendGroupMmsResponse(BaseModel):
- data: Optional[MessagingOutboundMessagePayload] = None
+ data: Optional[OutboundMessagePayload] = None
diff --git a/src/telnyx/types/message_send_long_code_response.py b/src/telnyx/types/message_send_long_code_response.py
index 3e3f0e629..e9ffdf7eb 100644
--- a/src/telnyx/types/message_send_long_code_response.py
+++ b/src/telnyx/types/message_send_long_code_response.py
@@ -5,10 +5,10 @@
from typing import Optional
from .._models import BaseModel
-from .messaging_outbound_message_payload import MessagingOutboundMessagePayload
+from .outbound_message_payload import OutboundMessagePayload
__all__ = ["MessageSendLongCodeResponse"]
class MessageSendLongCodeResponse(BaseModel):
- data: Optional[MessagingOutboundMessagePayload] = None
+ data: Optional[OutboundMessagePayload] = None
diff --git a/src/telnyx/types/message_send_number_pool_response.py b/src/telnyx/types/message_send_number_pool_response.py
index 17a80bc7d..3a8c9163d 100644
--- a/src/telnyx/types/message_send_number_pool_response.py
+++ b/src/telnyx/types/message_send_number_pool_response.py
@@ -5,10 +5,10 @@
from typing import Optional
from .._models import BaseModel
-from .messaging_outbound_message_payload import MessagingOutboundMessagePayload
+from .outbound_message_payload import OutboundMessagePayload
__all__ = ["MessageSendNumberPoolResponse"]
class MessageSendNumberPoolResponse(BaseModel):
- data: Optional[MessagingOutboundMessagePayload] = None
+ data: Optional[OutboundMessagePayload] = None
diff --git a/src/telnyx/types/message_send_response.py b/src/telnyx/types/message_send_response.py
index 1f38879f6..c1f006614 100644
--- a/src/telnyx/types/message_send_response.py
+++ b/src/telnyx/types/message_send_response.py
@@ -5,10 +5,10 @@
from typing import Optional
from .._models import BaseModel
-from .messaging_outbound_message_payload import MessagingOutboundMessagePayload
+from .outbound_message_payload import OutboundMessagePayload
__all__ = ["MessageSendResponse"]
class MessageSendResponse(BaseModel):
- data: Optional[MessagingOutboundMessagePayload] = None
+ data: Optional[OutboundMessagePayload] = None
diff --git a/src/telnyx/types/message_send_short_code_response.py b/src/telnyx/types/message_send_short_code_response.py
index 950e4ca8a..3b02b298e 100644
--- a/src/telnyx/types/message_send_short_code_response.py
+++ b/src/telnyx/types/message_send_short_code_response.py
@@ -5,10 +5,10 @@
from typing import Optional
from .._models import BaseModel
-from .messaging_outbound_message_payload import MessagingOutboundMessagePayload
+from .outbound_message_payload import OutboundMessagePayload
__all__ = ["MessageSendShortCodeResponse"]
class MessageSendShortCodeResponse(BaseModel):
- data: Optional[MessagingOutboundMessagePayload] = None
+ data: Optional[OutboundMessagePayload] = None
diff --git a/src/telnyx/types/messaging_inbound_message.py b/src/telnyx/types/messaging_inbound_message.py
new file mode 100644
index 000000000..762880bb0
--- /dev/null
+++ b/src/telnyx/types/messaging_inbound_message.py
@@ -0,0 +1,28 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Optional
+from datetime import datetime
+from typing_extensions import Literal
+
+from .._models import BaseModel
+from .messaging_inbound_message_payload import MessagingInboundMessagePayload
+
+__all__ = ["MessagingInboundMessage"]
+
+
+class MessagingInboundMessage(BaseModel):
+ id: Optional[str] = None
+ """Identifies the type of resource."""
+
+ event_type: Optional[Literal["message.received"]] = None
+ """The type of event being delivered."""
+
+ occurred_at: Optional[datetime] = None
+ """ISO 8601 formatted date indicating when the resource was created."""
+
+ payload: Optional[MessagingInboundMessagePayload] = None
+
+ record_type: Optional[Literal["event"]] = None
+ """Identifies the type of the resource."""
diff --git a/src/telnyx/types/messaging_inbound_message_payload.py b/src/telnyx/types/messaging_inbound_message_payload.py
index 0cdf0c60e..9452ceb83 100644
--- a/src/telnyx/types/messaging_inbound_message_payload.py
+++ b/src/telnyx/types/messaging_inbound_message_payload.py
@@ -4,7 +4,7 @@
from typing import TYPE_CHECKING, Dict, List, Union, Optional
from datetime import datetime
-from typing_extensions import Literal
+from typing_extensions import Literal, TypeAlias
from pydantic import Field as FieldInfo
@@ -15,7 +15,14 @@
"MessagingInboundMessagePayload",
"Body",
"BodyEdit",
+ "BodyLocation",
"BodyRevoke",
+ "BodySuggestionResponse",
+ "BodyText",
+ "BodyTextBody",
+ "BodyUserFile",
+ "BodyUserFilePayload",
+ "BodyUserFileThumbnail",
"Cc",
"Cost",
"CostBreakdown",
@@ -40,6 +47,14 @@ class BodyEdit(BaseModel):
"""
+class BodyLocation(BaseModel):
+ """Location shared in an RCS message."""
+
+ latitude: Optional[float] = None
+
+ longitude: Optional[float] = None
+
+
class BodyRevoke(BaseModel):
"""Details for a revoked WhatsApp message."""
@@ -50,10 +65,65 @@ class BodyRevoke(BaseModel):
"""
+class BodySuggestionResponse(BaseModel):
+ """Selected RCS suggestion."""
+
+ postback_data: Optional[str] = None
+
+ text: Optional[str] = None
+
+
+class BodyTextBody(BaseModel):
+ body: Optional[str] = None
+
+ if TYPE_CHECKING:
+ # Some versions of Pydantic <2.8.0 have a bug and don’t allow assigning a
+ # value to this field, so for compatibility we avoid doing it at runtime.
+ __pydantic_extra__: Dict[str, object] = FieldInfo(init=False) # pyright: ignore[reportIncompatibleVariableOverride]
+
+ # Stub to indicate that arbitrary properties are accepted.
+ # To access properties that are not valid identifiers you can use `getattr`, e.g.
+ # `getattr(obj, '$type')`
+ def __getattr__(self, attr: str) -> object: ...
+ else:
+ __pydantic_extra__: Dict[str, object]
+
+
+BodyText: TypeAlias = Union[str, BodyTextBody]
+
+
+class BodyUserFilePayload(BaseModel):
+ file_name: Optional[str] = None
+
+ file_size_bytes: Optional[int] = None
+
+ file_uri: Optional[str] = None
+
+ mime_type: Optional[str] = None
+
+
+class BodyUserFileThumbnail(BaseModel):
+ file_name: Optional[str] = None
+
+ file_size_bytes: Optional[int] = None
+
+ file_uri: Optional[str] = None
+
+ mime_type: Optional[str] = None
+
+
+class BodyUserFile(BaseModel):
+ """RCS file attachment and optional thumbnail."""
+
+ payload: Optional[BodyUserFilePayload] = None
+
+ thumbnail: Optional[BodyUserFileThumbnail] = None
+
+
class Body(BaseModel):
- """WhatsApp message body.
+ """Message body for RCS and WhatsApp.
- For message edits and revocations, inspect `type` and the corresponding `edit` or `revoke` object.
+ RCS messages contain text, user_file, location, or suggestion_response. For WhatsApp edits and revocations, inspect type and the corresponding edit or revoke object.
"""
id: Optional[str] = None
@@ -68,9 +138,18 @@ class Body(BaseModel):
from_: Optional[str] = FieldInfo(alias="from", default=None)
"""WhatsApp sender in E.164 format."""
+ location: Optional[BodyLocation] = None
+ """Location shared in an RCS message."""
+
revoke: Optional[BodyRevoke] = None
"""Details for a revoked WhatsApp message."""
+ suggestion_response: Optional[BodySuggestionResponse] = None
+ """Selected RCS suggestion."""
+
+ text: Optional[BodyText] = None
+ """RCS text string or WhatsApp text object."""
+
timestamp: Optional[str] = None
"""Unix timestamp supplied by Meta."""
@@ -80,6 +159,9 @@ class Body(BaseModel):
Edit and revoke events use `edit` and `revoke`, respectively.
"""
+ user_file: Optional[BodyUserFile] = None
+ """RCS file attachment and optional thumbnail."""
+
if TYPE_CHECKING:
# Some versions of Pydantic <2.8.0 have a bug and don’t allow assigning a
# value to this field, so for compatibility we avoid doing it at runtime.
@@ -144,7 +226,7 @@ class From(BaseModel):
carrier: Optional[str] = None
"""The carrier of the sender."""
- line_type: Optional[Literal["Wireline", "Wireless", "VoWiFi", "VoIP", "Pre-Paid Wireless", ""]] = None
+ line_type: Optional[Literal["Wireline", "Wireless", "VoWiFi", "VoIP", "Pre-Paid Wireless", "", "long_code"]] = None
"""The line-type of the sender."""
phone_number: Optional[str] = None
@@ -153,7 +235,7 @@ class From(BaseModel):
code).
"""
- status: Optional[Literal["received", "delivered"]] = None
+ status: Optional[Literal["received", "delivered", "webhook_delivered"]] = None
class Media(BaseModel):
@@ -171,6 +253,12 @@ class Media(BaseModel):
class ToUnionMember0(BaseModel):
+ agent_id: Optional[str] = None
+ """RCS agent identifier."""
+
+ agent_name: Optional[str] = None
+ """RCS agent name."""
+
carrier: Optional[str] = None
"""The carrier of the receiver."""
@@ -198,11 +286,19 @@ class MessagingInboundMessagePayload(BaseModel):
id: Optional[str] = None
"""Identifies the type of resource."""
+ autoresponse_type: Optional[str] = None
+ """Automatic response type triggered by an inbound opt-in, opt-out, or help
+ keyword.
+
+ Examples include START, STOP, and HELP.
+ """
+
body: Optional[Body] = None
- """WhatsApp message body.
+ """Message body for RCS and WhatsApp.
- For message edits and revocations, inspect `type` and the corresponding `edit`
- or `revoke` object.
+ RCS messages contain text, user_file, location, or suggestion_response. For
+ WhatsApp edits and revocations, inspect type and the corresponding edit or
+ revoke object.
"""
cc: Optional[List[Cc]] = None
@@ -279,11 +375,12 @@ class MessagingInboundMessagePayload(BaseModel):
to: Union[List[ToUnionMember0], str, None] = None
"""Receiving address.
- SMS and MMS webhooks use an array of recipients. WhatsApp webhooks use one E.164
- phone number.
+ SMS, MMS and RCS webhooks use an array of recipients. RCS recipients are
+ identified by agent_id and agent_name. WhatsApp webhooks use one E.164 phone
+ number.
"""
- type: Optional[Literal["SMS", "MMS", "WHATSAPP"]] = None
+ type: Optional[Literal["SMS", "MMS", "WHATSAPP", "RCS"]] = None
"""The messaging channel used for the message."""
valid_until: Optional[datetime] = None
diff --git a/src/telnyx/types/messaging_outbound_message_payload.py b/src/telnyx/types/messaging_outbound_message_payload.py
deleted file mode 100644
index c022e0692..000000000
--- a/src/telnyx/types/messaging_outbound_message_payload.py
+++ /dev/null
@@ -1,236 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing import List, Optional
-from datetime import datetime
-from typing_extensions import Literal
-
-from pydantic import Field as FieldInfo
-
-from .._models import BaseModel
-from .messaging_error_0b38e7044b import MessagingError0b38e7044b
-
-__all__ = [
- "MessagingOutboundMessagePayload",
- "Cc",
- "Cost",
- "CostBreakdown",
- "CostBreakdownCarrierFee",
- "CostBreakdownRate",
- "From",
- "Media",
- "To",
-]
-
-
-class Cc(BaseModel):
- carrier: Optional[str] = None
- """The carrier of the receiver."""
-
- line_type: Optional[Literal["Wireline", "Wireless", "VoWiFi", "VoIP", "Pre-Paid Wireless", ""]] = None
- """The line-type of the receiver."""
-
- phone_number: Optional[str] = None
- """Receiving address (+E.164 formatted phone number or short code)."""
-
- status: Optional[
- Literal["queued", "sending", "sent", "delivered", "sending_failed", "delivery_failed", "delivery_unconfirmed"]
- ] = None
-
-
-class Cost(BaseModel):
- amount: Optional[str] = None
- """The amount deducted from your account."""
-
- currency: Optional[str] = None
- """The ISO 4217 currency identifier."""
-
-
-class CostBreakdownCarrierFee(BaseModel):
- amount: Optional[str] = None
- """The carrier fee amount."""
-
- currency: Optional[str] = None
- """The ISO 4217 currency identifier."""
-
-
-class CostBreakdownRate(BaseModel):
- amount: Optional[str] = None
- """The rate amount applied."""
-
- currency: Optional[str] = None
- """The ISO 4217 currency identifier."""
-
-
-class CostBreakdown(BaseModel):
- """Detailed breakdown of the message cost components."""
-
- carrier_fee: Optional[CostBreakdownCarrierFee] = None
-
- rate: Optional[CostBreakdownRate] = None
-
-
-class From(BaseModel):
- carrier: Optional[str] = None
- """The carrier of the receiver."""
-
- line_type: Optional[Literal["Wireline", "Wireless", "VoWiFi", "VoIP", "Pre-Paid Wireless", ""]] = None
- """The line-type of the receiver."""
-
- phone_number: Optional[str] = None
- """
- Sending address (+E.164 formatted phone number, alphanumeric sender ID, or short
- code).
- """
-
-
-class Media(BaseModel):
- content_type: Optional[str] = None
- """The MIME type of the requested media."""
-
- sha256: Optional[str] = None
- """The SHA256 hash of the requested media."""
-
- size: Optional[int] = None
- """The size of the requested media."""
-
- url: Optional[str] = None
- """The url of the media requested to be sent."""
-
-
-class To(BaseModel):
- carrier: Optional[str] = None
- """The carrier of the receiver."""
-
- line_type: Optional[Literal["Wireline", "Wireless", "VoWiFi", "VoIP", "Pre-Paid Wireless", ""]] = None
- """The line-type of the receiver."""
-
- phone_number: Optional[str] = None
- """Receiving address (+E.164 formatted phone number or short code)."""
-
- status: Optional[
- Literal[
- "queued",
- "sending",
- "sent",
- "expired",
- "sending_failed",
- "delivery_unconfirmed",
- "delivered",
- "delivery_failed",
- ]
- ] = None
- """The delivery status of the message."""
-
-
-class MessagingOutboundMessagePayload(BaseModel):
- id: Optional[str] = None
- """Identifies the type of resource."""
-
- cc: Optional[List[Cc]] = None
-
- completed_at: Optional[datetime] = None
- """ISO 8601 formatted date indicating when the message was finalized."""
-
- cost: Optional[Cost] = None
-
- cost_breakdown: Optional[CostBreakdown] = None
- """Detailed breakdown of the message cost components."""
-
- direction: Optional[Literal["outbound"]] = None
- """The direction of the message.
-
- Inbound messages are sent to you whereas outbound messages are sent from you.
- """
-
- encoding: Optional[str] = None
- """Encoding scheme used for the message body."""
-
- errors: Optional[List[MessagingError0b38e7044b]] = None
- """
- These errors may point at addressees when referring to unsuccessful/unconfirmed
- delivery statuses.
- """
-
- from_: Optional[From] = FieldInfo(alias="from", default=None)
-
- media: Optional[List[Media]] = None
-
- messaging_profile_id: Optional[str] = None
- """Unique identifier for a messaging profile."""
-
- num_chars: Optional[int] = None
- """The number of characters in the message text"""
-
- organization_id: Optional[str] = None
- """The id of the organization the messaging profile belongs to."""
-
- parts: Optional[int] = None
- """Number of parts into which the message's body must be split."""
-
- received_at: Optional[datetime] = None
- """ISO 8601 formatted date indicating when the message request was received."""
-
- record_type: Optional[Literal["message"]] = None
- """Identifies the type of the resource."""
-
- sent_at: Optional[datetime] = None
- """ISO 8601 formatted date indicating when the message was sent."""
-
- smart_encoding_applied: Optional[bool] = None
- """Indicates whether smart encoding was applied to this message.
-
- When `true`, one or more Unicode characters were automatically replaced with
- GSM-7 equivalents to reduce segment count and cost. The original message text is
- preserved in webhooks.
- """
-
- subject: Optional[str] = None
- """Subject of multimedia message"""
-
- tags: Optional[List[str]] = None
- """Tags associated with the resource."""
-
- tcr_campaign_billable: Optional[bool] = None
- """Indicates whether the TCR campaign is billable."""
-
- tcr_campaign_id: Optional[str] = None
- """The Campaign Registry (TCR) campaign ID associated with the message."""
-
- tcr_campaign_registered: Optional[str] = None
- """The registration status of the TCR campaign."""
-
- text: Optional[str] = None
- """Message body (i.e., content) as a non-empty string.
-
- **Required for SMS**
- """
-
- to: Optional[List[To]] = None
-
- type: Optional[Literal["SMS", "MMS"]] = None
- """The type of message."""
-
- valid_until: Optional[datetime] = None
- """
- Message must be out of the queue by this time or else it will be discarded and
- marked as 'sending_failed'. Once the message moves out of the queue, this field
- will be nulled
- """
-
- wait_seconds: Optional[float] = None
- """
- Seconds the message is queued due to rate limiting before being sent to the
- carrier. Represents the maximum wait across all applicable rate limits (account,
- carrier, campaign). 0.0 = no queuing delay.
- """
-
- webhook_failover_url: Optional[str] = None
- """
- The failover URL where webhooks related to this message will be sent if sending
- to the primary URL fails.
- """
-
- webhook_url: Optional[str] = None
- """The URL where webhooks related to this message will be sent."""
diff --git a/src/telnyx/types/noise_suppression_engine_list_response.py b/src/telnyx/types/noise_suppression_engine_list_response.py
new file mode 100644
index 000000000..851ac843e
--- /dev/null
+++ b/src/telnyx/types/noise_suppression_engine_list_response.py
@@ -0,0 +1,29 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import List
+
+from .._models import BaseModel
+
+__all__ = ["NoiseSuppressionEngineListResponse", "Data"]
+
+
+class Data(BaseModel):
+ """A noise suppression engine available to the authenticated user."""
+
+ default_attenuation_level: int
+ """Default attenuation level of the engine (0-100, in multiples of ten)."""
+
+ label: str
+ """Human-readable name of the engine."""
+
+ value: str
+ """
+ Machine-readable identifier of the engine, used when configuring noise
+ suppression.
+ """
+
+
+class NoiseSuppressionEngineListResponse(BaseModel):
+ data: List[Data]
diff --git a/src/telnyx/types/number_order_status_update_webhook_event.py b/src/telnyx/types/number_order_status_update_webhook_event.py
index 788c90b6c..376d7f3fc 100644
--- a/src/telnyx/types/number_order_status_update_webhook_event.py
+++ b/src/telnyx/types/number_order_status_update_webhook_event.py
@@ -123,7 +123,7 @@ class Data(BaseModel):
id: str
"""Unique identifier for the event"""
- event_type: str
+ event_type: Literal["number_order.complete"]
"""The type of event being sent"""
occurred_at: datetime
diff --git a/src/telnyx/types/number_order_status_update_webhook_event1.py b/src/telnyx/types/number_order_status_update_webhook_event1.py
index 788c90b6c..376d7f3fc 100644
--- a/src/telnyx/types/number_order_status_update_webhook_event1.py
+++ b/src/telnyx/types/number_order_status_update_webhook_event1.py
@@ -123,7 +123,7 @@ class Data(BaseModel):
id: str
"""Unique identifier for the event"""
- event_type: str
+ event_type: Literal["number_order.complete"]
"""The type of event being sent"""
occurred_at: datetime
diff --git a/src/telnyx/types/outbound_message.py b/src/telnyx/types/outbound_message.py
index cb929ffa0..92c4118ad 100644
--- a/src/telnyx/types/outbound_message.py
+++ b/src/telnyx/types/outbound_message.py
@@ -16,7 +16,7 @@ class OutboundMessage(BaseModel):
id: Optional[str] = None
"""Identifies the type of resource."""
- event_type: Optional[Literal["message.sent", "message.finalized"]] = None
+ event_type: Optional[Literal["message.sent", "message.finalized", "message.read"]] = None
"""The type of event being delivered."""
occurred_at: Optional[datetime] = None
diff --git a/src/telnyx/types/outbound_message_payload.py b/src/telnyx/types/outbound_message_payload.py
index d402968d3..9f4147845 100644
--- a/src/telnyx/types/outbound_message_payload.py
+++ b/src/telnyx/types/outbound_message_payload.py
@@ -9,10 +9,11 @@
from pydantic import Field as FieldInfo
from .._models import BaseModel
-from .shared.messaging_error import MessagingError
+from .messaging_error_0b38e7044b import MessagingError0b38e7044b
__all__ = [
"OutboundMessagePayload",
+ "Body",
"Cc",
"Cost",
"CostBreakdown",
@@ -24,6 +25,13 @@
]
+class Body(BaseModel):
+ """RCS webhook message body. Text messages use the text property."""
+
+ text: Optional[str] = None
+ """RCS text message."""
+
+
class Cc(BaseModel):
carrier: Optional[str] = None
"""The carrier of the receiver."""
@@ -72,6 +80,12 @@ class CostBreakdown(BaseModel):
class From(BaseModel):
+ agent_id: Optional[str] = None
+ """RCS agent identifier."""
+
+ agent_name: Optional[str] = None
+ """RCS agent name."""
+
carrier: Optional[str] = None
"""The carrier of the receiver."""
@@ -119,6 +133,7 @@ class To(BaseModel):
"delivery_unconfirmed",
"delivered",
"delivery_failed",
+ "read",
]
] = None
"""The delivery status of the message."""
@@ -128,6 +143,9 @@ class OutboundMessagePayload(BaseModel):
id: Optional[str] = None
"""Identifies the type of resource."""
+ body: Optional[Body] = None
+ """RCS webhook message body. Text messages use the text property."""
+
cc: Optional[List[Cc]] = None
completed_at: Optional[datetime] = None
@@ -147,7 +165,7 @@ class OutboundMessagePayload(BaseModel):
encoding: Optional[str] = None
"""Encoding scheme used for the message body."""
- errors: Optional[List[MessagingError]] = None
+ errors: Optional[List[MessagingError0b38e7044b]] = None
"""
These errors may point at addressees when referring to unsuccessful/unconfirmed
delivery statuses.
@@ -209,7 +227,7 @@ class OutboundMessagePayload(BaseModel):
to: Optional[List[To]] = None
- type: Optional[Literal["SMS", "MMS"]] = None
+ type: Optional[Literal["SMS", "MMS", "RCS"]] = None
"""The type of message."""
valid_until: Optional[datetime] = None
diff --git a/src/telnyx/types/speech_to_text_retrieve_transcription_params.py b/src/telnyx/types/speech_to_text_retrieve_transcription_params.py
index a56aea9c3..6bf0603f6 100644
--- a/src/telnyx/types/speech_to_text_retrieve_transcription_params.py
+++ b/src/telnyx/types/speech_to_text_retrieve_transcription_params.py
@@ -79,6 +79,7 @@ class SpeechToTextRetrieveTranscriptionParams(TypedDict, total=False):
"speechmatics/standard",
"soniox/stt-rt-v4",
"nvidia/parakeet-v3",
+ "omi-health/omi-med-stt-v1",
"humain/realtime",
"reson8/turns",
"cohere/ar-stt",
diff --git a/src/telnyx/types/success_response.py b/src/telnyx/types/success_response.py
new file mode 100644
index 000000000..47eaf5782
--- /dev/null
+++ b/src/telnyx/types/success_response.py
@@ -0,0 +1,17 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from .._models import BaseModel
+
+__all__ = ["SuccessResponse"]
+
+
+class SuccessResponse(BaseModel):
+ """Status envelope used by the signup and magic-link flows."""
+
+ message: str
+ """Human-readable status message."""
+
+ success: bool
+ """Whether the request was accepted."""
diff --git a/src/telnyx/types/texml/__init__.py b/src/telnyx/types/texml/__init__.py
index 50619e3c1..cbc98a191 100644
--- a/src/telnyx/types/texml/__init__.py
+++ b/src/telnyx/types/texml/__init__.py
@@ -4,6 +4,7 @@
from typing import TYPE_CHECKING, Any
+from .call_create_params import CallCreateParams as CallCreateParams
from .account_retrieve_recordings_json_params import (
AccountRetrieveRecordingsJsonParams as AccountRetrieveRecordingsJsonParams,
)
@@ -12,6 +13,7 @@
)
if TYPE_CHECKING:
+ from .call_create_response import CallCreateResponse as CallCreateResponse
from .texml_recording_subresources_uris import TexmlRecordingSubresourcesUris as TexmlRecordingSubresourcesUris
from .texml_get_call_recording_response_body import (
TexmlGetCallRecordingResponseBody as TexmlGetCallRecordingResponseBody,
@@ -22,6 +24,10 @@
def __getattr__(name: str) -> Any:
+ if name == "CallCreateResponse":
+ from .call_create_response import CallCreateResponse
+
+ return CallCreateResponse
if name == "TexmlGetCallRecordingResponseBody":
from .texml_get_call_recording_response_body import TexmlGetCallRecordingResponseBody
diff --git a/src/telnyx/types/texml/accounts/call_calls_params.py b/src/telnyx/types/texml/accounts/call_calls_params.py
index f1d2babc9..81ee3009f 100644
--- a/src/telnyx/types/texml/accounts/call_calls_params.py
+++ b/src/telnyx/types/texml/accounts/call_calls_params.py
@@ -122,6 +122,27 @@ class BodyWithURL(TypedDict, total=False):
]
"""Enables Answering Machine Detection."""
+ machine_detection_beep_max_frequency: Annotated[int, PropertyInfo(alias="MachineDetectionBeepMaxFrequency")]
+ """Highest frequency, in Hz, that a tone can reach and still be treated as a beep.
+
+ Only used when MachineDetection is enabled.
+ """
+
+ machine_detection_beep_min_frequency: Annotated[int, PropertyInfo(alias="MachineDetectionBeepMinFrequency")]
+ """Lowest frequency, in Hz, that a tone must reach to be treated as a beep.
+
+ Raising it above 480 excludes North American ringback (440 + 480 Hz), which can
+ otherwise be reported as a beep when the `freq_only` profile is in use. Only
+ used when MachineDetection is enabled.
+ """
+
+ machine_detection_beep_min_tone_duration: Annotated[int, PropertyInfo(alias="MachineDetectionBeepMinToneDuration")]
+ """Shortest tone, in milliseconds, that can be treated as a beep.
+
+ Raising it rejects brief tones such as call-progress blips. Only used when
+ MachineDetection is enabled.
+ """
+
machine_detection_beep_profile: Annotated[
Literal["both", "freq_only"], PropertyInfo(alias="MachineDetectionBeepProfile")
]
@@ -132,6 +153,37 @@ class BodyWithURL(TypedDict, total=False):
default profile. Only used when MachineDetection is enabled.
"""
+ machine_detection_beep_spectral_confirmation: Annotated[
+ bool, PropertyInfo(alias="MachineDetectionBeepSpectralConfirmation")
+ ]
+ """
+ When enabled, a candidate beep must pass an additional spectral check before it
+ is reported. Only used when MachineDetection is enabled.
+ """
+
+ machine_detection_beep_spectral_min_purity: Annotated[
+ float, PropertyInfo(alias="MachineDetectionBeepSpectralMinPurity")
+ ]
+ """Minimum spectral purity, from 0 to 1, for a tone to be treated as a beep.
+
+ Raising it rejects mixed tones such as ringback, which combines two frequencies.
+ Only used when MachineDetection is enabled.
+ """
+
+ machine_detection_beep_spectral_reject_fax_cng: Annotated[
+ bool, PropertyInfo(alias="MachineDetectionBeepSpectralRejectFaxCng")
+ ]
+ """When enabled, the fax CNG tone is rejected rather than reported as a beep.
+
+ Only used when MachineDetection is enabled.
+ """
+
+ machine_detection_beep_spectral_window: Annotated[int, PropertyInfo(alias="MachineDetectionBeepSpectralWindow")]
+ """Length of the spectral confirmation window, in milliseconds.
+
+ Only used when MachineDetection is enabled.
+ """
+
machine_detection_prompt_end_timeout: Annotated[int, PropertyInfo(alias="MachineDetectionPromptEndTimeout")]
"""
Silence duration threshold after a call screening prompt before ending prompt
@@ -382,6 +434,27 @@ class BodyWithTeXml(TypedDict, total=False):
]
"""Enables Answering Machine Detection."""
+ machine_detection_beep_max_frequency: Annotated[int, PropertyInfo(alias="MachineDetectionBeepMaxFrequency")]
+ """Highest frequency, in Hz, that a tone can reach and still be treated as a beep.
+
+ Only used when MachineDetection is enabled.
+ """
+
+ machine_detection_beep_min_frequency: Annotated[int, PropertyInfo(alias="MachineDetectionBeepMinFrequency")]
+ """Lowest frequency, in Hz, that a tone must reach to be treated as a beep.
+
+ Raising it above 480 excludes North American ringback (440 + 480 Hz), which can
+ otherwise be reported as a beep when the `freq_only` profile is in use. Only
+ used when MachineDetection is enabled.
+ """
+
+ machine_detection_beep_min_tone_duration: Annotated[int, PropertyInfo(alias="MachineDetectionBeepMinToneDuration")]
+ """Shortest tone, in milliseconds, that can be treated as a beep.
+
+ Raising it rejects brief tones such as call-progress blips. Only used when
+ MachineDetection is enabled.
+ """
+
machine_detection_beep_profile: Annotated[
Literal["both", "freq_only"], PropertyInfo(alias="MachineDetectionBeepProfile")
]
@@ -392,6 +465,37 @@ class BodyWithTeXml(TypedDict, total=False):
default profile. Only used when MachineDetection is enabled.
"""
+ machine_detection_beep_spectral_confirmation: Annotated[
+ bool, PropertyInfo(alias="MachineDetectionBeepSpectralConfirmation")
+ ]
+ """
+ When enabled, a candidate beep must pass an additional spectral check before it
+ is reported. Only used when MachineDetection is enabled.
+ """
+
+ machine_detection_beep_spectral_min_purity: Annotated[
+ float, PropertyInfo(alias="MachineDetectionBeepSpectralMinPurity")
+ ]
+ """Minimum spectral purity, from 0 to 1, for a tone to be treated as a beep.
+
+ Raising it rejects mixed tones such as ringback, which combines two frequencies.
+ Only used when MachineDetection is enabled.
+ """
+
+ machine_detection_beep_spectral_reject_fax_cng: Annotated[
+ bool, PropertyInfo(alias="MachineDetectionBeepSpectralRejectFaxCng")
+ ]
+ """When enabled, the fax CNG tone is rejected rather than reported as a beep.
+
+ Only used when MachineDetection is enabled.
+ """
+
+ machine_detection_beep_spectral_window: Annotated[int, PropertyInfo(alias="MachineDetectionBeepSpectralWindow")]
+ """Length of the spectral confirmation window, in milliseconds.
+
+ Only used when MachineDetection is enabled.
+ """
+
machine_detection_prompt_end_timeout: Annotated[int, PropertyInfo(alias="MachineDetectionPromptEndTimeout")]
"""
Silence duration threshold after a call screening prompt before ending prompt
@@ -635,6 +739,27 @@ class BodyApplicationDefault(TypedDict, total=False):
]
"""Enables Answering Machine Detection."""
+ machine_detection_beep_max_frequency: Annotated[int, PropertyInfo(alias="MachineDetectionBeepMaxFrequency")]
+ """Highest frequency, in Hz, that a tone can reach and still be treated as a beep.
+
+ Only used when MachineDetection is enabled.
+ """
+
+ machine_detection_beep_min_frequency: Annotated[int, PropertyInfo(alias="MachineDetectionBeepMinFrequency")]
+ """Lowest frequency, in Hz, that a tone must reach to be treated as a beep.
+
+ Raising it above 480 excludes North American ringback (440 + 480 Hz), which can
+ otherwise be reported as a beep when the `freq_only` profile is in use. Only
+ used when MachineDetection is enabled.
+ """
+
+ machine_detection_beep_min_tone_duration: Annotated[int, PropertyInfo(alias="MachineDetectionBeepMinToneDuration")]
+ """Shortest tone, in milliseconds, that can be treated as a beep.
+
+ Raising it rejects brief tones such as call-progress blips. Only used when
+ MachineDetection is enabled.
+ """
+
machine_detection_beep_profile: Annotated[
Literal["both", "freq_only"], PropertyInfo(alias="MachineDetectionBeepProfile")
]
@@ -645,6 +770,37 @@ class BodyApplicationDefault(TypedDict, total=False):
default profile. Only used when MachineDetection is enabled.
"""
+ machine_detection_beep_spectral_confirmation: Annotated[
+ bool, PropertyInfo(alias="MachineDetectionBeepSpectralConfirmation")
+ ]
+ """
+ When enabled, a candidate beep must pass an additional spectral check before it
+ is reported. Only used when MachineDetection is enabled.
+ """
+
+ machine_detection_beep_spectral_min_purity: Annotated[
+ float, PropertyInfo(alias="MachineDetectionBeepSpectralMinPurity")
+ ]
+ """Minimum spectral purity, from 0 to 1, for a tone to be treated as a beep.
+
+ Raising it rejects mixed tones such as ringback, which combines two frequencies.
+ Only used when MachineDetection is enabled.
+ """
+
+ machine_detection_beep_spectral_reject_fax_cng: Annotated[
+ bool, PropertyInfo(alias="MachineDetectionBeepSpectralRejectFaxCng")
+ ]
+ """When enabled, the fax CNG tone is rejected rather than reported as a beep.
+
+ Only used when MachineDetection is enabled.
+ """
+
+ machine_detection_beep_spectral_window: Annotated[int, PropertyInfo(alias="MachineDetectionBeepSpectralWindow")]
+ """Length of the spectral confirmation window, in milliseconds.
+
+ Only used when MachineDetection is enabled.
+ """
+
machine_detection_prompt_end_timeout: Annotated[int, PropertyInfo(alias="MachineDetectionPromptEndTimeout")]
"""
Silence duration threshold after a call screening prompt before ending prompt
diff --git a/src/telnyx/types/texml/accounts/conferences/participant_participants_params.py b/src/telnyx/types/texml/accounts/conferences/participant_participants_params.py
index 41a22a782..139f5137b 100644
--- a/src/telnyx/types/texml/accounts/conferences/participant_participants_params.py
+++ b/src/telnyx/types/texml/accounts/conferences/participant_participants_params.py
@@ -156,6 +156,27 @@ class ParticipantParticipantsParams(TypedDict, total=False):
answering machine.
"""
+ machine_detection_beep_max_frequency: Annotated[int, PropertyInfo(alias="MachineDetectionBeepMaxFrequency")]
+ """Highest frequency, in Hz, that a tone can reach and still be treated as a beep.
+
+ Only used when MachineDetection is enabled.
+ """
+
+ machine_detection_beep_min_frequency: Annotated[int, PropertyInfo(alias="MachineDetectionBeepMinFrequency")]
+ """Lowest frequency, in Hz, that a tone must reach to be treated as a beep.
+
+ Raising it above 480 excludes North American ringback (440 + 480 Hz), which can
+ otherwise be reported as a beep when the `freq_only` profile is in use. Only
+ used when MachineDetection is enabled.
+ """
+
+ machine_detection_beep_min_tone_duration: Annotated[int, PropertyInfo(alias="MachineDetectionBeepMinToneDuration")]
+ """Shortest tone, in milliseconds, that can be treated as a beep.
+
+ Raising it rejects brief tones such as call-progress blips. Only used when
+ MachineDetection is enabled.
+ """
+
machine_detection_beep_profile: Annotated[
Literal["both", "freq_only"], PropertyInfo(alias="MachineDetectionBeepProfile")
]
@@ -166,6 +187,37 @@ class ParticipantParticipantsParams(TypedDict, total=False):
default profile. Only used when MachineDetection is enabled.
"""
+ machine_detection_beep_spectral_confirmation: Annotated[
+ bool, PropertyInfo(alias="MachineDetectionBeepSpectralConfirmation")
+ ]
+ """
+ When enabled, a candidate beep must pass an additional spectral check before it
+ is reported. Only used when MachineDetection is enabled.
+ """
+
+ machine_detection_beep_spectral_min_purity: Annotated[
+ float, PropertyInfo(alias="MachineDetectionBeepSpectralMinPurity")
+ ]
+ """Minimum spectral purity, from 0 to 1, for a tone to be treated as a beep.
+
+ Raising it rejects mixed tones such as ringback, which combines two frequencies.
+ Only used when MachineDetection is enabled.
+ """
+
+ machine_detection_beep_spectral_reject_fax_cng: Annotated[
+ bool, PropertyInfo(alias="MachineDetectionBeepSpectralRejectFaxCng")
+ ]
+ """When enabled, the fax CNG tone is rejected rather than reported as a beep.
+
+ Only used when MachineDetection is enabled.
+ """
+
+ machine_detection_beep_spectral_window: Annotated[int, PropertyInfo(alias="MachineDetectionBeepSpectralWindow")]
+ """Length of the spectral confirmation window, in milliseconds.
+
+ Only used when MachineDetection is enabled.
+ """
+
machine_detection_silence_timeout: Annotated[int, PropertyInfo(alias="MachineDetectionSilenceTimeout")]
"""If initial silence duration is greater than this value, consider it a machine.
diff --git a/src/telnyx/types/texml/call_create_params.py b/src/telnyx/types/texml/call_create_params.py
new file mode 100644
index 000000000..1411f6a99
--- /dev/null
+++ b/src/telnyx/types/texml/call_create_params.py
@@ -0,0 +1,29 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Literal, Required, Annotated, TypedDict
+
+from ..._utils import PropertyInfo
+
+__all__ = ["CallCreateParams"]
+
+
+class CallCreateParams(TypedDict, total=False):
+ from_: Required[Annotated[str, PropertyInfo(alias="From")]]
+ """The E.164-formatted phone number or SIP URI to present as the caller."""
+
+ to: Required[Annotated[str, PropertyInfo(alias="To")]]
+ """The E.164-formatted phone number or SIP URI to call."""
+
+ method: Annotated[Literal["GET", "POST"], PropertyInfo(alias="Method")]
+ """HTTP method used to retrieve TeXML instructions from Url."""
+
+ texml: Annotated[str, PropertyInfo(alias="Texml")]
+ """Inline TeXML instructions to execute when the call is answered."""
+
+ url: Annotated[str, PropertyInfo(alias="Url")]
+ """The URL from which to retrieve TeXML instructions.
+
+ Overrides the TeXML application XML request URL.
+ """
diff --git a/src/telnyx/types/texml/call_create_response.py b/src/telnyx/types/texml/call_create_response.py
new file mode 100644
index 000000000..91034cdbd
--- /dev/null
+++ b/src/telnyx/types/texml/call_create_response.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
+
+from pydantic import Field as FieldInfo
+
+from ..._models import BaseModel
+
+__all__ = ["CallCreateResponse"]
+
+
+class CallCreateResponse(BaseModel):
+ call_sid: str
+ """The call control ID of the created call."""
+
+ from_: str = FieldInfo(alias="from")
+ """The caller address."""
+
+ status: Literal["queued"]
+ """The initial status of the outbound call."""
+
+ to: str
+ """The called address."""
diff --git a/src/telnyx/types/texml_initiate_ai_call_params.py b/src/telnyx/types/texml_initiate_ai_call_params.py
index 3adfaa199..a58b03d0e 100644
--- a/src/telnyx/types/texml_initiate_ai_call_params.py
+++ b/src/telnyx/types/texml_initiate_ai_call_params.py
@@ -91,6 +91,27 @@ class TexmlInitiateAICallParams(TypedDict, total=False):
]
"""Enables Answering Machine Detection."""
+ machine_detection_beep_max_frequency: Annotated[int, PropertyInfo(alias="MachineDetectionBeepMaxFrequency")]
+ """Highest frequency, in Hz, that a tone can reach and still be treated as a beep.
+
+ Only used when MachineDetection is enabled.
+ """
+
+ machine_detection_beep_min_frequency: Annotated[int, PropertyInfo(alias="MachineDetectionBeepMinFrequency")]
+ """Lowest frequency, in Hz, that a tone must reach to be treated as a beep.
+
+ Raising it above 480 excludes North American ringback (440 + 480 Hz), which can
+ otherwise be reported as a beep when the `freq_only` profile is in use. Only
+ used when MachineDetection is enabled.
+ """
+
+ machine_detection_beep_min_tone_duration: Annotated[int, PropertyInfo(alias="MachineDetectionBeepMinToneDuration")]
+ """Shortest tone, in milliseconds, that can be treated as a beep.
+
+ Raising it rejects brief tones such as call-progress blips. Only used when
+ MachineDetection is enabled.
+ """
+
machine_detection_beep_profile: Annotated[
Literal["both", "freq_only"], PropertyInfo(alias="MachineDetectionBeepProfile")
]
@@ -101,6 +122,37 @@ class TexmlInitiateAICallParams(TypedDict, total=False):
default profile. Only used when MachineDetection is enabled.
"""
+ machine_detection_beep_spectral_confirmation: Annotated[
+ bool, PropertyInfo(alias="MachineDetectionBeepSpectralConfirmation")
+ ]
+ """
+ When enabled, a candidate beep must pass an additional spectral check before it
+ is reported. Only used when MachineDetection is enabled.
+ """
+
+ machine_detection_beep_spectral_min_purity: Annotated[
+ float, PropertyInfo(alias="MachineDetectionBeepSpectralMinPurity")
+ ]
+ """Minimum spectral purity, from 0 to 1, for a tone to be treated as a beep.
+
+ Raising it rejects mixed tones such as ringback, which combines two frequencies.
+ Only used when MachineDetection is enabled.
+ """
+
+ machine_detection_beep_spectral_reject_fax_cng: Annotated[
+ bool, PropertyInfo(alias="MachineDetectionBeepSpectralRejectFaxCng")
+ ]
+ """When enabled, the fax CNG tone is rejected rather than reported as a beep.
+
+ Only used when MachineDetection is enabled.
+ """
+
+ machine_detection_beep_spectral_window: Annotated[int, PropertyInfo(alias="MachineDetectionBeepSpectralWindow")]
+ """Length of the spectral confirmation window, in milliseconds.
+
+ Only used when MachineDetection is enabled.
+ """
+
machine_detection_prompt_end_timeout: Annotated[int, PropertyInfo(alias="MachineDetectionPromptEndTimeout")]
"""
Silence duration threshold after a call screening prompt before ending prompt
diff --git a/src/telnyx/types/voice_clone_create_from_upload_params.py b/src/telnyx/types/voice_clone_create_from_upload_params.py
index 4b89a8cff..b7643422b 100644
--- a/src/telnyx/types/voice_clone_create_from_upload_params.py
+++ b/src/telnyx/types/voice_clone_create_from_upload_params.py
@@ -62,7 +62,7 @@ class VoiceCloneUploadRequestTelnyxUltraClone(TypedDict, total=False):
audio_file: Required[FileTypes]
"""Audio file to clone the voice from.
- Supported formats: WAV, MP3, FLAC, OGG, M4A. For best quality, provide 5–10
+ Supported formats: WAV, MP3, FLAC, OGG, M4A. For best quality, provide up to 60
seconds of clear, uninterrupted speech. Maximum size: 5MB.
"""
diff --git a/tests/api_resources/ai/assistants/test_versions.py b/tests/api_resources/ai/assistants/test_versions.py
index 76f1f978b..a101b32ee 100644
--- a/tests/api_resources/ai/assistants/test_versions.py
+++ b/tests/api_resources/ai/assistants/test_versions.py
@@ -320,6 +320,7 @@ def test_method_update_with_all_params(self, client: Telnyx) -> None:
interruption_settings={
"disable_greeting_interruption": True,
"enable": True,
+ "interrupt_prediction_threshold": 0,
"start_speaking_plan": {
"transcription_endpointing_plan": {
"on_no_punctuation_seconds": 0,
@@ -354,16 +355,22 @@ def test_method_update_with_all_params(self, client: Telnyx) -> None:
"status": "enabled",
},
post_conversation_settings={"enabled": True},
- privacy_settings={"data_retention": True},
+ privacy_settings={
+ "data_retention": True,
+ "in_transit_data_locality": True,
+ },
tags=["string"],
telephony_settings={
"default_texml_app_id": "default_texml_app_id",
"disable_dtmf": True,
"fallback_destination": "fallback_destination",
- "noise_suppression": "krisp",
+ "noise_suppression": "aicoustics",
"noise_suppression_config": {
"attenuation_limit": 0,
+ "enhancement_level": 0,
+ "family": "quail",
"mode": "advanced",
+ "size": "vf",
},
"recording_settings": {
"channels": "single",
@@ -390,66 +397,12 @@ def test_method_update_with_all_params(self, client: Telnyx) -> None:
tool_ids=["string"],
tools=[
{
- "type": "webhook",
- "webhook": {
- "description": "description",
+ "function": {
"name": "name",
- "url": "https://example.com/api/v1/function",
- "async": True,
- "async_timeout_ms": 1,
- "body_parameters": {
- "properties": {
- "age": "bar",
- "location": "bar",
- },
- "required": ["age", "location"],
- "type": "object",
- },
- "headers": [
- {
- "name": "name",
- "value": "value",
- }
- ],
- "messages": [
- {
- "content": "Let me look that up for you.",
- "type": "request_start",
- "timing_ms": 100,
- },
- {
- "content": "Still working on that.",
- "timing_ms": 5000,
- "type": "request_response_delayed",
- },
- ],
- "method": "GET",
- "path_parameters": {
- "properties": {"id": "bar"},
- "required": ["id"],
- "type": "object",
- },
- "preset_body_fields": {
- "account_id": "bar",
- "source": "bar",
- },
- "preset_query_params": {
- "caller": "bar",
- "channel": "bar",
- },
- "query_parameters": {
- "properties": {"page": "bar"},
- "required": ["page"],
- "type": "object",
- },
- "store_fields_as_variables": [
- {
- "name": "x",
- "value_path": "x",
- }
- ],
- "timeout_ms": 500,
+ "description": "description",
+ "parameters": {"foo": "bar"},
},
+ "type": "function",
}
],
transcription={
@@ -1006,6 +959,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncTelnyx) ->
interruption_settings={
"disable_greeting_interruption": True,
"enable": True,
+ "interrupt_prediction_threshold": 0,
"start_speaking_plan": {
"transcription_endpointing_plan": {
"on_no_punctuation_seconds": 0,
@@ -1040,16 +994,22 @@ async def test_method_update_with_all_params(self, async_client: AsyncTelnyx) ->
"status": "enabled",
},
post_conversation_settings={"enabled": True},
- privacy_settings={"data_retention": True},
+ privacy_settings={
+ "data_retention": True,
+ "in_transit_data_locality": True,
+ },
tags=["string"],
telephony_settings={
"default_texml_app_id": "default_texml_app_id",
"disable_dtmf": True,
"fallback_destination": "fallback_destination",
- "noise_suppression": "krisp",
+ "noise_suppression": "aicoustics",
"noise_suppression_config": {
"attenuation_limit": 0,
+ "enhancement_level": 0,
+ "family": "quail",
"mode": "advanced",
+ "size": "vf",
},
"recording_settings": {
"channels": "single",
@@ -1076,66 +1036,12 @@ async def test_method_update_with_all_params(self, async_client: AsyncTelnyx) ->
tool_ids=["string"],
tools=[
{
- "type": "webhook",
- "webhook": {
- "description": "description",
+ "function": {
"name": "name",
- "url": "https://example.com/api/v1/function",
- "async": True,
- "async_timeout_ms": 1,
- "body_parameters": {
- "properties": {
- "age": "bar",
- "location": "bar",
- },
- "required": ["age", "location"],
- "type": "object",
- },
- "headers": [
- {
- "name": "name",
- "value": "value",
- }
- ],
- "messages": [
- {
- "content": "Let me look that up for you.",
- "type": "request_start",
- "timing_ms": 100,
- },
- {
- "content": "Still working on that.",
- "timing_ms": 5000,
- "type": "request_response_delayed",
- },
- ],
- "method": "GET",
- "path_parameters": {
- "properties": {"id": "bar"},
- "required": ["id"],
- "type": "object",
- },
- "preset_body_fields": {
- "account_id": "bar",
- "source": "bar",
- },
- "preset_query_params": {
- "caller": "bar",
- "channel": "bar",
- },
- "query_parameters": {
- "properties": {"page": "bar"},
- "required": ["page"],
- "type": "object",
- },
- "store_fields_as_variables": [
- {
- "name": "x",
- "value_path": "x",
- }
- ],
- "timeout_ms": 500,
+ "description": "description",
+ "parameters": {"foo": "bar"},
},
+ "type": "function",
}
],
transcription={
diff --git a/tests/api_resources/ai/test_assistants.py b/tests/api_resources/ai/test_assistants.py
index 4a7420ec0..025c2fc27 100644
--- a/tests/api_resources/ai/test_assistants.py
+++ b/tests/api_resources/ai/test_assistants.py
@@ -260,6 +260,7 @@ def test_method_create_with_all_params(self, client: Telnyx) -> None:
interruption_settings={
"disable_greeting_interruption": True,
"enable": True,
+ "interrupt_prediction_threshold": 0,
"start_speaking_plan": {
"transcription_endpointing_plan": {
"on_no_punctuation_seconds": 0,
@@ -293,16 +294,22 @@ def test_method_create_with_all_params(self, client: Telnyx) -> None:
"status": "enabled",
},
post_conversation_settings={"enabled": True},
- privacy_settings={"data_retention": True},
+ privacy_settings={
+ "data_retention": True,
+ "in_transit_data_locality": True,
+ },
tags=["string"],
telephony_settings={
"default_texml_app_id": "default_texml_app_id",
"disable_dtmf": True,
"fallback_destination": "fallback_destination",
- "noise_suppression": "krisp",
+ "noise_suppression": "aicoustics",
"noise_suppression_config": {
"attenuation_limit": 0,
+ "enhancement_level": 0,
+ "family": "quail",
"mode": "advanced",
+ "size": "vf",
},
"recording_settings": {
"channels": "single",
@@ -329,66 +336,12 @@ def test_method_create_with_all_params(self, client: Telnyx) -> None:
tool_ids=["string"],
tools=[
{
- "type": "webhook",
- "webhook": {
- "description": "description",
+ "function": {
"name": "name",
- "url": "https://example.com/api/v1/function",
- "async": True,
- "async_timeout_ms": 1,
- "body_parameters": {
- "properties": {
- "age": "bar",
- "location": "bar",
- },
- "required": ["age", "location"],
- "type": "object",
- },
- "headers": [
- {
- "name": "name",
- "value": "value",
- }
- ],
- "messages": [
- {
- "content": "Let me look that up for you.",
- "type": "request_start",
- "timing_ms": 100,
- },
- {
- "content": "Still working on that.",
- "timing_ms": 5000,
- "type": "request_response_delayed",
- },
- ],
- "method": "GET",
- "path_parameters": {
- "properties": {"id": "bar"},
- "required": ["id"],
- "type": "object",
- },
- "preset_body_fields": {
- "account_id": "bar",
- "source": "bar",
- },
- "preset_query_params": {
- "caller": "bar",
- "channel": "bar",
- },
- "query_parameters": {
- "properties": {"page": "bar"},
- "required": ["page"],
- "type": "object",
- },
- "store_fields_as_variables": [
- {
- "name": "x",
- "value_path": "x",
- }
- ],
- "timeout_ms": 500,
+ "description": "description",
+ "parameters": {"foo": "bar"},
},
+ "type": "function",
}
],
transcription={
@@ -768,6 +721,7 @@ def test_method_update_with_all_params(self, client: Telnyx) -> None:
interruption_settings={
"disable_greeting_interruption": True,
"enable": True,
+ "interrupt_prediction_threshold": 0,
"start_speaking_plan": {
"transcription_endpointing_plan": {
"on_no_punctuation_seconds": 0,
@@ -802,17 +756,23 @@ def test_method_update_with_all_params(self, client: Telnyx) -> None:
"status": "enabled",
},
post_conversation_settings={"enabled": True},
- privacy_settings={"data_retention": True},
+ privacy_settings={
+ "data_retention": True,
+ "in_transit_data_locality": True,
+ },
promote_to_main=True,
tags=["string"],
telephony_settings={
"default_texml_app_id": "default_texml_app_id",
"disable_dtmf": True,
"fallback_destination": "fallback_destination",
- "noise_suppression": "krisp",
+ "noise_suppression": "aicoustics",
"noise_suppression_config": {
"attenuation_limit": 0,
+ "enhancement_level": 0,
+ "family": "quail",
"mode": "advanced",
+ "size": "vf",
},
"recording_settings": {
"channels": "single",
@@ -839,66 +799,12 @@ def test_method_update_with_all_params(self, client: Telnyx) -> None:
tool_ids=["string"],
tools=[
{
- "type": "webhook",
- "webhook": {
- "description": "description",
+ "function": {
"name": "name",
- "url": "https://example.com/api/v1/function",
- "async": True,
- "async_timeout_ms": 1,
- "body_parameters": {
- "properties": {
- "age": "bar",
- "location": "bar",
- },
- "required": ["age", "location"],
- "type": "object",
- },
- "headers": [
- {
- "name": "name",
- "value": "value",
- }
- ],
- "messages": [
- {
- "content": "Let me look that up for you.",
- "type": "request_start",
- "timing_ms": 100,
- },
- {
- "content": "Still working on that.",
- "timing_ms": 5000,
- "type": "request_response_delayed",
- },
- ],
- "method": "GET",
- "path_parameters": {
- "properties": {"id": "bar"},
- "required": ["id"],
- "type": "object",
- },
- "preset_body_fields": {
- "account_id": "bar",
- "source": "bar",
- },
- "preset_query_params": {
- "caller": "bar",
- "channel": "bar",
- },
- "query_parameters": {
- "properties": {"page": "bar"},
- "required": ["page"],
- "type": "object",
- },
- "store_fields_as_variables": [
- {
- "name": "x",
- "value_path": "x",
- }
- ],
- "timeout_ms": 500,
+ "description": "description",
+ "parameters": {"foo": "bar"},
},
+ "type": "function",
}
],
transcription={
@@ -1574,6 +1480,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncTelnyx) ->
interruption_settings={
"disable_greeting_interruption": True,
"enable": True,
+ "interrupt_prediction_threshold": 0,
"start_speaking_plan": {
"transcription_endpointing_plan": {
"on_no_punctuation_seconds": 0,
@@ -1607,16 +1514,22 @@ async def test_method_create_with_all_params(self, async_client: AsyncTelnyx) ->
"status": "enabled",
},
post_conversation_settings={"enabled": True},
- privacy_settings={"data_retention": True},
+ privacy_settings={
+ "data_retention": True,
+ "in_transit_data_locality": True,
+ },
tags=["string"],
telephony_settings={
"default_texml_app_id": "default_texml_app_id",
"disable_dtmf": True,
"fallback_destination": "fallback_destination",
- "noise_suppression": "krisp",
+ "noise_suppression": "aicoustics",
"noise_suppression_config": {
"attenuation_limit": 0,
+ "enhancement_level": 0,
+ "family": "quail",
"mode": "advanced",
+ "size": "vf",
},
"recording_settings": {
"channels": "single",
@@ -1643,66 +1556,12 @@ async def test_method_create_with_all_params(self, async_client: AsyncTelnyx) ->
tool_ids=["string"],
tools=[
{
- "type": "webhook",
- "webhook": {
- "description": "description",
+ "function": {
"name": "name",
- "url": "https://example.com/api/v1/function",
- "async": True,
- "async_timeout_ms": 1,
- "body_parameters": {
- "properties": {
- "age": "bar",
- "location": "bar",
- },
- "required": ["age", "location"],
- "type": "object",
- },
- "headers": [
- {
- "name": "name",
- "value": "value",
- }
- ],
- "messages": [
- {
- "content": "Let me look that up for you.",
- "type": "request_start",
- "timing_ms": 100,
- },
- {
- "content": "Still working on that.",
- "timing_ms": 5000,
- "type": "request_response_delayed",
- },
- ],
- "method": "GET",
- "path_parameters": {
- "properties": {"id": "bar"},
- "required": ["id"],
- "type": "object",
- },
- "preset_body_fields": {
- "account_id": "bar",
- "source": "bar",
- },
- "preset_query_params": {
- "caller": "bar",
- "channel": "bar",
- },
- "query_parameters": {
- "properties": {"page": "bar"},
- "required": ["page"],
- "type": "object",
- },
- "store_fields_as_variables": [
- {
- "name": "x",
- "value_path": "x",
- }
- ],
- "timeout_ms": 500,
+ "description": "description",
+ "parameters": {"foo": "bar"},
},
+ "type": "function",
}
],
transcription={
@@ -2082,6 +1941,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncTelnyx) ->
interruption_settings={
"disable_greeting_interruption": True,
"enable": True,
+ "interrupt_prediction_threshold": 0,
"start_speaking_plan": {
"transcription_endpointing_plan": {
"on_no_punctuation_seconds": 0,
@@ -2116,17 +1976,23 @@ async def test_method_update_with_all_params(self, async_client: AsyncTelnyx) ->
"status": "enabled",
},
post_conversation_settings={"enabled": True},
- privacy_settings={"data_retention": True},
+ privacy_settings={
+ "data_retention": True,
+ "in_transit_data_locality": True,
+ },
promote_to_main=True,
tags=["string"],
telephony_settings={
"default_texml_app_id": "default_texml_app_id",
"disable_dtmf": True,
"fallback_destination": "fallback_destination",
- "noise_suppression": "krisp",
+ "noise_suppression": "aicoustics",
"noise_suppression_config": {
"attenuation_limit": 0,
+ "enhancement_level": 0,
+ "family": "quail",
"mode": "advanced",
+ "size": "vf",
},
"recording_settings": {
"channels": "single",
@@ -2153,66 +2019,12 @@ async def test_method_update_with_all_params(self, async_client: AsyncTelnyx) ->
tool_ids=["string"],
tools=[
{
- "type": "webhook",
- "webhook": {
- "description": "description",
+ "function": {
"name": "name",
- "url": "https://example.com/api/v1/function",
- "async": True,
- "async_timeout_ms": 1,
- "body_parameters": {
- "properties": {
- "age": "bar",
- "location": "bar",
- },
- "required": ["age", "location"],
- "type": "object",
- },
- "headers": [
- {
- "name": "name",
- "value": "value",
- }
- ],
- "messages": [
- {
- "content": "Let me look that up for you.",
- "type": "request_start",
- "timing_ms": 100,
- },
- {
- "content": "Still working on that.",
- "timing_ms": 5000,
- "type": "request_response_delayed",
- },
- ],
- "method": "GET",
- "path_parameters": {
- "properties": {"id": "bar"},
- "required": ["id"],
- "type": "object",
- },
- "preset_body_fields": {
- "account_id": "bar",
- "source": "bar",
- },
- "preset_query_params": {
- "caller": "bar",
- "channel": "bar",
- },
- "query_parameters": {
- "properties": {"page": "bar"},
- "required": ["page"],
- "type": "object",
- },
- "store_fields_as_variables": [
- {
- "name": "x",
- "value_path": "x",
- }
- ],
- "timeout_ms": 500,
+ "description": "description",
+ "parameters": {"foo": "bar"},
},
+ "type": "function",
}
],
transcription={
diff --git a/tests/api_resources/ai/typesafe/__init__.py b/tests/api_resources/ai/typesafe/__init__.py
new file mode 100644
index 000000000..fd8019a9a
--- /dev/null
+++ b/tests/api_resources/ai/typesafe/__init__.py
@@ -0,0 +1 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
diff --git a/tests/api_resources/ai/typesafe/test_v1.py b/tests/api_resources/ai/typesafe/test_v1.py
new file mode 100644
index 000000000..45c5d81b0
--- /dev/null
+++ b/tests/api_resources/ai/typesafe/test_v1.py
@@ -0,0 +1,212 @@
+# 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.ai.typesafe import V1SystemoneResponse
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestV1:
+ 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_systemone(self, client: Telnyx) -> None:
+ v1 = client.ai.typesafe.v1.systemone(
+ questions={
+ "team": {
+ "criteria": {
+ "billing": "Payments and refunds",
+ "technical_support": "Service faults and technical problems",
+ "sales": "New purchases",
+ },
+ "instructions": "Choose the team that should handle this incident.",
+ "type": "choice",
+ },
+ "production_incident": {
+ "instructions": "Does the message describe an active production incident?",
+ "type": "noul",
+ },
+ "urgency": {
+ "criteria": ["Low", "Normal", "High", "Critical"],
+ "instructions": "Rate operational urgency.",
+ "type": "score",
+ },
+ },
+ state="Our production calls are failing. Every customer is affected.",
+ )
+ assert_matches_type(V1SystemoneResponse, v1, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_systemone(self, client: Telnyx) -> None:
+ response = client.ai.typesafe.v1.with_raw_response.systemone(
+ questions={
+ "team": {
+ "criteria": {
+ "billing": "Payments and refunds",
+ "technical_support": "Service faults and technical problems",
+ "sales": "New purchases",
+ },
+ "instructions": "Choose the team that should handle this incident.",
+ "type": "choice",
+ },
+ "production_incident": {
+ "instructions": "Does the message describe an active production incident?",
+ "type": "noul",
+ },
+ "urgency": {
+ "criteria": ["Low", "Normal", "High", "Critical"],
+ "instructions": "Rate operational urgency.",
+ "type": "score",
+ },
+ },
+ state="Our production calls are failing. Every customer is affected.",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ v1 = response.parse()
+ assert_matches_type(V1SystemoneResponse, v1, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_systemone(self, client: Telnyx) -> None:
+ with client.ai.typesafe.v1.with_streaming_response.systemone(
+ questions={
+ "team": {
+ "criteria": {
+ "billing": "Payments and refunds",
+ "technical_support": "Service faults and technical problems",
+ "sales": "New purchases",
+ },
+ "instructions": "Choose the team that should handle this incident.",
+ "type": "choice",
+ },
+ "production_incident": {
+ "instructions": "Does the message describe an active production incident?",
+ "type": "noul",
+ },
+ "urgency": {
+ "criteria": ["Low", "Normal", "High", "Critical"],
+ "instructions": "Rate operational urgency.",
+ "type": "score",
+ },
+ },
+ state="Our production calls are failing. Every customer is affected.",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ v1 = response.parse()
+ assert_matches_type(V1SystemoneResponse, v1, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+
+class TestAsyncV1:
+ 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_systemone(self, async_client: AsyncTelnyx) -> None:
+ v1 = await async_client.ai.typesafe.v1.systemone(
+ questions={
+ "team": {
+ "criteria": {
+ "billing": "Payments and refunds",
+ "technical_support": "Service faults and technical problems",
+ "sales": "New purchases",
+ },
+ "instructions": "Choose the team that should handle this incident.",
+ "type": "choice",
+ },
+ "production_incident": {
+ "instructions": "Does the message describe an active production incident?",
+ "type": "noul",
+ },
+ "urgency": {
+ "criteria": ["Low", "Normal", "High", "Critical"],
+ "instructions": "Rate operational urgency.",
+ "type": "score",
+ },
+ },
+ state="Our production calls are failing. Every customer is affected.",
+ )
+ assert_matches_type(V1SystemoneResponse, v1, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_systemone(self, async_client: AsyncTelnyx) -> None:
+ response = await async_client.ai.typesafe.v1.with_raw_response.systemone(
+ questions={
+ "team": {
+ "criteria": {
+ "billing": "Payments and refunds",
+ "technical_support": "Service faults and technical problems",
+ "sales": "New purchases",
+ },
+ "instructions": "Choose the team that should handle this incident.",
+ "type": "choice",
+ },
+ "production_incident": {
+ "instructions": "Does the message describe an active production incident?",
+ "type": "noul",
+ },
+ "urgency": {
+ "criteria": ["Low", "Normal", "High", "Critical"],
+ "instructions": "Rate operational urgency.",
+ "type": "score",
+ },
+ },
+ state="Our production calls are failing. Every customer is affected.",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ v1 = await response.parse()
+ assert_matches_type(V1SystemoneResponse, v1, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_systemone(self, async_client: AsyncTelnyx) -> None:
+ async with async_client.ai.typesafe.v1.with_streaming_response.systemone(
+ questions={
+ "team": {
+ "criteria": {
+ "billing": "Payments and refunds",
+ "technical_support": "Service faults and technical problems",
+ "sales": "New purchases",
+ },
+ "instructions": "Choose the team that should handle this incident.",
+ "type": "choice",
+ },
+ "production_incident": {
+ "instructions": "Does the message describe an active production incident?",
+ "type": "noul",
+ },
+ "urgency": {
+ "criteria": ["Low", "Normal", "High", "Critical"],
+ "instructions": "Rate operational urgency.",
+ "type": "score",
+ },
+ },
+ state="Our production calls are failing. Every customer is affected.",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ v1 = await response.parse()
+ assert_matches_type(V1SystemoneResponse, v1, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/calls/test_actions.py b/tests/api_resources/calls/test_actions.py
index 1c6953009..238271476 100644
--- a/tests/api_resources/calls/test_actions.py
+++ b/tests/api_resources/calls/test_actions.py
@@ -2837,6 +2837,13 @@ def test_method_transfer_with_all_params(self, client: Telnyx) -> None:
answering_machine_detection_config={
"after_greeting_silence_millis": 1000,
"beep_detection_profile": "freq_only",
+ "beep_max_frequency_hz": 2000,
+ "beep_min_frequency_hz": 550,
+ "beep_min_tone_duration_millis": 300,
+ "beep_spectral_confirmation": True,
+ "beep_spectral_min_purity": 0.8,
+ "beep_spectral_reject_fax_cng": True,
+ "beep_spectral_window_millis": 100,
"between_words_silence_millis": 1000,
"greeting_duration_millis": 1000,
"greeting_silence_duration_millis": 2000,
@@ -5777,6 +5784,13 @@ async def test_method_transfer_with_all_params(self, async_client: AsyncTelnyx)
answering_machine_detection_config={
"after_greeting_silence_millis": 1000,
"beep_detection_profile": "freq_only",
+ "beep_max_frequency_hz": 2000,
+ "beep_min_frequency_hz": 550,
+ "beep_min_tone_duration_millis": 300,
+ "beep_spectral_confirmation": True,
+ "beep_spectral_min_purity": 0.8,
+ "beep_spectral_reject_fax_cng": True,
+ "beep_spectral_window_millis": 100,
"between_words_silence_millis": 1000,
"greeting_duration_millis": 1000,
"greeting_silence_duration_millis": 2000,
diff --git a/tests/api_resources/compute/funcs/__init__.py b/tests/api_resources/compute/funcs/__init__.py
new file mode 100644
index 000000000..fd8019a9a
--- /dev/null
+++ b/tests/api_resources/compute/funcs/__init__.py
@@ -0,0 +1 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
diff --git a/tests/api_resources/compute/funcs/test_export.py b/tests/api_resources/compute/funcs/test_export.py
new file mode 100644
index 000000000..132a218a7
--- /dev/null
+++ b/tests/api_resources/compute/funcs/test_export.py
@@ -0,0 +1,308 @@
+# 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.compute.funcs import FuncLogExportConfigResponse
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestExport:
+ 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:
+ export = client.compute.funcs.export.create(
+ id="id",
+ endpoint="https://api.honeycomb.io/v1/logs",
+ headers={"x-honeycomb-team": "abc123"},
+ invocation_export_enabled=True,
+ runtime_export_enabled=True,
+ )
+ assert_matches_type(FuncLogExportConfigResponse, export, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_create(self, client: Telnyx) -> None:
+ response = client.compute.funcs.export.with_raw_response.create(
+ id="id",
+ endpoint="https://api.honeycomb.io/v1/logs",
+ headers={"x-honeycomb-team": "abc123"},
+ invocation_export_enabled=True,
+ runtime_export_enabled=True,
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ export = response.parse()
+ assert_matches_type(FuncLogExportConfigResponse, export, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_create(self, client: Telnyx) -> None:
+ with client.compute.funcs.export.with_streaming_response.create(
+ id="id",
+ endpoint="https://api.honeycomb.io/v1/logs",
+ headers={"x-honeycomb-team": "abc123"},
+ invocation_export_enabled=True,
+ runtime_export_enabled=True,
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ export = response.parse()
+ assert_matches_type(FuncLogExportConfigResponse, export, 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 `id` but received ''"):
+ client.compute.funcs.export.with_raw_response.create(
+ id="",
+ endpoint="https://api.honeycomb.io/v1/logs",
+ headers={"x-honeycomb-team": "abc123"},
+ invocation_export_enabled=True,
+ runtime_export_enabled=True,
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_list(self, client: Telnyx) -> None:
+ export = client.compute.funcs.export.list(
+ "id",
+ )
+ assert_matches_type(FuncLogExportConfigResponse, export, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_list(self, client: Telnyx) -> None:
+ response = client.compute.funcs.export.with_raw_response.list(
+ "id",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ export = response.parse()
+ assert_matches_type(FuncLogExportConfigResponse, export, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_list(self, client: Telnyx) -> None:
+ with client.compute.funcs.export.with_streaming_response.list(
+ "id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ export = response.parse()
+ assert_matches_type(FuncLogExportConfigResponse, export, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_path_params_list(self, client: Telnyx) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ client.compute.funcs.export.with_raw_response.list(
+ "",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_delete_all(self, client: Telnyx) -> None:
+ export = client.compute.funcs.export.delete_all(
+ "id",
+ )
+ assert export is None
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_delete_all(self, client: Telnyx) -> None:
+ response = client.compute.funcs.export.with_raw_response.delete_all(
+ "id",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ export = response.parse()
+ assert export is None
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_delete_all(self, client: Telnyx) -> None:
+ with client.compute.funcs.export.with_streaming_response.delete_all(
+ "id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ export = response.parse()
+ assert export 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_all(self, client: Telnyx) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ client.compute.funcs.export.with_raw_response.delete_all(
+ "",
+ )
+
+
+class TestAsyncExport:
+ 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:
+ export = await async_client.compute.funcs.export.create(
+ id="id",
+ endpoint="https://api.honeycomb.io/v1/logs",
+ headers={"x-honeycomb-team": "abc123"},
+ invocation_export_enabled=True,
+ runtime_export_enabled=True,
+ )
+ assert_matches_type(FuncLogExportConfigResponse, export, 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.compute.funcs.export.with_raw_response.create(
+ id="id",
+ endpoint="https://api.honeycomb.io/v1/logs",
+ headers={"x-honeycomb-team": "abc123"},
+ invocation_export_enabled=True,
+ runtime_export_enabled=True,
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ export = await response.parse()
+ assert_matches_type(FuncLogExportConfigResponse, export, 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.compute.funcs.export.with_streaming_response.create(
+ id="id",
+ endpoint="https://api.honeycomb.io/v1/logs",
+ headers={"x-honeycomb-team": "abc123"},
+ invocation_export_enabled=True,
+ runtime_export_enabled=True,
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ export = await response.parse()
+ assert_matches_type(FuncLogExportConfigResponse, export, 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 `id` but received ''"):
+ await async_client.compute.funcs.export.with_raw_response.create(
+ id="",
+ endpoint="https://api.honeycomb.io/v1/logs",
+ headers={"x-honeycomb-team": "abc123"},
+ invocation_export_enabled=True,
+ runtime_export_enabled=True,
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_list(self, async_client: AsyncTelnyx) -> None:
+ export = await async_client.compute.funcs.export.list(
+ "id",
+ )
+ assert_matches_type(FuncLogExportConfigResponse, export, 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.compute.funcs.export.with_raw_response.list(
+ "id",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ export = await response.parse()
+ assert_matches_type(FuncLogExportConfigResponse, export, 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.compute.funcs.export.with_streaming_response.list(
+ "id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ export = await response.parse()
+ assert_matches_type(FuncLogExportConfigResponse, export, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_path_params_list(self, async_client: AsyncTelnyx) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ await async_client.compute.funcs.export.with_raw_response.list(
+ "",
+ )
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_delete_all(self, async_client: AsyncTelnyx) -> None:
+ export = await async_client.compute.funcs.export.delete_all(
+ "id",
+ )
+ assert export is None
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_delete_all(self, async_client: AsyncTelnyx) -> None:
+ response = await async_client.compute.funcs.export.with_raw_response.delete_all(
+ "id",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ export = await response.parse()
+ assert export is None
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_delete_all(self, async_client: AsyncTelnyx) -> None:
+ async with async_client.compute.funcs.export.with_streaming_response.delete_all(
+ "id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ export = await response.parse()
+ assert export 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_all(self, async_client: AsyncTelnyx) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"):
+ await async_client.compute.funcs.export.with_raw_response.delete_all(
+ "",
+ )
diff --git a/tests/api_resources/test_bot_challenge.py b/tests/api_resources/test_bot_challenge.py
new file mode 100644
index 000000000..0f3f7c5e4
--- /dev/null
+++ b/tests/api_resources/test_bot_challenge.py
@@ -0,0 +1,100 @@
+# 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 BotChallengeCreateResponse
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestBotChallenge:
+ 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:
+ bot_challenge = client.bot_challenge.create()
+ assert_matches_type(BotChallengeCreateResponse, bot_challenge, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_create_with_all_params(self, client: Telnyx) -> None:
+ bot_challenge = client.bot_challenge.create(
+ llm_model_name="claude-opus-4",
+ llm_parameter_count="175B",
+ llm_quantization="int8",
+ )
+ assert_matches_type(BotChallengeCreateResponse, bot_challenge, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_create(self, client: Telnyx) -> None:
+ response = client.bot_challenge.with_raw_response.create()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ bot_challenge = response.parse()
+ assert_matches_type(BotChallengeCreateResponse, bot_challenge, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_create(self, client: Telnyx) -> None:
+ with client.bot_challenge.with_streaming_response.create() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ bot_challenge = response.parse()
+ assert_matches_type(BotChallengeCreateResponse, bot_challenge, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+
+class TestAsyncBotChallenge:
+ 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:
+ bot_challenge = await async_client.bot_challenge.create()
+ assert_matches_type(BotChallengeCreateResponse, bot_challenge, 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:
+ bot_challenge = await async_client.bot_challenge.create(
+ llm_model_name="claude-opus-4",
+ llm_parameter_count="175B",
+ llm_quantization="int8",
+ )
+ assert_matches_type(BotChallengeCreateResponse, bot_challenge, 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.bot_challenge.with_raw_response.create()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ bot_challenge = await response.parse()
+ assert_matches_type(BotChallengeCreateResponse, bot_challenge, 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.bot_challenge.with_streaming_response.create() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ bot_challenge = await response.parse()
+ assert_matches_type(BotChallengeCreateResponse, bot_challenge, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/test_bot_sessions.py b/tests/api_resources/test_bot_sessions.py
new file mode 100644
index 000000000..61c4e03d5
--- /dev/null
+++ b/tests/api_resources/test_bot_sessions.py
@@ -0,0 +1,98 @@
+# 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 BotSessionListResponse
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestBotSessions:
+ 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:
+ bot_session = client.bot_sessions.list(
+ email="agent-owner@example.com",
+ portal_redirect_token="01890a7e-e2f7-7c3d-8dbb-9a2c5f3d1e0b",
+ )
+ assert_matches_type(BotSessionListResponse, bot_session, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_list(self, client: Telnyx) -> None:
+ response = client.bot_sessions.with_raw_response.list(
+ email="agent-owner@example.com",
+ portal_redirect_token="01890a7e-e2f7-7c3d-8dbb-9a2c5f3d1e0b",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ bot_session = response.parse()
+ assert_matches_type(BotSessionListResponse, bot_session, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_list(self, client: Telnyx) -> None:
+ with client.bot_sessions.with_streaming_response.list(
+ email="agent-owner@example.com",
+ portal_redirect_token="01890a7e-e2f7-7c3d-8dbb-9a2c5f3d1e0b",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ bot_session = response.parse()
+ assert_matches_type(BotSessionListResponse, bot_session, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+
+class TestAsyncBotSessions:
+ 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:
+ bot_session = await async_client.bot_sessions.list(
+ email="agent-owner@example.com",
+ portal_redirect_token="01890a7e-e2f7-7c3d-8dbb-9a2c5f3d1e0b",
+ )
+ assert_matches_type(BotSessionListResponse, bot_session, 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.bot_sessions.with_raw_response.list(
+ email="agent-owner@example.com",
+ portal_redirect_token="01890a7e-e2f7-7c3d-8dbb-9a2c5f3d1e0b",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ bot_session = await response.parse()
+ assert_matches_type(BotSessionListResponse, bot_session, 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.bot_sessions.with_streaming_response.list(
+ email="agent-owner@example.com",
+ portal_redirect_token="01890a7e-e2f7-7c3d-8dbb-9a2c5f3d1e0b",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ bot_session = await response.parse()
+ assert_matches_type(BotSessionListResponse, bot_session, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/test_bot_signup.py b/tests/api_resources/test_bot_signup.py
new file mode 100644
index 000000000..5009c1d4b
--- /dev/null
+++ b/tests/api_resources/test_bot_signup.py
@@ -0,0 +1,214 @@
+# 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 SuccessResponse
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestBotSignup:
+ 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:
+ bot_signup = client.bot_signup.create(
+ bot_challenge_answer="35",
+ bot_challenge_nonce="c6feda4e-6501-4db9-a21f-665e5b4ce2ba",
+ privacy_policy_url="https://telnyx.com/privacy-policy",
+ terms_and_conditions_url="https://telnyx.com/terms-and-conditions-of-service",
+ terms_of_service=True,
+ )
+ assert_matches_type(SuccessResponse, bot_signup, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_create_with_all_params(self, client: Telnyx) -> None:
+ bot_signup = client.bot_signup.create(
+ bot_challenge_answer="35",
+ bot_challenge_nonce="c6feda4e-6501-4db9-a21f-665e5b4ce2ba",
+ privacy_policy_url="https://telnyx.com/privacy-policy",
+ terms_and_conditions_url="https://telnyx.com/terms-and-conditions-of-service",
+ terms_of_service=True,
+ email="agent-owner@example.com",
+ terms_and_conditions_eu_url="https://telnyx.com/terms-and-conditions-of-service-eu",
+ terms_of_service_eu=True,
+ )
+ assert_matches_type(SuccessResponse, bot_signup, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_create(self, client: Telnyx) -> None:
+ response = client.bot_signup.with_raw_response.create(
+ bot_challenge_answer="35",
+ bot_challenge_nonce="c6feda4e-6501-4db9-a21f-665e5b4ce2ba",
+ privacy_policy_url="https://telnyx.com/privacy-policy",
+ terms_and_conditions_url="https://telnyx.com/terms-and-conditions-of-service",
+ terms_of_service=True,
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ bot_signup = response.parse()
+ assert_matches_type(SuccessResponse, bot_signup, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_create(self, client: Telnyx) -> None:
+ with client.bot_signup.with_streaming_response.create(
+ bot_challenge_answer="35",
+ bot_challenge_nonce="c6feda4e-6501-4db9-a21f-665e5b4ce2ba",
+ privacy_policy_url="https://telnyx.com/privacy-policy",
+ terms_and_conditions_url="https://telnyx.com/terms-and-conditions-of-service",
+ terms_of_service=True,
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ bot_signup = response.parse()
+ assert_matches_type(SuccessResponse, bot_signup, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_resend_magic_link(self, client: Telnyx) -> None:
+ bot_signup = client.bot_signup.resend_magic_link(
+ email="agent-owner@example.com",
+ )
+ assert_matches_type(SuccessResponse, bot_signup, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_resend_magic_link(self, client: Telnyx) -> None:
+ response = client.bot_signup.with_raw_response.resend_magic_link(
+ email="agent-owner@example.com",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ bot_signup = response.parse()
+ assert_matches_type(SuccessResponse, bot_signup, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_resend_magic_link(self, client: Telnyx) -> None:
+ with client.bot_signup.with_streaming_response.resend_magic_link(
+ email="agent-owner@example.com",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ bot_signup = response.parse()
+ assert_matches_type(SuccessResponse, bot_signup, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+
+class TestAsyncBotSignup:
+ 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:
+ bot_signup = await async_client.bot_signup.create(
+ bot_challenge_answer="35",
+ bot_challenge_nonce="c6feda4e-6501-4db9-a21f-665e5b4ce2ba",
+ privacy_policy_url="https://telnyx.com/privacy-policy",
+ terms_and_conditions_url="https://telnyx.com/terms-and-conditions-of-service",
+ terms_of_service=True,
+ )
+ assert_matches_type(SuccessResponse, bot_signup, 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:
+ bot_signup = await async_client.bot_signup.create(
+ bot_challenge_answer="35",
+ bot_challenge_nonce="c6feda4e-6501-4db9-a21f-665e5b4ce2ba",
+ privacy_policy_url="https://telnyx.com/privacy-policy",
+ terms_and_conditions_url="https://telnyx.com/terms-and-conditions-of-service",
+ terms_of_service=True,
+ email="agent-owner@example.com",
+ terms_and_conditions_eu_url="https://telnyx.com/terms-and-conditions-of-service-eu",
+ terms_of_service_eu=True,
+ )
+ assert_matches_type(SuccessResponse, bot_signup, 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.bot_signup.with_raw_response.create(
+ bot_challenge_answer="35",
+ bot_challenge_nonce="c6feda4e-6501-4db9-a21f-665e5b4ce2ba",
+ privacy_policy_url="https://telnyx.com/privacy-policy",
+ terms_and_conditions_url="https://telnyx.com/terms-and-conditions-of-service",
+ terms_of_service=True,
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ bot_signup = await response.parse()
+ assert_matches_type(SuccessResponse, bot_signup, 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.bot_signup.with_streaming_response.create(
+ bot_challenge_answer="35",
+ bot_challenge_nonce="c6feda4e-6501-4db9-a21f-665e5b4ce2ba",
+ privacy_policy_url="https://telnyx.com/privacy-policy",
+ terms_and_conditions_url="https://telnyx.com/terms-and-conditions-of-service",
+ terms_of_service=True,
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ bot_signup = await response.parse()
+ assert_matches_type(SuccessResponse, bot_signup, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_resend_magic_link(self, async_client: AsyncTelnyx) -> None:
+ bot_signup = await async_client.bot_signup.resend_magic_link(
+ email="agent-owner@example.com",
+ )
+ assert_matches_type(SuccessResponse, bot_signup, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_resend_magic_link(self, async_client: AsyncTelnyx) -> None:
+ response = await async_client.bot_signup.with_raw_response.resend_magic_link(
+ email="agent-owner@example.com",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ bot_signup = await response.parse()
+ assert_matches_type(SuccessResponse, bot_signup, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_resend_magic_link(self, async_client: AsyncTelnyx) -> None:
+ async with async_client.bot_signup.with_streaming_response.resend_magic_link(
+ email="agent-owner@example.com",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ bot_signup = await response.parse()
+ assert_matches_type(SuccessResponse, bot_signup, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/test_calls.py b/tests/api_resources/test_calls.py
index d490b3e43..644dbdb3c 100644
--- a/tests/api_resources/test_calls.py
+++ b/tests/api_resources/test_calls.py
@@ -41,6 +41,13 @@ def test_method_dial_with_all_params(self, client: Telnyx) -> None:
answering_machine_detection_config={
"after_greeting_silence_millis": 1000,
"beep_detection_profile": "freq_only",
+ "beep_max_frequency_hz": 2000,
+ "beep_min_frequency_hz": 550,
+ "beep_min_tone_duration_millis": 300,
+ "beep_spectral_confirmation": True,
+ "beep_spectral_min_purity": 0.8,
+ "beep_spectral_reject_fax_cng": True,
+ "beep_spectral_window_millis": 100,
"between_words_silence_millis": 1000,
"greeting_duration_millis": 1000,
"greeting_silence_duration_millis": 2000,
@@ -393,6 +400,13 @@ async def test_method_dial_with_all_params(self, async_client: AsyncTelnyx) -> N
answering_machine_detection_config={
"after_greeting_silence_millis": 1000,
"beep_detection_profile": "freq_only",
+ "beep_max_frequency_hz": 2000,
+ "beep_min_frequency_hz": 550,
+ "beep_min_tone_duration_millis": 300,
+ "beep_spectral_confirmation": True,
+ "beep_spectral_min_purity": 0.8,
+ "beep_spectral_reject_fax_cng": True,
+ "beep_spectral_window_millis": 100,
"between_words_silence_millis": 1000,
"greeting_duration_millis": 1000,
"greeting_silence_duration_millis": 2000,
diff --git a/tests/api_resources/test_connections.py b/tests/api_resources/test_connections.py
index 48d3d90b1..f05402b27 100644
--- a/tests/api_resources/test_connections.py
+++ b/tests/api_resources/test_connections.py
@@ -12,6 +12,7 @@
from telnyx.types import (
Connection,
ConnectionRetrieveResponse,
+ ConnectionRetrieveCountResponse,
ConnectionListActiveCallsResponse,
)
from telnyx.pagination import SyncDefaultFlatPagination, AsyncDefaultFlatPagination
@@ -161,6 +162,34 @@ def test_path_params_list_active_calls(self, client: Telnyx) -> None:
connection_id="",
)
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_retrieve_count(self, client: Telnyx) -> None:
+ connection = client.connections.retrieve_count()
+ assert_matches_type(ConnectionRetrieveCountResponse, connection, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_retrieve_count(self, client: Telnyx) -> None:
+ response = client.connections.with_raw_response.retrieve_count()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ connection = response.parse()
+ assert_matches_type(ConnectionRetrieveCountResponse, connection, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_retrieve_count(self, client: Telnyx) -> None:
+ with client.connections.with_streaming_response.retrieve_count() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ connection = response.parse()
+ assert_matches_type(ConnectionRetrieveCountResponse, connection, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
class TestAsyncConnections:
parametrize = pytest.mark.parametrize(
@@ -311,3 +340,31 @@ async def test_path_params_list_active_calls(self, async_client: AsyncTelnyx) ->
await async_client.connections.with_raw_response.list_active_calls(
connection_id="",
)
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_method_retrieve_count(self, async_client: AsyncTelnyx) -> None:
+ connection = await async_client.connections.retrieve_count()
+ assert_matches_type(ConnectionRetrieveCountResponse, connection, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_retrieve_count(self, async_client: AsyncTelnyx) -> None:
+ response = await async_client.connections.with_raw_response.retrieve_count()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ connection = await response.parse()
+ assert_matches_type(ConnectionRetrieveCountResponse, connection, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_retrieve_count(self, async_client: AsyncTelnyx) -> None:
+ async with async_client.connections.with_streaming_response.retrieve_count() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ connection = await response.parse()
+ assert_matches_type(ConnectionRetrieveCountResponse, connection, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/test_machine_payments.py b/tests/api_resources/test_machine_payments.py
new file mode 100644
index 000000000..3d5f7c2eb
--- /dev/null
+++ b/tests/api_resources/test_machine_payments.py
@@ -0,0 +1,92 @@
+# 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 MachinePaymentAccountCreditResponse
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestMachinePayments:
+ 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_account_credit(self, client: Telnyx) -> None:
+ machine_payment = client.machine_payments.account_credit(
+ amount_usd="10.00",
+ )
+ assert_matches_type(MachinePaymentAccountCreditResponse, machine_payment, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_account_credit(self, client: Telnyx) -> None:
+ response = client.machine_payments.with_raw_response.account_credit(
+ amount_usd="10.00",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ machine_payment = response.parse()
+ assert_matches_type(MachinePaymentAccountCreditResponse, machine_payment, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_account_credit(self, client: Telnyx) -> None:
+ with client.machine_payments.with_streaming_response.account_credit(
+ amount_usd="10.00",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ machine_payment = response.parse()
+ assert_matches_type(MachinePaymentAccountCreditResponse, machine_payment, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+
+class TestAsyncMachinePayments:
+ 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_account_credit(self, async_client: AsyncTelnyx) -> None:
+ machine_payment = await async_client.machine_payments.account_credit(
+ amount_usd="10.00",
+ )
+ assert_matches_type(MachinePaymentAccountCreditResponse, machine_payment, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_raw_response_account_credit(self, async_client: AsyncTelnyx) -> None:
+ response = await async_client.machine_payments.with_raw_response.account_credit(
+ amount_usd="10.00",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ machine_payment = await response.parse()
+ assert_matches_type(MachinePaymentAccountCreditResponse, machine_payment, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ async def test_streaming_response_account_credit(self, async_client: AsyncTelnyx) -> None:
+ async with async_client.machine_payments.with_streaming_response.account_credit(
+ amount_usd="10.00",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ machine_payment = await response.parse()
+ assert_matches_type(MachinePaymentAccountCreditResponse, machine_payment, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/test_noise_suppression_engines.py b/tests/api_resources/test_noise_suppression_engines.py
new file mode 100644
index 000000000..3beea017f
--- /dev/null
+++ b/tests/api_resources/test_noise_suppression_engines.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 import NoiseSuppressionEngineListResponse
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestNoiseSuppressionEngines:
+ 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:
+ noise_suppression_engine = client.noise_suppression_engines.list()
+ assert_matches_type(NoiseSuppressionEngineListResponse, noise_suppression_engine, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_list(self, client: Telnyx) -> None:
+ response = client.noise_suppression_engines.with_raw_response.list()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ noise_suppression_engine = response.parse()
+ assert_matches_type(NoiseSuppressionEngineListResponse, noise_suppression_engine, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_list(self, client: Telnyx) -> None:
+ with client.noise_suppression_engines.with_streaming_response.list() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ noise_suppression_engine = response.parse()
+ assert_matches_type(NoiseSuppressionEngineListResponse, noise_suppression_engine, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+
+class TestAsyncNoiseSuppressionEngines:
+ 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:
+ noise_suppression_engine = await async_client.noise_suppression_engines.list()
+ assert_matches_type(NoiseSuppressionEngineListResponse, noise_suppression_engine, 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.noise_suppression_engines.with_raw_response.list()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ noise_suppression_engine = await response.parse()
+ assert_matches_type(NoiseSuppressionEngineListResponse, noise_suppression_engine, 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.noise_suppression_engines.with_streaming_response.list() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ noise_suppression_engine = await response.parse()
+ assert_matches_type(NoiseSuppressionEngineListResponse, noise_suppression_engine, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/test_texml.py b/tests/api_resources/test_texml.py
index 50eace414..89533a6e2 100644
--- a/tests/api_resources/test_texml.py
+++ b/tests/api_resources/test_texml.py
@@ -62,7 +62,14 @@ def test_method_initiate_ai_call_with_all_params(self, client: Telnyx) -> None:
],
detection_mode="Premium",
machine_detection="Enable",
+ machine_detection_beep_max_frequency=2000,
+ machine_detection_beep_min_frequency=550,
+ machine_detection_beep_min_tone_duration=300,
machine_detection_beep_profile="freq_only",
+ machine_detection_beep_spectral_confirmation=True,
+ machine_detection_beep_spectral_min_purity=0.8,
+ machine_detection_beep_spectral_reject_fax_cng=True,
+ machine_detection_beep_spectral_window=100,
machine_detection_prompt_end_timeout=5000,
machine_detection_silence_timeout=2000,
machine_detection_speech_end_threshold=2000,
@@ -219,7 +226,14 @@ async def test_method_initiate_ai_call_with_all_params(self, async_client: Async
],
detection_mode="Premium",
machine_detection="Enable",
+ machine_detection_beep_max_frequency=2000,
+ machine_detection_beep_min_frequency=550,
+ machine_detection_beep_min_tone_duration=300,
machine_detection_beep_profile="freq_only",
+ machine_detection_beep_spectral_confirmation=True,
+ machine_detection_beep_spectral_min_purity=0.8,
+ machine_detection_beep_spectral_reject_fax_cng=True,
+ machine_detection_beep_spectral_window=100,
machine_detection_prompt_end_timeout=5000,
machine_detection_silence_timeout=2000,
machine_detection_speech_end_threshold=2000,
diff --git a/tests/api_resources/texml/accounts/conferences/test_participants.py b/tests/api_resources/texml/accounts/conferences/test_participants.py
index 6f315d6d8..d30375d97 100644
--- a/tests/api_resources/texml/accounts/conferences/test_participants.py
+++ b/tests/api_resources/texml/accounts/conferences/test_participants.py
@@ -284,7 +284,14 @@ def test_method_participants_with_all_params(self, client: Telnyx) -> None:
from_="+12065550200",
label="customer",
machine_detection="Enable",
+ machine_detection_beep_max_frequency=2000,
+ machine_detection_beep_min_frequency=550,
+ machine_detection_beep_min_tone_duration=300,
machine_detection_beep_profile="freq_only",
+ machine_detection_beep_spectral_confirmation=True,
+ machine_detection_beep_spectral_min_purity=0.8,
+ machine_detection_beep_spectral_reject_fax_cng=True,
+ machine_detection_beep_spectral_window=100,
machine_detection_silence_timeout=2000,
machine_detection_speech_end_threshold=2000,
machine_detection_speech_threshold=2000,
@@ -676,7 +683,14 @@ async def test_method_participants_with_all_params(self, async_client: AsyncTeln
from_="+12065550200",
label="customer",
machine_detection="Enable",
+ machine_detection_beep_max_frequency=2000,
+ machine_detection_beep_min_frequency=550,
+ machine_detection_beep_min_tone_duration=300,
machine_detection_beep_profile="freq_only",
+ machine_detection_beep_spectral_confirmation=True,
+ machine_detection_beep_spectral_min_purity=0.8,
+ machine_detection_beep_spectral_reject_fax_cng=True,
+ machine_detection_beep_spectral_window=100,
machine_detection_silence_timeout=2000,
machine_detection_speech_end_threshold=2000,
machine_detection_speech_threshold=2000,
diff --git a/tests/api_resources/texml/accounts/test_calls.py b/tests/api_resources/texml/accounts/test_calls.py
index 34bc82c11..3d526d83a 100644
--- a/tests/api_resources/texml/accounts/test_calls.py
+++ b/tests/api_resources/texml/accounts/test_calls.py
@@ -180,7 +180,14 @@ def test_method_calls_with_all_params(self, client: Telnyx) -> None:
"fallback_url": "https://www.example.com/instructions-fallback.xml",
"from_": "+13120001234",
"machine_detection": "Enable",
+ "machine_detection_beep_max_frequency": 2000,
+ "machine_detection_beep_min_frequency": 550,
+ "machine_detection_beep_min_tone_duration": 300,
"machine_detection_beep_profile": "freq_only",
+ "machine_detection_beep_spectral_confirmation": True,
+ "machine_detection_beep_spectral_min_purity": 0.8,
+ "machine_detection_beep_spectral_reject_fax_cng": True,
+ "machine_detection_beep_spectral_window": 100,
"machine_detection_prompt_end_timeout": 5000,
"machine_detection_silence_timeout": 2000,
"machine_detection_speech_end_threshold": 2000,
@@ -614,7 +621,14 @@ async def test_method_calls_with_all_params(self, async_client: AsyncTelnyx) ->
"fallback_url": "https://www.example.com/instructions-fallback.xml",
"from_": "+13120001234",
"machine_detection": "Enable",
+ "machine_detection_beep_max_frequency": 2000,
+ "machine_detection_beep_min_frequency": 550,
+ "machine_detection_beep_min_tone_duration": 300,
"machine_detection_beep_profile": "freq_only",
+ "machine_detection_beep_spectral_confirmation": True,
+ "machine_detection_beep_spectral_min_purity": 0.8,
+ "machine_detection_beep_spectral_reject_fax_cng": True,
+ "machine_detection_beep_spectral_window": 100,
"machine_detection_prompt_end_timeout": 5000,
"machine_detection_silence_timeout": 2000,
"machine_detection_speech_end_threshold": 2000,
diff --git a/tests/api_resources/texml/test_calls.py b/tests/api_resources/texml/test_calls.py
new file mode 100644
index 000000000..c5688c59f
--- /dev/null
+++ b/tests/api_resources/texml/test_calls.py
@@ -0,0 +1,150 @@
+# 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.texml import CallCreateResponse
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestCalls:
+ 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:
+ call = client.texml.calls.create(
+ connection_id="1234567890",
+ from_="+13120001234",
+ to="+13121230000",
+ )
+ assert_matches_type(CallCreateResponse, call, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_method_create_with_all_params(self, client: Telnyx) -> None:
+ call = client.texml.calls.create(
+ connection_id="1234567890",
+ from_="+13120001234",
+ to="+13121230000",
+ method="POST",
+ texml="Hello",
+ url="https://example.com/instructions.xml",
+ )
+ assert_matches_type(CallCreateResponse, call, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_raw_response_create(self, client: Telnyx) -> None:
+ response = client.texml.calls.with_raw_response.create(
+ connection_id="1234567890",
+ from_="+13120001234",
+ to="+13121230000",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ call = response.parse()
+ assert_matches_type(CallCreateResponse, call, path=["response"])
+
+ @pytest.mark.skip(reason="Mock server tests are disabled")
+ @parametrize
+ def test_streaming_response_create(self, client: Telnyx) -> None:
+ with client.texml.calls.with_streaming_response.create(
+ connection_id="1234567890",
+ from_="+13120001234",
+ to="+13121230000",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ call = response.parse()
+ assert_matches_type(CallCreateResponse, call, 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 `connection_id` but received ''"):
+ client.texml.calls.with_raw_response.create(
+ connection_id="",
+ from_="+13120001234",
+ to="+13121230000",
+ )
+
+
+class TestAsyncCalls:
+ 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:
+ call = await async_client.texml.calls.create(
+ connection_id="1234567890",
+ from_="+13120001234",
+ to="+13121230000",
+ )
+ assert_matches_type(CallCreateResponse, call, 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:
+ call = await async_client.texml.calls.create(
+ connection_id="1234567890",
+ from_="+13120001234",
+ to="+13121230000",
+ method="POST",
+ texml="Hello",
+ url="https://example.com/instructions.xml",
+ )
+ assert_matches_type(CallCreateResponse, call, 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.texml.calls.with_raw_response.create(
+ connection_id="1234567890",
+ from_="+13120001234",
+ to="+13121230000",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ call = await response.parse()
+ assert_matches_type(CallCreateResponse, call, 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.texml.calls.with_streaming_response.create(
+ connection_id="1234567890",
+ from_="+13120001234",
+ to="+13121230000",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ call = await response.parse()
+ assert_matches_type(CallCreateResponse, call, 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 `connection_id` but received ''"):
+ await async_client.texml.calls.with_raw_response.create(
+ connection_id="",
+ from_="+13120001234",
+ to="+13121230000",
+ )