diff --git a/.release-please-manifest.json b/.release-please-manifest.json index baecb9848..28a64b708 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "4.179.0" + ".": "4.180.0" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index 0a0068803..d0e375fdc 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1 +1 @@ -configured_endpoints: 1249 +configured_endpoints: 1256 diff --git a/CHANGELOG.md b/CHANGELOG.md index 41553a83b..4fc124d9a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [4.180.0](https://github.com/team-telnyx/telnyx-python/compare/v4.179.0...v4.180.0) (2026-09-13) + + +### Features + +* promote from staging 938aa9b ([fb184dc](https://github.com/team-telnyx/telnyx-python/commit/fb184dc2e4b0c9abecc4aba606fd8d66b25f5e73)) + ## [4.179.0](https://github.com/team-telnyx/telnyx-python/compare/v4.178.0...v4.179.0) (2026-09-07) diff --git a/api.md b/api.md index 7efee71e9..e1e4fdd12 100644 --- a/api.md +++ b/api.md @@ -330,6 +330,8 @@ from telnyx.types import ( OutboundMessage, ReplacedLinkClick, Transcription, + WhatsappAccountUpdate, + WhatsappMessageEcho, CallAIGatherEndedWebhookEvent, CallAIGatherMessageHistoryUpdatedWebhookEvent, CallAIGatherPartialResultsWebhookEvent, @@ -606,6 +608,7 @@ Types: from telnyx.types.ai import ( ArithmeticExpression, Assistant, + AssistantA2AAgent, AssistantIntegration, AssistantMcpServer, AssistantTool, @@ -2790,6 +2793,7 @@ Types: from telnyx.types import ( MessagingMessagingProfile, MessagingProfile, + MessagingProfileFeatures, NumberPoolSettings, URLShortenerSettings, MessagingProfileCreateResponse, @@ -5737,6 +5741,7 @@ from telnyx.types.whatsapp import ( PhoneNumberListResponse, PhoneNumberGetResponse, PhoneNumberRetrieveConversationWindowResponse, + PhoneNumberRetrievePhoneNumberResponse, ) ``` @@ -5747,6 +5752,7 @@ Methods: - client.whatsapp.phone_numbers.get(\*\*params) -> PhoneNumberGetResponse - client.whatsapp.phone_numbers.resend_verification(phone_number, \*\*params) -> None - client.whatsapp.phone_numbers.retrieve_conversation_window(phone_number, \*\*params) -> PhoneNumberRetrieveConversationWindowResponse +- client.whatsapp.phone_numbers.retrieve_phone_number(phone_number) -> PhoneNumberRetrievePhoneNumberResponse - client.whatsapp.phone_numbers.verify(phone_number, \*\*params) -> None ### CallingSettings @@ -5856,8 +5862,21 @@ from telnyx.types.x402 import CreditAccountCreateQuoteResponse, CreditAccountSet Methods: -- client.x402.credit_account.create_quote(\*\*params) -> CreditAccountCreateQuoteResponse -- client.x402.credit_account.settle(\*\*params) -> CreditAccountSettleResponse +- client.x402.credit_account.create_quote(\*\*params) -> CreditAccountCreateQuoteResponse +- client.x402.credit_account.settle(\*\*params) -> CreditAccountSettleResponse + +### Payments + +Types: + +```python +from telnyx.types.x402.credit_account import X402TransactionRecord, PaymentRetrieveResponse +``` + +Methods: + +- client.x402.credit_account.payments.retrieve(id) -> PaymentRetrieveResponse +- client.x402.credit_account.payments.list(\*\*params) -> SyncDefaultFlatPagination[X402TransactionRecord] # VoiceClones @@ -6787,3 +6806,27 @@ Methods: - client.external_requirements.sub_number_orders.retrieve(sub_number_order_id, \*, regulatory_requirement_id) -> SubNumberOrderRetrieveResponse - client.external_requirements.sub_number_orders.update(sub_number_order_id, \*, regulatory_requirement_id, \*\*params) -> SubNumberOrderUpdateResponse + +# Compute + +## Funcs + +Types: + +```python +from telnyx.types.compute import ( + FunctionsObservabilityPaginationMeta, + LogsMeta, + FuncRetrieveLogsResponse, + FuncRetrieveMetricAggregatesResponse, + FuncRetrieveRevisionsResponse, + FuncRetrieveShipInspectionResponse, +) +``` + +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 diff --git a/pyproject.toml b/pyproject.toml index 17b258e1e..ab8d35410 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "telnyx" -version = "4.179.0" +version = "4.180.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 ab28b8024..11c29ae54 100644 --- a/src/telnyx/_client.py +++ b/src/telnyx/_client.py @@ -55,6 +55,7 @@ queues, actions, balance, + compute, payment, porting, pricing, @@ -271,6 +272,7 @@ from .resources.actions.actions import ActionsResource, AsyncActionsResource from .resources.advanced_orders import AdvancedOrdersResource, AsyncAdvancedOrdersResource from .resources.charges_summary import ChargesSummaryResource, AsyncChargesSummaryResource + from .resources.compute.compute import ComputeResource, AsyncComputeResource from .resources.email_templates import EmailTemplatesResource, AsyncEmailTemplatesResource from .resources.global_ip_usage import GlobalIPUsageResource, AsyncGlobalIPUsageResource from .resources.payment.payment import PaymentResource, AsyncPaymentResource @@ -1850,6 +1852,12 @@ def external_requirements(self) -> ExternalRequirementsResource: return ExternalRequirementsResource(self) + @cached_property + def compute(self) -> ComputeResource: + from .resources.compute import ComputeResource + + return ComputeResource(self) + @cached_property def with_raw_response(self) -> TelnyxWithRawResponse: return TelnyxWithRawResponse(self) @@ -3348,6 +3356,12 @@ def external_requirements(self) -> AsyncExternalRequirementsResource: return AsyncExternalRequirementsResource(self) + @cached_property + def compute(self) -> AsyncComputeResource: + from .resources.compute import AsyncComputeResource + + return AsyncComputeResource(self) + @cached_property def with_raw_response(self) -> AsyncTelnyxWithRawResponse: return AsyncTelnyxWithRawResponse(self) @@ -4782,6 +4796,12 @@ def external_requirements(self) -> external_requirements.ExternalRequirementsRes return ExternalRequirementsResourceWithRawResponse(self._client.external_requirements) + @cached_property + def compute(self) -> compute.ComputeResourceWithRawResponse: + from .resources.compute import ComputeResourceWithRawResponse + + return ComputeResourceWithRawResponse(self._client.compute) + class AsyncTelnyxWithRawResponse: _client: AsyncTelnyx @@ -6087,6 +6107,12 @@ def external_requirements(self) -> external_requirements.AsyncExternalRequiremen return AsyncExternalRequirementsResourceWithRawResponse(self._client.external_requirements) + @cached_property + def compute(self) -> compute.AsyncComputeResourceWithRawResponse: + from .resources.compute import AsyncComputeResourceWithRawResponse + + return AsyncComputeResourceWithRawResponse(self._client.compute) + class TelnyxWithStreamedResponse: _client: Telnyx @@ -7394,6 +7420,12 @@ def external_requirements(self) -> external_requirements.ExternalRequirementsRes return ExternalRequirementsResourceWithStreamingResponse(self._client.external_requirements) + @cached_property + def compute(self) -> compute.ComputeResourceWithStreamingResponse: + from .resources.compute import ComputeResourceWithStreamingResponse + + return ComputeResourceWithStreamingResponse(self._client.compute) + class AsyncTelnyxWithStreamedResponse: _client: AsyncTelnyx @@ -8749,6 +8781,12 @@ def external_requirements(self) -> external_requirements.AsyncExternalRequiremen return AsyncExternalRequirementsResourceWithStreamingResponse(self._client.external_requirements) + @cached_property + def compute(self) -> compute.AsyncComputeResourceWithStreamingResponse: + from .resources.compute import AsyncComputeResourceWithStreamingResponse + + return AsyncComputeResourceWithStreamingResponse(self._client.compute) + Client = Telnyx diff --git a/src/telnyx/_version.py b/src/telnyx/_version.py index bd4f52a53..2c5801666 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.179.0" # x-release-please-version +__version__ = "4.180.0" # x-release-please-version diff --git a/src/telnyx/resources/__init__.py b/src/telnyx/resources/__init__.py index cc508b0c9..7595ed0ba 100644 --- a/src/telnyx/resources/__init__.py +++ b/src/telnyx/resources/__init__.py @@ -144,6 +144,14 @@ BalanceResourceWithStreamingResponse, AsyncBalanceResourceWithStreamingResponse, ) +from .compute import ( + ComputeResource, + AsyncComputeResource, + ComputeResourceWithRawResponse, + AsyncComputeResourceWithRawResponse, + ComputeResourceWithStreamingResponse, + AsyncComputeResourceWithStreamingResponse, +) from .payment import ( PaymentResource, AsyncPaymentResource, @@ -2539,4 +2547,10 @@ "AsyncExternalRequirementsResourceWithRawResponse", "ExternalRequirementsResourceWithStreamingResponse", "AsyncExternalRequirementsResourceWithStreamingResponse", + "ComputeResource", + "AsyncComputeResource", + "ComputeResourceWithRawResponse", + "AsyncComputeResourceWithRawResponse", + "ComputeResourceWithStreamingResponse", + "AsyncComputeResourceWithStreamingResponse", ] diff --git a/src/telnyx/resources/ai/assistants/assistants.py b/src/telnyx/resources/ai/assistants/assistants.py index f83186f94..62e44f416 100644 --- a/src/telnyx/resources/ai/assistants/assistants.py +++ b/src/telnyx/resources/ai/assistants/assistants.py @@ -97,6 +97,7 @@ from ....types.ai.telephony_settings_param import TelephonySettingsParam from ....types.ai.assistant_delete_response import AssistantDeleteResponse from ....types.ai.fallback_config_req_param import FallbackConfigReqParam +from ....types.ai.assistant_a2_a_agent_param import AssistantA2AAgentParam from ....types.ai.assistant_mcp_server_param import AssistantMcpServerParam from ....types.ai.assistant_integration_param import AssistantIntegrationParam from ....types.ai.assistant_send_sms_response import AssistantSendSMSResponse @@ -170,6 +171,7 @@ def create( *, instructions: str, name: str, + a2a_agents: Iterable[AssistantA2AAgentParam] | Omit = omit, conversation_flow: ConversationFlowReqParam | Omit = omit, description: str | Omit = omit, dynamic_variables: Dict[str, object] | Omit = omit, @@ -212,6 +214,15 @@ def create( instructions: System instructions for the assistant. These may be templated with [dynamic variables](https://developers.telnyx.com/docs/inference/ai-assistants/dynamic-variables) + a2a_agents: A2A agents this assistant can delegate to. Tools are not stored here: at the + start of every conversation each agent's card is fetched and one tool is derived + per skill the card advertises, named `a2a__`. The following + limits are not enforced when the assistant is saved, and anything past them is + dropped when the conversation starts: 64 agents per assistant, 64 skills per + card, 128 derived tools per assistant, and a 6 second budget for all card + fetches combined. An agent whose card cannot be fetched costs the assistant that + capability for the conversation; it does not fail the call. + conversation_flow: Conversation flow as supplied by API clients (create / update). A directed graph of `FlowNodeReq` connected by `FlowEdge`s. Validation enforces @@ -303,6 +314,7 @@ def create( { "instructions": instructions, "name": name, + "a2a_agents": a2a_agents, "conversation_flow": conversation_flow, "description": description, "dynamic_variables": dynamic_variables, @@ -399,6 +411,7 @@ def update( self, assistant_id: str, *, + a2a_agents: Iterable[AssistantA2AAgentParam] | Omit = omit, conversation_flow: ConversationFlowReqParam | Omit = omit, description: str | Omit = omit, dynamic_variables: Dict[str, object] | Omit = omit, @@ -442,6 +455,16 @@ def update( assistant versions. Args: + a2a_agents: A2A agents this assistant can delegate to. Tools are not stored here: at the + start of every conversation each agent's card is fetched and one tool is derived + per skill the card advertises, named `a2a__`. The following + limits are not enforced when the assistant is saved, and anything past them is + dropped when the conversation starts: 64 agents per assistant, 64 skills per + card, 128 derived tools per assistant, and a 6 second budget for all card + fetches combined. An agent whose card cannot be fetched costs the assistant that + capability for the conversation; it does not fail the call. Omit this field to + leave the assistant's agents unchanged; send an empty array to remove them all. + conversation_flow: Conversation flow as supplied by API clients (create / update). A directed graph of `FlowNodeReq` connected by `FlowEdge`s. Validation enforces @@ -540,6 +563,7 @@ def update( path_template("/ai/assistants/{assistant_id}", assistant_id=assistant_id), body=maybe_transform( { + "a2a_agents": a2a_agents, "conversation_flow": conversation_flow, "description": description, "dynamic_variables": dynamic_variables, @@ -944,6 +968,7 @@ async def create( *, instructions: str, name: str, + a2a_agents: Iterable[AssistantA2AAgentParam] | Omit = omit, conversation_flow: ConversationFlowReqParam | Omit = omit, description: str | Omit = omit, dynamic_variables: Dict[str, object] | Omit = omit, @@ -986,6 +1011,15 @@ async def create( instructions: System instructions for the assistant. These may be templated with [dynamic variables](https://developers.telnyx.com/docs/inference/ai-assistants/dynamic-variables) + a2a_agents: A2A agents this assistant can delegate to. Tools are not stored here: at the + start of every conversation each agent's card is fetched and one tool is derived + per skill the card advertises, named `a2a__`. The following + limits are not enforced when the assistant is saved, and anything past them is + dropped when the conversation starts: 64 agents per assistant, 64 skills per + card, 128 derived tools per assistant, and a 6 second budget for all card + fetches combined. An agent whose card cannot be fetched costs the assistant that + capability for the conversation; it does not fail the call. + conversation_flow: Conversation flow as supplied by API clients (create / update). A directed graph of `FlowNodeReq` connected by `FlowEdge`s. Validation enforces @@ -1077,6 +1111,7 @@ async def create( { "instructions": instructions, "name": name, + "a2a_agents": a2a_agents, "conversation_flow": conversation_flow, "description": description, "dynamic_variables": dynamic_variables, @@ -1173,6 +1208,7 @@ async def update( self, assistant_id: str, *, + a2a_agents: Iterable[AssistantA2AAgentParam] | Omit = omit, conversation_flow: ConversationFlowReqParam | Omit = omit, description: str | Omit = omit, dynamic_variables: Dict[str, object] | Omit = omit, @@ -1216,6 +1252,16 @@ async def update( assistant versions. Args: + a2a_agents: A2A agents this assistant can delegate to. Tools are not stored here: at the + start of every conversation each agent's card is fetched and one tool is derived + per skill the card advertises, named `a2a__`. The following + limits are not enforced when the assistant is saved, and anything past them is + dropped when the conversation starts: 64 agents per assistant, 64 skills per + card, 128 derived tools per assistant, and a 6 second budget for all card + fetches combined. An agent whose card cannot be fetched costs the assistant that + capability for the conversation; it does not fail the call. Omit this field to + leave the assistant's agents unchanged; send an empty array to remove them all. + conversation_flow: Conversation flow as supplied by API clients (create / update). A directed graph of `FlowNodeReq` connected by `FlowEdge`s. Validation enforces @@ -1314,6 +1360,7 @@ async def update( path_template("/ai/assistants/{assistant_id}", assistant_id=assistant_id), body=await async_maybe_transform( { + "a2a_agents": a2a_agents, "conversation_flow": conversation_flow, "description": description, "dynamic_variables": dynamic_variables, diff --git a/src/telnyx/resources/ai/assistants/versions.py b/src/telnyx/resources/ai/assistants/versions.py index 53fe4dbbe..33af21060 100644 --- a/src/telnyx/resources/ai/assistants/versions.py +++ b/src/telnyx/resources/ai/assistants/versions.py @@ -31,6 +31,7 @@ from ....types.ai.messaging_settings_param import MessagingSettingsParam from ....types.ai.telephony_settings_param import TelephonySettingsParam from ....types.ai.fallback_config_req_param import FallbackConfigReqParam +from ....types.ai.assistant_a2_a_agent_param import AssistantA2AAgentParam from ....types.ai.assistant_mcp_server_param import AssistantMcpServerParam from ....types.ai.assistant_integration_param import AssistantIntegrationParam from ....types.ai.conversation_flow_req_param import ConversationFlowReqParam @@ -115,6 +116,7 @@ def update( version_id: str, *, assistant_id: str, + a2a_agents: Iterable[AssistantA2AAgentParam] | Omit = omit, conversation_flow: ConversationFlowReqParam | Omit = omit, description: str | Omit = omit, dynamic_variables: Dict[str, object] | Omit = omit, @@ -157,6 +159,16 @@ def update( version Args: + a2a_agents: A2A agents this assistant can delegate to. Tools are not stored here: at the + start of every conversation each agent's card is fetched and one tool is derived + per skill the card advertises, named `a2a__`. The following + limits are not enforced when the assistant is saved, and anything past them is + dropped when the conversation starts: 64 agents per assistant, 64 skills per + card, 128 derived tools per assistant, and a 6 second budget for all card + fetches combined. An agent whose card cannot be fetched costs the assistant that + capability for the conversation; it does not fail the call. Omit this field to + leave the assistant's agents unchanged; send an empty array to remove them all. + conversation_flow: Conversation flow as supplied by API clients (create / update). A directed graph of `FlowNodeReq` connected by `FlowEdge`s. Validation enforces @@ -256,6 +268,7 @@ def update( ), body=maybe_transform( { + "a2a_agents": a2a_agents, "conversation_flow": conversation_flow, "description": description, "dynamic_variables": dynamic_variables, @@ -486,6 +499,7 @@ async def update( version_id: str, *, assistant_id: str, + a2a_agents: Iterable[AssistantA2AAgentParam] | Omit = omit, conversation_flow: ConversationFlowReqParam | Omit = omit, description: str | Omit = omit, dynamic_variables: Dict[str, object] | Omit = omit, @@ -528,6 +542,16 @@ async def update( version Args: + a2a_agents: A2A agents this assistant can delegate to. Tools are not stored here: at the + start of every conversation each agent's card is fetched and one tool is derived + per skill the card advertises, named `a2a__`. The following + limits are not enforced when the assistant is saved, and anything past them is + dropped when the conversation starts: 64 agents per assistant, 64 skills per + card, 128 derived tools per assistant, and a 6 second budget for all card + fetches combined. An agent whose card cannot be fetched costs the assistant that + capability for the conversation; it does not fail the call. Omit this field to + leave the assistant's agents unchanged; send an empty array to remove them all. + conversation_flow: Conversation flow as supplied by API clients (create / update). A directed graph of `FlowNodeReq` connected by `FlowEdge`s. Validation enforces @@ -627,6 +651,7 @@ async def update( ), body=await async_maybe_transform( { + "a2a_agents": a2a_agents, "conversation_flow": conversation_flow, "description": description, "dynamic_variables": dynamic_variables, diff --git a/src/telnyx/resources/ai/openai/chat.py b/src/telnyx/resources/ai/openai/chat.py index c2ee67886..5de789c19 100644 --- a/src/telnyx/resources/ai/openai/chat.py +++ b/src/telnyx/resources/ai/openai/chat.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import Dict, Union, Iterable +from typing import Union, Iterable from typing_extensions import Literal import httpx @@ -53,9 +53,6 @@ def create_completion( early_stopping: bool | Omit = omit, enable_thinking: bool | Omit = omit, frequency_penalty: float | Omit = omit, - guided_choice: SequenceNotStr[str] | Omit = omit, - guided_json: Dict[str, object] | Omit = omit, - guided_regex: str | Omit = omit, length_penalty: float | Omit = omit, logprobs: bool | Omit = omit, max_tokens: int | Omit = omit, @@ -112,13 +109,6 @@ def create_completion( frequency_penalty: Higher values will penalize the model from repeating the same output tokens. - guided_choice: If specified, the output will be exactly one of the choices. - - guided_json: Must be a valid JSON schema. If specified, the output will follow the JSON - schema. - - guided_regex: If specified, the output will follow the regex pattern. - length_penalty: This is used with `use_beam_search` to prefer shorter or longer completions. logprobs: Whether to return log probabilities of the output tokens or not. If true, @@ -155,8 +145,10 @@ def create_completion( provider never passes through Telnyx model routing, so a region cannot be enforced for it. Omit for today's latency-based routing. - response_format: Use this is you want to guarantee a JSON output without defining a schema. For - control over the schema, use `guided_json`. + response_format: Controls the format of the model output. `json_object` guarantees valid JSON + output without defining a schema; `json_schema` constrains the output to the + JSON schema you supply via the `json_schema` property and is the supported way + to get guaranteed structured output on Telnyx-hosted models. seed: If specified, the system will make a best effort to sample deterministically, such that repeated requests with the same `seed` and parameters should return @@ -210,9 +202,6 @@ def create_completion( "early_stopping": early_stopping, "enable_thinking": enable_thinking, "frequency_penalty": frequency_penalty, - "guided_choice": guided_choice, - "guided_json": guided_json, - "guided_regex": guided_regex, "length_penalty": length_penalty, "logprobs": logprobs, "max_tokens": max_tokens, @@ -273,9 +262,6 @@ async def create_completion( early_stopping: bool | Omit = omit, enable_thinking: bool | Omit = omit, frequency_penalty: float | Omit = omit, - guided_choice: SequenceNotStr[str] | Omit = omit, - guided_json: Dict[str, object] | Omit = omit, - guided_regex: str | Omit = omit, length_penalty: float | Omit = omit, logprobs: bool | Omit = omit, max_tokens: int | Omit = omit, @@ -332,13 +318,6 @@ async def create_completion( frequency_penalty: Higher values will penalize the model from repeating the same output tokens. - guided_choice: If specified, the output will be exactly one of the choices. - - guided_json: Must be a valid JSON schema. If specified, the output will follow the JSON - schema. - - guided_regex: If specified, the output will follow the regex pattern. - length_penalty: This is used with `use_beam_search` to prefer shorter or longer completions. logprobs: Whether to return log probabilities of the output tokens or not. If true, @@ -375,8 +354,10 @@ async def create_completion( provider never passes through Telnyx model routing, so a region cannot be enforced for it. Omit for today's latency-based routing. - response_format: Use this is you want to guarantee a JSON output without defining a schema. For - control over the schema, use `guided_json`. + response_format: Controls the format of the model output. `json_object` guarantees valid JSON + output without defining a schema; `json_schema` constrains the output to the + JSON schema you supply via the `json_schema` property and is the supported way + to get guaranteed structured output on Telnyx-hosted models. seed: If specified, the system will make a best effort to sample deterministically, such that repeated requests with the same `seed` and parameters should return @@ -430,9 +411,6 @@ async def create_completion( "early_stopping": early_stopping, "enable_thinking": enable_thinking, "frequency_penalty": frequency_penalty, - "guided_choice": guided_choice, - "guided_json": guided_json, - "guided_regex": guided_regex, "length_penalty": length_penalty, "logprobs": logprobs, "max_tokens": max_tokens, diff --git a/src/telnyx/resources/compute/__init__.py b/src/telnyx/resources/compute/__init__.py new file mode 100644 index 000000000..d3f382ac7 --- /dev/null +++ b/src/telnyx/resources/compute/__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 .compute import ( + ComputeResource, + AsyncComputeResource, + ComputeResourceWithRawResponse, + AsyncComputeResourceWithRawResponse, + ComputeResourceWithStreamingResponse, + AsyncComputeResourceWithStreamingResponse, +) + +__all__ = [ + "FuncsResource", + "AsyncFuncsResource", + "FuncsResourceWithRawResponse", + "AsyncFuncsResourceWithRawResponse", + "FuncsResourceWithStreamingResponse", + "AsyncFuncsResourceWithStreamingResponse", + "ComputeResource", + "AsyncComputeResource", + "ComputeResourceWithRawResponse", + "AsyncComputeResourceWithRawResponse", + "ComputeResourceWithStreamingResponse", + "AsyncComputeResourceWithStreamingResponse", +] diff --git a/src/telnyx/resources/compute/compute.py b/src/telnyx/resources/compute/compute.py new file mode 100644 index 000000000..5a77c3552 --- /dev/null +++ b/src/telnyx/resources/compute/compute.py @@ -0,0 +1,102 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from .funcs import ( + FuncsResource, + AsyncFuncsResource, + FuncsResourceWithRawResponse, + AsyncFuncsResourceWithRawResponse, + FuncsResourceWithStreamingResponse, + AsyncFuncsResourceWithStreamingResponse, +) +from ..._compat import cached_property +from ..._resource import SyncAPIResource, AsyncAPIResource + +__all__ = ["ComputeResource", "AsyncComputeResource"] + + +class ComputeResource(SyncAPIResource): + @cached_property + def funcs(self) -> FuncsResource: + return FuncsResource(self._client) + + @cached_property + def with_raw_response(self) -> ComputeResourceWithRawResponse: + """ + 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 ComputeResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> ComputeResourceWithStreamingResponse: + """ + 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 ComputeResourceWithStreamingResponse(self) + + +class AsyncComputeResource(AsyncAPIResource): + @cached_property + def funcs(self) -> AsyncFuncsResource: + return AsyncFuncsResource(self._client) + + @cached_property + def with_raw_response(self) -> AsyncComputeResourceWithRawResponse: + """ + 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 AsyncComputeResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncComputeResourceWithStreamingResponse: + """ + 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 AsyncComputeResourceWithStreamingResponse(self) + + +class ComputeResourceWithRawResponse: + def __init__(self, compute: ComputeResource) -> None: + self._compute = compute + + @cached_property + def funcs(self) -> FuncsResourceWithRawResponse: + return FuncsResourceWithRawResponse(self._compute.funcs) + + +class AsyncComputeResourceWithRawResponse: + def __init__(self, compute: AsyncComputeResource) -> None: + self._compute = compute + + @cached_property + def funcs(self) -> AsyncFuncsResourceWithRawResponse: + return AsyncFuncsResourceWithRawResponse(self._compute.funcs) + + +class ComputeResourceWithStreamingResponse: + def __init__(self, compute: ComputeResource) -> None: + self._compute = compute + + @cached_property + def funcs(self) -> FuncsResourceWithStreamingResponse: + return FuncsResourceWithStreamingResponse(self._compute.funcs) + + +class AsyncComputeResourceWithStreamingResponse: + def __init__(self, compute: AsyncComputeResource) -> None: + self._compute = compute + + @cached_property + def funcs(self) -> AsyncFuncsResourceWithStreamingResponse: + return AsyncFuncsResourceWithStreamingResponse(self._compute.funcs) diff --git a/src/telnyx/resources/compute/funcs.py b/src/telnyx/resources/compute/funcs.py new file mode 100644 index 000000000..512b8839d --- /dev/null +++ b/src/telnyx/resources/compute/funcs.py @@ -0,0 +1,566 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Any, Union, cast +from datetime import datetime +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 ..._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 + +__all__ = ["FuncsResource", "AsyncFuncsResource"] + + +class FuncsResource(SyncAPIResource): + @cached_property + def with_raw_response(self) -> FuncsResourceWithRawResponse: + """ + 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 FuncsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> FuncsResourceWithStreamingResponse: + """ + 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 FuncsResourceWithStreamingResponse(self) + + def retrieve_logs( + self, + id: str, + *, + end_time: Union[str, datetime] | Omit = omit, + limit: int | Omit = omit, + start_time: Union[str, datetime] | Omit = omit, + type: Literal["runtime", "invocations"] | 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, + ) -> FuncRetrieveLogsResponse: + """Returns logs oldest first. + + `type=runtime` (default) returns function + stdout/stderr. `type=invocations` returns one platform-generated record per HTTP + request served. + + Args: + end_time: Return records at or before this RFC 3339 timestamp. + + limit: Maximum records to return. + + start_time: Return records at or after this RFC 3339 timestamp. + + type: Log stream to return. + + 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 cast( + FuncRetrieveLogsResponse, + self._get( + path_template("/compute/funcs/{id}/logs", id=id), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "end_time": end_time, + "limit": limit, + "start_time": start_time, + "type": type, + }, + func_retrieve_logs_params.FuncRetrieveLogsParams, + ), + ), + cast_to=cast( + Any, FuncRetrieveLogsResponse + ), # Union types cannot be passed in as arguments in the type system + ), + ) + + def retrieve_metric_aggregates( + self, + id: str, + *, + end_time: Union[str, datetime], + start_time: Union[str, datetime], + filter_edge_site: str | Omit = omit, + filter_namespace: str | Omit = omit, + page_number: int | Omit = omit, + page_size: int | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> FuncRetrieveMetricAggregatesResponse: + """ + Returns aggregate request, latency, CPU, memory, and resource-limit metrics for + a function over the requested window. + + Args: + end_time: Exclusive window end, UTC ISO 8601 with milliseconds + + start_time: Inclusive window start, UTC ISO 8601 with milliseconds + + filter_edge_site: Edge site filter + + filter_namespace: Kubernetes namespace filter + + 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}/metric_aggregates", id=id), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "end_time": end_time, + "start_time": start_time, + "filter_edge_site": filter_edge_site, + "filter_namespace": filter_namespace, + "page_number": page_number, + "page_size": page_size, + }, + func_retrieve_metric_aggregates_params.FuncRetrieveMetricAggregatesParams, + ), + ), + cast_to=FuncRetrieveMetricAggregatesResponse, + ) + + def retrieve_revisions( + self, + id: str, + *, + page_number: int | Omit = omit, + page_size: int | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> FuncRetrieveRevisionsResponse: + """ + Lists a function's ship history newest first, including per-ship failure stage + and reason when recorded. + + 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}/revisions", id=id), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "page_number": page_number, + "page_size": page_size, + }, + func_retrieve_revisions_params.FuncRetrieveRevisionsParams, + ), + ), + cast_to=FuncRetrieveRevisionsResponse, + ) + + def retrieve_ship_inspection( + 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, + ) -> FuncRetrieveShipInspectionResponse: + """Returns the latest ship outcome. + + The stage is `none` on success, `pending` while + building, or a failure stage such as `build`, `platform`, `pre_build`, `deploy`, + or `security_review`. This stage-neutral customer-facing path is an alias over + the same inspection resource as `build_log_inspection`. + + 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}/ship_inspection", id=id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=FuncRetrieveShipInspectionResponse, + ) + + +class AsyncFuncsResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncFuncsResourceWithRawResponse: + """ + 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 AsyncFuncsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncFuncsResourceWithStreamingResponse: + """ + 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 AsyncFuncsResourceWithStreamingResponse(self) + + async def retrieve_logs( + self, + id: str, + *, + end_time: Union[str, datetime] | Omit = omit, + limit: int | Omit = omit, + start_time: Union[str, datetime] | Omit = omit, + type: Literal["runtime", "invocations"] | 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, + ) -> FuncRetrieveLogsResponse: + """Returns logs oldest first. + + `type=runtime` (default) returns function + stdout/stderr. `type=invocations` returns one platform-generated record per HTTP + request served. + + Args: + end_time: Return records at or before this RFC 3339 timestamp. + + limit: Maximum records to return. + + start_time: Return records at or after this RFC 3339 timestamp. + + type: Log stream to return. + + 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 cast( + FuncRetrieveLogsResponse, + await self._get( + path_template("/compute/funcs/{id}/logs", id=id), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform( + { + "end_time": end_time, + "limit": limit, + "start_time": start_time, + "type": type, + }, + func_retrieve_logs_params.FuncRetrieveLogsParams, + ), + ), + cast_to=cast( + Any, FuncRetrieveLogsResponse + ), # Union types cannot be passed in as arguments in the type system + ), + ) + + async def retrieve_metric_aggregates( + self, + id: str, + *, + end_time: Union[str, datetime], + start_time: Union[str, datetime], + filter_edge_site: str | Omit = omit, + filter_namespace: str | Omit = omit, + page_number: int | Omit = omit, + page_size: int | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> FuncRetrieveMetricAggregatesResponse: + """ + Returns aggregate request, latency, CPU, memory, and resource-limit metrics for + a function over the requested window. + + Args: + end_time: Exclusive window end, UTC ISO 8601 with milliseconds + + start_time: Inclusive window start, UTC ISO 8601 with milliseconds + + filter_edge_site: Edge site filter + + filter_namespace: Kubernetes namespace filter + + 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}/metric_aggregates", id=id), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform( + { + "end_time": end_time, + "start_time": start_time, + "filter_edge_site": filter_edge_site, + "filter_namespace": filter_namespace, + "page_number": page_number, + "page_size": page_size, + }, + func_retrieve_metric_aggregates_params.FuncRetrieveMetricAggregatesParams, + ), + ), + cast_to=FuncRetrieveMetricAggregatesResponse, + ) + + async def retrieve_revisions( + self, + id: str, + *, + page_number: int | Omit = omit, + page_size: int | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> FuncRetrieveRevisionsResponse: + """ + Lists a function's ship history newest first, including per-ship failure stage + and reason when recorded. + + 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}/revisions", id=id), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform( + { + "page_number": page_number, + "page_size": page_size, + }, + func_retrieve_revisions_params.FuncRetrieveRevisionsParams, + ), + ), + cast_to=FuncRetrieveRevisionsResponse, + ) + + async def retrieve_ship_inspection( + 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, + ) -> FuncRetrieveShipInspectionResponse: + """Returns the latest ship outcome. + + The stage is `none` on success, `pending` while + building, or a failure stage such as `build`, `platform`, `pre_build`, `deploy`, + or `security_review`. This stage-neutral customer-facing path is an alias over + the same inspection resource as `build_log_inspection`. + + 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}/ship_inspection", id=id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=FuncRetrieveShipInspectionResponse, + ) + + +class FuncsResourceWithRawResponse: + def __init__(self, funcs: FuncsResource) -> None: + self._funcs = funcs + + self.retrieve_logs = to_raw_response_wrapper( + funcs.retrieve_logs, + ) + self.retrieve_metric_aggregates = to_raw_response_wrapper( + funcs.retrieve_metric_aggregates, + ) + self.retrieve_revisions = to_raw_response_wrapper( + funcs.retrieve_revisions, + ) + self.retrieve_ship_inspection = to_raw_response_wrapper( + funcs.retrieve_ship_inspection, + ) + + +class AsyncFuncsResourceWithRawResponse: + def __init__(self, funcs: AsyncFuncsResource) -> None: + self._funcs = funcs + + self.retrieve_logs = async_to_raw_response_wrapper( + funcs.retrieve_logs, + ) + self.retrieve_metric_aggregates = async_to_raw_response_wrapper( + funcs.retrieve_metric_aggregates, + ) + self.retrieve_revisions = async_to_raw_response_wrapper( + funcs.retrieve_revisions, + ) + self.retrieve_ship_inspection = async_to_raw_response_wrapper( + funcs.retrieve_ship_inspection, + ) + + +class FuncsResourceWithStreamingResponse: + def __init__(self, funcs: FuncsResource) -> None: + self._funcs = funcs + + self.retrieve_logs = to_streamed_response_wrapper( + funcs.retrieve_logs, + ) + self.retrieve_metric_aggregates = to_streamed_response_wrapper( + funcs.retrieve_metric_aggregates, + ) + self.retrieve_revisions = to_streamed_response_wrapper( + funcs.retrieve_revisions, + ) + self.retrieve_ship_inspection = to_streamed_response_wrapper( + funcs.retrieve_ship_inspection, + ) + + +class AsyncFuncsResourceWithStreamingResponse: + def __init__(self, funcs: AsyncFuncsResource) -> None: + self._funcs = funcs + + self.retrieve_logs = async_to_streamed_response_wrapper( + funcs.retrieve_logs, + ) + self.retrieve_metric_aggregates = async_to_streamed_response_wrapper( + funcs.retrieve_metric_aggregates, + ) + self.retrieve_revisions = async_to_streamed_response_wrapper( + funcs.retrieve_revisions, + ) + self.retrieve_ship_inspection = async_to_streamed_response_wrapper( + funcs.retrieve_ship_inspection, + ) diff --git a/src/telnyx/resources/email_messages/email_messages.py b/src/telnyx/resources/email_messages/email_messages.py index 41a7d1549..c8d444293 100644 --- a/src/telnyx/resources/email_messages/email_messages.py +++ b/src/telnyx/resources/email_messages/email_messages.py @@ -382,10 +382,17 @@ def batch( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> EmailMessageBatchResponse: - """ - Creates up to 50 email messages in a single request. + """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. Args: + messages: Array of email messages to send. Up to 1,000 messages per batch request. Each + message is validated and sent independently; per-message failures do not affect + other messages in the batch. + sandbox_mode: Applies sandbox mode to all messages in the batch. Overrides any per-message sandbox_mode in the messages array. @@ -882,10 +889,17 @@ async def batch( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> EmailMessageBatchResponse: - """ - Creates up to 50 email messages in a single request. + """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. Args: + messages: Array of email messages to send. Up to 1,000 messages per batch request. Each + message is validated and sent independently; per-message failures do not affect + other messages in the batch. + sandbox_mode: Applies sandbox mode to all messages in the batch. Overrides any per-message sandbox_mode in the messages array. diff --git a/src/telnyx/resources/messaging_profiles/messaging_profiles.py b/src/telnyx/resources/messaging_profiles/messaging_profiles.py index f3d1e2cc0..f92aebf80 100644 --- a/src/telnyx/resources/messaging_profiles/messaging_profiles.py +++ b/src/telnyx/resources/messaging_profiles/messaging_profiles.py @@ -51,6 +51,7 @@ from ...types.messaging_messaging_profile import MessagingMessagingProfile from ...types.messaging_metrics_time_frame import MessagingMetricsTimeFrame from ...types.url_shortener_settings_param import URLShortenerSettingsParam +from ...types.messaging_profile_features_param import MessagingProfileFeaturesParam from ...types.messaging_profile_create_response import MessagingProfileCreateResponse from ...types.messaging_profile_delete_response import MessagingProfileDeleteResponse from ...types.messaging_profile_update_response import MessagingProfileUpdateResponse @@ -100,6 +101,7 @@ def create( daily_spend_limit: str | Omit = omit, daily_spend_limit_enabled: bool | Omit = omit, enabled: bool | Omit = omit, + features: Optional[MessagingProfileFeaturesParam] | Omit = omit, health_webhook_url: Optional[str] | Omit = omit, mms_fall_back_to_sms: bool | Omit = omit, mms_transcoding: bool | Omit = omit, @@ -141,6 +143,10 @@ def create( enabled: Specifies whether the messaging profile is enabled or not. + features: Telnyx product features the messaging customer can enable on the messaging + profile. Keys map to individual feature flags; unknown keys are accepted and + preserved for forward compatibility with rolling deployments. + health_webhook_url: A URL to receive health check webhooks for numbers in this profile. mms_fall_back_to_sms: enables SMS fallback for MMS messages. @@ -196,6 +202,7 @@ def create( "daily_spend_limit": daily_spend_limit, "daily_spend_limit_enabled": daily_spend_limit_enabled, "enabled": enabled, + "features": features, "health_webhook_url": health_webhook_url, "mms_fall_back_to_sms": mms_fall_back_to_sms, "mms_transcoding": mms_transcoding, @@ -261,6 +268,7 @@ def update( daily_spend_limit: str | Omit = omit, daily_spend_limit_enabled: bool | Omit = omit, enabled: bool | Omit = omit, + features: Optional[MessagingProfileFeaturesParam] | Omit = omit, mms_fall_back_to_sms: bool | Omit = omit, mms_transcoding: bool | Omit = omit, mobile_only: bool | Omit = omit, @@ -300,6 +308,10 @@ def update( enabled: Specifies whether the messaging profile is enabled or not. + features: Telnyx product features the messaging customer can enable on the messaging + profile. Keys map to individual feature flags; unknown keys are accepted and + preserved for forward compatibility with rolling deployments. + mms_fall_back_to_sms: enables SMS fallback for MMS messages. mms_transcoding: enables automated resizing of MMS media. @@ -372,6 +384,7 @@ def update( "daily_spend_limit": daily_spend_limit, "daily_spend_limit_enabled": daily_spend_limit_enabled, "enabled": enabled, + "features": features, "mms_fall_back_to_sms": mms_fall_back_to_sms, "mms_transcoding": mms_transcoding, "mobile_only": mobile_only, @@ -724,6 +737,7 @@ async def create( daily_spend_limit: str | Omit = omit, daily_spend_limit_enabled: bool | Omit = omit, enabled: bool | Omit = omit, + features: Optional[MessagingProfileFeaturesParam] | Omit = omit, health_webhook_url: Optional[str] | Omit = omit, mms_fall_back_to_sms: bool | Omit = omit, mms_transcoding: bool | Omit = omit, @@ -765,6 +779,10 @@ async def create( enabled: Specifies whether the messaging profile is enabled or not. + features: Telnyx product features the messaging customer can enable on the messaging + profile. Keys map to individual feature flags; unknown keys are accepted and + preserved for forward compatibility with rolling deployments. + health_webhook_url: A URL to receive health check webhooks for numbers in this profile. mms_fall_back_to_sms: enables SMS fallback for MMS messages. @@ -820,6 +838,7 @@ async def create( "daily_spend_limit": daily_spend_limit, "daily_spend_limit_enabled": daily_spend_limit_enabled, "enabled": enabled, + "features": features, "health_webhook_url": health_webhook_url, "mms_fall_back_to_sms": mms_fall_back_to_sms, "mms_transcoding": mms_transcoding, @@ -885,6 +904,7 @@ async def update( daily_spend_limit: str | Omit = omit, daily_spend_limit_enabled: bool | Omit = omit, enabled: bool | Omit = omit, + features: Optional[MessagingProfileFeaturesParam] | Omit = omit, mms_fall_back_to_sms: bool | Omit = omit, mms_transcoding: bool | Omit = omit, mobile_only: bool | Omit = omit, @@ -924,6 +944,10 @@ async def update( enabled: Specifies whether the messaging profile is enabled or not. + features: Telnyx product features the messaging customer can enable on the messaging + profile. Keys map to individual feature flags; unknown keys are accepted and + preserved for forward compatibility with rolling deployments. + mms_fall_back_to_sms: enables SMS fallback for MMS messages. mms_transcoding: enables automated resizing of MMS media. @@ -996,6 +1020,7 @@ async def update( "daily_spend_limit": daily_spend_limit, "daily_spend_limit_enabled": daily_spend_limit_enabled, "enabled": enabled, + "features": features, "mms_fall_back_to_sms": mms_fall_back_to_sms, "mms_transcoding": mms_transcoding, "mobile_only": mobile_only, diff --git a/src/telnyx/resources/whatsapp/phone_numbers/phone_numbers.py b/src/telnyx/resources/whatsapp/phone_numbers/phone_numbers.py index 4f57df715..08a1c24ac 100644 --- a/src/telnyx/resources/whatsapp/phone_numbers/phone_numbers.py +++ b/src/telnyx/resources/whatsapp/phone_numbers/phone_numbers.py @@ -51,6 +51,7 @@ ) from ....types.whatsapp.phone_number_get_response import PhoneNumberGetResponse from ....types.whatsapp.phone_number_list_response import PhoneNumberListResponse +from ....types.whatsapp.phone_number_retrieve_phone_number_response import PhoneNumberRetrievePhoneNumberResponse from ....types.whatsapp.phone_number_retrieve_conversation_window_response import ( PhoneNumberRetrieveConversationWindowResponse, ) @@ -298,6 +299,41 @@ def retrieve_conversation_window( cast_to=PhoneNumberRetrieveConversationWindowResponse, ) + def retrieve_phone_number( + self, + phone_number: 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, + ) -> PhoneNumberRetrievePhoneNumberResponse: + """ + Returns one WhatsApp phone number linked to the authenticated Telnyx account. + For a coexistence number in the `syncing` state, the response includes + `sync_progress`. + + 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 phone_number: + raise ValueError(f"Expected a non-empty value for `phone_number` but received {phone_number!r}") + return self._get( + path_template("/whatsapp/phone_numbers/{phone_number}", phone_number=phone_number), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=PhoneNumberRetrievePhoneNumberResponse, + ) + def verify( self, phone_number: str, @@ -575,6 +611,41 @@ async def retrieve_conversation_window( cast_to=PhoneNumberRetrieveConversationWindowResponse, ) + async def retrieve_phone_number( + self, + phone_number: 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, + ) -> PhoneNumberRetrievePhoneNumberResponse: + """ + Returns one WhatsApp phone number linked to the authenticated Telnyx account. + For a coexistence number in the `syncing` state, the response includes + `sync_progress`. + + 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 phone_number: + raise ValueError(f"Expected a non-empty value for `phone_number` but received {phone_number!r}") + return await self._get( + path_template("/whatsapp/phone_numbers/{phone_number}", phone_number=phone_number), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=PhoneNumberRetrievePhoneNumberResponse, + ) + async def verify( self, phone_number: str, @@ -631,6 +702,9 @@ def __init__(self, phone_numbers: PhoneNumbersResource) -> None: self.retrieve_conversation_window = to_raw_response_wrapper( phone_numbers.retrieve_conversation_window, ) + self.retrieve_phone_number = to_raw_response_wrapper( + phone_numbers.retrieve_phone_number, + ) self.verify = to_raw_response_wrapper( phone_numbers.verify, ) @@ -670,6 +744,9 @@ def __init__(self, phone_numbers: AsyncPhoneNumbersResource) -> None: self.retrieve_conversation_window = async_to_raw_response_wrapper( phone_numbers.retrieve_conversation_window, ) + self.retrieve_phone_number = async_to_raw_response_wrapper( + phone_numbers.retrieve_phone_number, + ) self.verify = async_to_raw_response_wrapper( phone_numbers.verify, ) @@ -709,6 +786,9 @@ def __init__(self, phone_numbers: PhoneNumbersResource) -> None: self.retrieve_conversation_window = to_streamed_response_wrapper( phone_numbers.retrieve_conversation_window, ) + self.retrieve_phone_number = to_streamed_response_wrapper( + phone_numbers.retrieve_phone_number, + ) self.verify = to_streamed_response_wrapper( phone_numbers.verify, ) @@ -748,6 +828,9 @@ def __init__(self, phone_numbers: AsyncPhoneNumbersResource) -> None: self.retrieve_conversation_window = async_to_streamed_response_wrapper( phone_numbers.retrieve_conversation_window, ) + self.retrieve_phone_number = async_to_streamed_response_wrapper( + phone_numbers.retrieve_phone_number, + ) self.verify = async_to_streamed_response_wrapper( phone_numbers.verify, ) diff --git a/src/telnyx/resources/x402/credit_account/__init__.py b/src/telnyx/resources/x402/credit_account/__init__.py new file mode 100644 index 000000000..2bfff4bb2 --- /dev/null +++ b/src/telnyx/resources/x402/credit_account/__init__.py @@ -0,0 +1,33 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from .payments import ( + PaymentsResource, + AsyncPaymentsResource, + PaymentsResourceWithRawResponse, + AsyncPaymentsResourceWithRawResponse, + PaymentsResourceWithStreamingResponse, + AsyncPaymentsResourceWithStreamingResponse, +) +from .credit_account import ( + CreditAccountResource, + AsyncCreditAccountResource, + CreditAccountResourceWithRawResponse, + AsyncCreditAccountResourceWithRawResponse, + CreditAccountResourceWithStreamingResponse, + AsyncCreditAccountResourceWithStreamingResponse, +) + +__all__ = [ + "PaymentsResource", + "AsyncPaymentsResource", + "PaymentsResourceWithRawResponse", + "AsyncPaymentsResourceWithRawResponse", + "PaymentsResourceWithStreamingResponse", + "AsyncPaymentsResourceWithStreamingResponse", + "CreditAccountResource", + "AsyncCreditAccountResource", + "CreditAccountResourceWithRawResponse", + "AsyncCreditAccountResourceWithRawResponse", + "CreditAccountResourceWithStreamingResponse", + "AsyncCreditAccountResourceWithStreamingResponse", +] diff --git a/src/telnyx/resources/x402/credit_account.py b/src/telnyx/resources/x402/credit_account/credit_account.py similarity index 79% rename from src/telnyx/resources/x402/credit_account.py rename to src/telnyx/resources/x402/credit_account/credit_account.py index 21c3256d3..0d4926905 100644 --- a/src/telnyx/resources/x402/credit_account.py +++ b/src/telnyx/resources/x402/credit_account/credit_account.py @@ -4,20 +4,28 @@ import httpx -from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given -from ..._utils import maybe_transform, strip_not_given, async_maybe_transform -from ..._compat import cached_property -from ..._resource import SyncAPIResource, AsyncAPIResource -from ..._response import ( +from .payments import ( + PaymentsResource, + AsyncPaymentsResource, + PaymentsResourceWithRawResponse, + AsyncPaymentsResourceWithRawResponse, + PaymentsResourceWithStreamingResponse, + AsyncPaymentsResourceWithStreamingResponse, +) +from ...._types import Body, Omit, Query, Headers, NotGiven, omit, not_given +from ...._utils import maybe_transform, strip_not_given, 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.x402 import credit_account_settle_params, credit_account_create_quote_params -from ..._base_client import make_request_options -from ...types.x402.credit_account_settle_response import CreditAccountSettleResponse -from ...types.x402.credit_account_create_quote_response import CreditAccountCreateQuoteResponse +from ....types.x402 import credit_account_settle_params, credit_account_create_quote_params +from ...._base_client import make_request_options +from ....types.x402.credit_account_settle_response import CreditAccountSettleResponse +from ....types.x402.credit_account_create_quote_response import CreditAccountCreateQuoteResponse __all__ = ["CreditAccountResource", "AsyncCreditAccountResource"] @@ -28,6 +36,14 @@ class CreditAccountResource(SyncAPIResource): Fund your Telnyx account using USDC stablecoin payments via the x402 protocol. """ + @cached_property + def payments(self) -> PaymentsResource: + """Operations for x402 cryptocurrency payment transactions. + + Fund your Telnyx account using USDC stablecoin payments via the x402 protocol. + """ + return PaymentsResource(self._client) + @cached_property def with_raw_response(self) -> CreditAccountResourceWithRawResponse: """ @@ -76,7 +92,7 @@ def create_quote( timeout: Override the client-level default timeout for this request, in seconds """ return self._post( - "/v2/x402/credit_account/quote", + "/x402/credit_account/quote", body=maybe_transform( {"amount_usd": amount_usd}, credit_account_create_quote_params.CreditAccountCreateQuoteParams ), @@ -121,7 +137,7 @@ def settle( """ extra_headers = {**strip_not_given({"PAYMENT-SIGNATURE": header_payment_signature}), **(extra_headers or {})} return self._post( - "/v2/x402/credit_account", + "/x402/credit_account", body=maybe_transform( { "id": id, @@ -142,6 +158,14 @@ class AsyncCreditAccountResource(AsyncAPIResource): Fund your Telnyx account using USDC stablecoin payments via the x402 protocol. """ + @cached_property + def payments(self) -> AsyncPaymentsResource: + """Operations for x402 cryptocurrency payment transactions. + + Fund your Telnyx account using USDC stablecoin payments via the x402 protocol. + """ + return AsyncPaymentsResource(self._client) + @cached_property def with_raw_response(self) -> AsyncCreditAccountResourceWithRawResponse: """ @@ -190,7 +214,7 @@ async def create_quote( timeout: Override the client-level default timeout for this request, in seconds """ return await self._post( - "/v2/x402/credit_account/quote", + "/x402/credit_account/quote", body=await async_maybe_transform( {"amount_usd": amount_usd}, credit_account_create_quote_params.CreditAccountCreateQuoteParams ), @@ -235,7 +259,7 @@ async def settle( """ extra_headers = {**strip_not_given({"PAYMENT-SIGNATURE": header_payment_signature}), **(extra_headers or {})} return await self._post( - "/v2/x402/credit_account", + "/x402/credit_account", body=await async_maybe_transform( { "id": id, @@ -261,6 +285,14 @@ def __init__(self, credit_account: CreditAccountResource) -> None: credit_account.settle, ) + @cached_property + def payments(self) -> PaymentsResourceWithRawResponse: + """Operations for x402 cryptocurrency payment transactions. + + Fund your Telnyx account using USDC stablecoin payments via the x402 protocol. + """ + return PaymentsResourceWithRawResponse(self._credit_account.payments) + class AsyncCreditAccountResourceWithRawResponse: def __init__(self, credit_account: AsyncCreditAccountResource) -> None: @@ -273,6 +305,14 @@ def __init__(self, credit_account: AsyncCreditAccountResource) -> None: credit_account.settle, ) + @cached_property + def payments(self) -> AsyncPaymentsResourceWithRawResponse: + """Operations for x402 cryptocurrency payment transactions. + + Fund your Telnyx account using USDC stablecoin payments via the x402 protocol. + """ + return AsyncPaymentsResourceWithRawResponse(self._credit_account.payments) + class CreditAccountResourceWithStreamingResponse: def __init__(self, credit_account: CreditAccountResource) -> None: @@ -285,6 +325,14 @@ def __init__(self, credit_account: CreditAccountResource) -> None: credit_account.settle, ) + @cached_property + def payments(self) -> PaymentsResourceWithStreamingResponse: + """Operations for x402 cryptocurrency payment transactions. + + Fund your Telnyx account using USDC stablecoin payments via the x402 protocol. + """ + return PaymentsResourceWithStreamingResponse(self._credit_account.payments) + class AsyncCreditAccountResourceWithStreamingResponse: def __init__(self, credit_account: AsyncCreditAccountResource) -> None: @@ -296,3 +344,11 @@ def __init__(self, credit_account: AsyncCreditAccountResource) -> None: self.settle = async_to_streamed_response_wrapper( credit_account.settle, ) + + @cached_property + def payments(self) -> AsyncPaymentsResourceWithStreamingResponse: + """Operations for x402 cryptocurrency payment transactions. + + Fund your Telnyx account using USDC stablecoin payments via the x402 protocol. + """ + return AsyncPaymentsResourceWithStreamingResponse(self._credit_account.payments) diff --git a/src/telnyx/resources/x402/credit_account/payments.py b/src/telnyx/resources/x402/credit_account/payments.py new file mode 100644 index 000000000..5d4528fb5 --- /dev/null +++ b/src/telnyx/resources/x402/credit_account/payments.py @@ -0,0 +1,295 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import httpx + +from ...._types import Body, Omit, Query, Headers, NotGiven, omit, not_given +from ...._utils import path_template, maybe_transform +from ...._compat import cached_property +from ...._resource import SyncAPIResource, AsyncAPIResource +from ...._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ....pagination import SyncDefaultFlatPagination, AsyncDefaultFlatPagination +from ...._base_client import AsyncPaginator, make_request_options +from ....types.x402.credit_account import payment_list_params +from ....types.x402.credit_account.x402_transaction_record import X402TransactionRecord +from ....types.x402.credit_account.payment_retrieve_response import PaymentRetrieveResponse + +__all__ = ["PaymentsResource", "AsyncPaymentsResource"] + + +class PaymentsResource(SyncAPIResource): + """Operations for x402 cryptocurrency payment transactions. + + Fund your Telnyx account using USDC stablecoin payments via the x402 protocol. + """ + + @cached_property + def with_raw_response(self) -> PaymentsResourceWithRawResponse: + """ + 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 PaymentsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> PaymentsResourceWithStreamingResponse: + """ + 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 PaymentsResourceWithStreamingResponse(self) + + def retrieve( + 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, + ) -> PaymentRetrieveResponse: + """Returns a single x402 payment transaction by ID. + + The transaction must belong to + the authenticated user; organization sub-users must have read permission on + transactions. Returns 404 if the transaction does not exist or belongs to + another user. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return self._get( + path_template("/x402/credit_account/payments/{id}", id=id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=PaymentRetrieveResponse, + ) + + def list( + self, + *, + page_number: int | Omit = omit, + page_size: int | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> SyncDefaultFlatPagination[X402TransactionRecord]: + """ + Returns a paginated list of the authenticated user's x402 payment transactions, + newest first. Organization sub-users must have read permission on transactions; + without it the list is empty. + + Args: + page_number: The page number to load. + + page_size: The size of the page. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._get_api_list( + "/x402/credit_account/payments", + page=SyncDefaultFlatPagination[X402TransactionRecord], + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "page_number": page_number, + "page_size": page_size, + }, + payment_list_params.PaymentListParams, + ), + ), + model=X402TransactionRecord, + ) + + +class AsyncPaymentsResource(AsyncAPIResource): + """Operations for x402 cryptocurrency payment transactions. + + Fund your Telnyx account using USDC stablecoin payments via the x402 protocol. + """ + + @cached_property + def with_raw_response(self) -> AsyncPaymentsResourceWithRawResponse: + """ + 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 AsyncPaymentsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncPaymentsResourceWithStreamingResponse: + """ + 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 AsyncPaymentsResourceWithStreamingResponse(self) + + async def retrieve( + 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, + ) -> PaymentRetrieveResponse: + """Returns a single x402 payment transaction by ID. + + The transaction must belong to + the authenticated user; organization sub-users must have read permission on + transactions. Returns 404 if the transaction does not exist or belongs to + another user. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return await self._get( + path_template("/x402/credit_account/payments/{id}", id=id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=PaymentRetrieveResponse, + ) + + def list( + self, + *, + page_number: int | Omit = omit, + page_size: int | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> AsyncPaginator[X402TransactionRecord, AsyncDefaultFlatPagination[X402TransactionRecord]]: + """ + Returns a paginated list of the authenticated user's x402 payment transactions, + newest first. Organization sub-users must have read permission on transactions; + without it the list is empty. + + Args: + page_number: The page number to load. + + page_size: The size of the page. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._get_api_list( + "/x402/credit_account/payments", + page=AsyncDefaultFlatPagination[X402TransactionRecord], + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "page_number": page_number, + "page_size": page_size, + }, + payment_list_params.PaymentListParams, + ), + ), + model=X402TransactionRecord, + ) + + +class PaymentsResourceWithRawResponse: + def __init__(self, payments: PaymentsResource) -> None: + self._payments = payments + + self.retrieve = to_raw_response_wrapper( + payments.retrieve, + ) + self.list = to_raw_response_wrapper( + payments.list, + ) + + +class AsyncPaymentsResourceWithRawResponse: + def __init__(self, payments: AsyncPaymentsResource) -> None: + self._payments = payments + + self.retrieve = async_to_raw_response_wrapper( + payments.retrieve, + ) + self.list = async_to_raw_response_wrapper( + payments.list, + ) + + +class PaymentsResourceWithStreamingResponse: + def __init__(self, payments: PaymentsResource) -> None: + self._payments = payments + + self.retrieve = to_streamed_response_wrapper( + payments.retrieve, + ) + self.list = to_streamed_response_wrapper( + payments.list, + ) + + +class AsyncPaymentsResourceWithStreamingResponse: + def __init__(self, payments: AsyncPaymentsResource) -> None: + self._payments = payments + + self.retrieve = async_to_streamed_response_wrapper( + payments.retrieve, + ) + self.list = async_to_streamed_response_wrapper( + payments.list, + ) diff --git a/src/telnyx/resources/x402/x402.py b/src/telnyx/resources/x402/x402.py index 456197384..160daf9be 100644 --- a/src/telnyx/resources/x402/x402.py +++ b/src/telnyx/resources/x402/x402.py @@ -4,7 +4,7 @@ from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource -from .credit_account import ( +from .credit_account.credit_account import ( CreditAccountResource, AsyncCreditAccountResource, CreditAccountResourceWithRawResponse, diff --git a/src/telnyx/types/__init__.py b/src/telnyx/types/__init__.py index 7b01c411d..8b22e9ea8 100644 --- a/src/telnyx/types/__init__.py +++ b/src/telnyx/types/__init__.py @@ -313,6 +313,7 @@ from .uac_internal_settings import UacInternalSettings as UacInternalSettings from .voice_design_response import VoiceDesignResponse as VoiceDesignResponse from .voice_sdk_call_report import VoiceSDKCallReport as VoiceSDKCallReport +from .whatsapp_message_echo import WhatsappMessageEcho as WhatsappMessageEcho from .alphanumeric_sender_id import AlphanumericSenderID as AlphanumericSenderID from .call_event_list_params import CallEventListParams as CallEventListParams from .call_streaming_started import CallStreamingStarted as CallStreamingStarted @@ -397,6 +398,7 @@ from .transcribe_client_event import TranscribeClientEvent as TranscribeClientEvent from .transcribe_server_event import TranscribeServerEvent as TranscribeServerEvent from .voice_clone_list_params import VoiceCloneListParams as VoiceCloneListParams +from .whatsapp_account_update import WhatsappAccountUpdate as WhatsappAccountUpdate from .whatsapp_location_param import WhatsappLocationParam as WhatsappLocationParam from .whatsapp_reaction_param import WhatsappReactionParam as WhatsappReactionParam from .attachment_request_param import AttachmentRequestParam as AttachmentRequestParam @@ -501,6 +503,7 @@ from .infringement_claim_wrapped import InfringementClaimWrapped as InfringementClaimWrapped from .list_retrieve_all_response import ListRetrieveAllResponse as ListRetrieveAllResponse from .messaging_error_0b38e7044b import MessagingError0b38e7044b as MessagingError0b38e7044b +from .messaging_profile_features import MessagingProfileFeatures as MessagingProfileFeatures from .number_order_create_params import NumberOrderCreateParams as NumberOrderCreateParams from .number_order_list_response import NumberOrderListResponse as NumberOrderListResponse from .number_order_update_params import NumberOrderUpdateParams as NumberOrderUpdateParams @@ -792,6 +795,7 @@ from .integration_secret_create_params import IntegrationSecretCreateParams as IntegrationSecretCreateParams from .inventory_coverage_list_response import InventoryCoverageListResponse as InventoryCoverageListResponse from .message_send_short_code_response import MessageSendShortCodeResponse as MessageSendShortCodeResponse +from .messaging_profile_features_param import MessagingProfileFeaturesParam as MessagingProfileFeaturesParam from .messaging_url_domain_list_params import MessagingURLDomainListParams as MessagingURLDomainListParams from .network_list_interfaces_response import NetworkListInterfacesResponse as NetworkListInterfacesResponse from .notification_channel_list_params import NotificationChannelListParams as NotificationChannelListParams diff --git a/src/telnyx/types/ai/__init__.py b/src/telnyx/types/ai/__init__.py index e5dceb21b..bbd64274b 100644 --- a/src/telnyx/types/ai/__init__.py +++ b/src/telnyx/types/ai/__init__.py @@ -60,6 +60,7 @@ from .assistant_send_sms_params import AssistantSendSMSParams as AssistantSendSMSParams from .fallback_config_req_param import FallbackConfigReqParam as FallbackConfigReqParam from .start_speaking_plan_param import StartSpeakingPlanParam as StartSpeakingPlanParam +from .assistant_a2_a_agent_param import AssistantA2AAgentParam as AssistantA2AAgentParam from .assistant_mcp_server_param import AssistantMcpServerParam as AssistantMcpServerParam from .cluster_fetch_graph_params import ClusterFetchGraphParams as ClusterFetchGraphParams from .conversation_create_params import ConversationCreateParams as ConversationCreateParams @@ -122,6 +123,7 @@ from .collection_envelope import CollectionEnvelope as CollectionEnvelope from .inference_embedding import InferenceEmbedding as InferenceEmbedding from .start_speaking_plan import StartSpeakingPlan as StartSpeakingPlan + from .assistant_a2_a_agent import AssistantA2AAgent as AssistantA2AAgent from .assistant_mcp_server import AssistantMcpServer as AssistantMcpServer from .events_list_response import EventsListResponse as EventsListResponse from .shared_tool_response import SharedToolResponse as SharedToolResponse @@ -162,6 +164,10 @@ def __getattr__(name: str) -> Any: + if name == "AssistantA2AAgent": + from .assistant_a2_a_agent import AssistantA2AAgent + + return AssistantA2AAgent if name == "AssistantIntegration": from .assistant_integration import AssistantIntegration diff --git a/src/telnyx/types/ai/assistant_a2_a_agent.py b/src/telnyx/types/ai/assistant_a2_a_agent.py new file mode 100644 index 000000000..8155830a9 --- /dev/null +++ b/src/telnyx/types/ai/assistant_a2_a_agent.py @@ -0,0 +1,130 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import List, Union, Optional +from typing_extensions import Literal, TypeAlias + +from pydantic import Field as FieldInfo + +from ..._models import BaseModel + +__all__ = [ + "AssistantA2AAgent", + "Header", + "Message", + "MessageA2AAgentRequestStartMessage", + "MessageA2AAgentRequestResponseDelayedMessage", +] + + +class Header(BaseModel): + """ + A header sent when fetching an A2A agent's card and on every call made to that agent. + """ + + name: str + """HTTP header name. + + May only contain alphanumeric characters, hyphens, and underscores, or a + `{{dynamic_variable}}` placeholder surrounded by those characters. + """ + + value: str + """Header value, stored exactly as written. + + It may be a literal, a `{{dynamic_variable}}`, or an + `{{#integration_secret}}identifier{{/integration_secret}}` section that resolves + to a stored integration secret when the conversation starts. Control characters + are not allowed. The encrypted `{{variable | encryption_secret_ref}}` form used + for per-caller credentials is not resolved here and is rejected when the + assistant is saved. + """ + + +class MessageA2AAgentRequestStartMessage(BaseModel): + content: str + """The text the assistant speaks.""" + + type: Literal["request_start"] + """Speak the filler message immediately when the call to the agent begins.""" + + timing_ms: Optional[int] = None + """An optional delay value. This value is ignored for `request_start` messages.""" + + +class MessageA2AAgentRequestResponseDelayedMessage(BaseModel): + content: str + """The text the assistant speaks.""" + + timing_ms: int + """How long to wait, in milliseconds, before speaking this message.""" + + type: Literal["request_response_delayed"] + """ + Speak the filler message only if the agent has not answered yet after + `timing_ms`. + """ + + +Message: TypeAlias = Union[MessageA2AAgentRequestStartMessage, MessageA2AAgentRequestResponseDelayedMessage] + + +class AssistantA2AAgent(BaseModel): + """ + A remote agent, reachable over the A2A (Agent2Agent) protocol, that an assistant can delegate to. Tools are not configured here: at the start of every conversation the agent's card is fetched and one tool is derived per skill the card advertises. + """ + + name: str + """ + Identifies the agent and seeds the names of the tools derived from its card + (`a2a__`). Characters outside `[A-Za-z0-9_]` are replaced with + `_` before the tool name is built, so two agents whose names differ only in + punctuation collide and are rejected. + """ + + url: str + """The agent's base URL, or the URL of its agent card. + + At most 2,048 bytes once UTF-8 encoded. `/.well-known/agent-card.json` is + appended to the path unless it already ends in `.json`. Must be an `http://` or + `https://` URL for an externally reachable host: internal destinations + (`localhost`, private and reserved IP ranges, `.local` domains) are rejected, + and the hostname may not contain a `{{...}}` placeholder. Placeholders in the + path are allowed. + """ + + async_: Optional[bool] = FieldInfo(alias="async", default=None) + """ + When `true`, the assistant hands the turn straight back to the model and the + agent's answer is delivered into the conversation once it arrives, instead of + the caller waiting for it in silence. + """ + + headers: Optional[List[Header]] = None + """Headers sent when fetching this agent's card and on every call made to it. + + Use them to authenticate to the agent. + """ + + messages: Optional[List[Message]] = None + """Filler messages spoken while a call to this agent is in progress. + + `request_start` messages are spoken immediately when the call begins. + `request_response_delayed` messages are spoken after `timing_ms` has elapsed + only if the agent has not answered yet. Filler messages are not used when + `async` is `true`. + """ + + poll_interval_ms: Optional[int] = None + """How often, in milliseconds, to poll an agent task that has not finished yet. + + Defaults to 500. + """ + + timeout_ms: Optional[int] = None + """ + Total budget, in milliseconds, for one call to this agent, including any time + spent polling a task that is still running. Omit to inherit the assistant's tool + timeout. + """ diff --git a/src/telnyx/types/ai/assistant_a2_a_agent_param.py b/src/telnyx/types/ai/assistant_a2_a_agent_param.py new file mode 100644 index 000000000..29bcd9b77 --- /dev/null +++ b/src/telnyx/types/ai/assistant_a2_a_agent_param.py @@ -0,0 +1,127 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Union, Iterable +from typing_extensions import Literal, Required, TypeAlias, TypedDict + +__all__ = [ + "AssistantA2AAgentParam", + "Header", + "Message", + "MessageA2AAgentRequestStartMessage", + "MessageA2AAgentRequestResponseDelayedMessage", +] + + +class Header(TypedDict, total=False): + """ + A header sent when fetching an A2A agent's card and on every call made to that agent. + """ + + name: Required[str] + """HTTP header name. + + May only contain alphanumeric characters, hyphens, and underscores, or a + `{{dynamic_variable}}` placeholder surrounded by those characters. + """ + + value: Required[str] + """Header value, stored exactly as written. + + It may be a literal, a `{{dynamic_variable}}`, or an + `{{#integration_secret}}identifier{{/integration_secret}}` section that resolves + to a stored integration secret when the conversation starts. Control characters + are not allowed. The encrypted `{{variable | encryption_secret_ref}}` form used + for per-caller credentials is not resolved here and is rejected when the + assistant is saved. + """ + + +class MessageA2AAgentRequestStartMessage(TypedDict, total=False): + content: Required[str] + """The text the assistant speaks.""" + + type: Required[Literal["request_start"]] + """Speak the filler message immediately when the call to the agent begins.""" + + timing_ms: int + """An optional delay value. This value is ignored for `request_start` messages.""" + + +class MessageA2AAgentRequestResponseDelayedMessage(TypedDict, total=False): + content: Required[str] + """The text the assistant speaks.""" + + timing_ms: Required[int] + """How long to wait, in milliseconds, before speaking this message.""" + + type: Required[Literal["request_response_delayed"]] + """ + Speak the filler message only if the agent has not answered yet after + `timing_ms`. + """ + + +Message: TypeAlias = Union[MessageA2AAgentRequestStartMessage, MessageA2AAgentRequestResponseDelayedMessage] + +_AssistantA2AAgentParamReservedKeywords = TypedDict( + "_AssistantA2AAgentParamReservedKeywords", + { + "async": bool, + }, + total=False, +) + + +class AssistantA2AAgentParam(_AssistantA2AAgentParamReservedKeywords, total=False): + """ + A remote agent, reachable over the A2A (Agent2Agent) protocol, that an assistant can delegate to. Tools are not configured here: at the start of every conversation the agent's card is fetched and one tool is derived per skill the card advertises. + """ + + name: Required[str] + """ + Identifies the agent and seeds the names of the tools derived from its card + (`a2a__`). Characters outside `[A-Za-z0-9_]` are replaced with + `_` before the tool name is built, so two agents whose names differ only in + punctuation collide and are rejected. + """ + + url: Required[str] + """The agent's base URL, or the URL of its agent card. + + At most 2,048 bytes once UTF-8 encoded. `/.well-known/agent-card.json` is + appended to the path unless it already ends in `.json`. Must be an `http://` or + `https://` URL for an externally reachable host: internal destinations + (`localhost`, private and reserved IP ranges, `.local` domains) are rejected, + and the hostname may not contain a `{{...}}` placeholder. Placeholders in the + path are allowed. + """ + + headers: Iterable[Header] + """Headers sent when fetching this agent's card and on every call made to it. + + Use them to authenticate to the agent. + """ + + messages: Iterable[Message] + """Filler messages spoken while a call to this agent is in progress. + + `request_start` messages are spoken immediately when the call begins. + `request_response_delayed` messages are spoken after `timing_ms` has elapsed + only if the agent has not answered yet. Filler messages are not used when + `async` is `true`. + """ + + poll_interval_ms: int + """How often, in milliseconds, to poll an agent task that has not finished yet. + + Defaults to 500. + """ + + timeout_ms: int + """ + Total budget, in milliseconds, for one call to this agent, including any time + spent polling a task that is still running. Omit to inherit the assistant's tool + timeout. + """ diff --git a/src/telnyx/types/ai/assistant_create_params.py b/src/telnyx/types/ai/assistant_create_params.py index 670ae88ef..e579df2d1 100644 --- a/src/telnyx/types/ai/assistant_create_params.py +++ b/src/telnyx/types/ai/assistant_create_params.py @@ -18,6 +18,7 @@ from .messaging_settings_param import MessagingSettingsParam from .telephony_settings_param import TelephonySettingsParam from .fallback_config_req_param import FallbackConfigReqParam +from .assistant_a2_a_agent_param import AssistantA2AAgentParam from .assistant_mcp_server_param import AssistantMcpServerParam from .assistant_integration_param import AssistantIntegrationParam from .conversation_flow_req_param import ConversationFlowReqParam @@ -38,6 +39,19 @@ class AssistantCreateParams(TypedDict, total=False): name: Required[str] + a2a_agents: Iterable[AssistantA2AAgentParam] + """A2A agents this assistant can delegate to. + + Tools are not stored here: at the start of every conversation each agent's card + is fetched and one tool is derived per skill the card advertises, named + `a2a__`. The following limits are not enforced when the + assistant is saved, and anything past them is dropped when the conversation + starts: 64 agents per assistant, 64 skills per card, 128 derived tools per + assistant, and a 6 second budget for all card fetches combined. An agent whose + card cannot be fetched costs the assistant that capability for the conversation; + it does not fail the call. + """ + conversation_flow: ConversationFlowReqParam """Conversation flow as supplied by API clients (create / update). diff --git a/src/telnyx/types/ai/assistant_update_params.py b/src/telnyx/types/ai/assistant_update_params.py index 09633fe25..0ea5158a4 100644 --- a/src/telnyx/types/ai/assistant_update_params.py +++ b/src/telnyx/types/ai/assistant_update_params.py @@ -17,6 +17,7 @@ from .messaging_settings_param import MessagingSettingsParam from .telephony_settings_param import TelephonySettingsParam from .fallback_config_req_param import FallbackConfigReqParam +from .assistant_a2_a_agent_param import AssistantA2AAgentParam from .assistant_mcp_server_param import AssistantMcpServerParam from .assistant_integration_param import AssistantIntegrationParam from .conversation_flow_req_param import ConversationFlowReqParam @@ -28,6 +29,20 @@ class AssistantUpdateParams(TypedDict, total=False): + a2a_agents: Iterable[AssistantA2AAgentParam] + """A2A agents this assistant can delegate to. + + Tools are not stored here: at the start of every conversation each agent's card + is fetched and one tool is derived per skill the card advertises, named + `a2a__`. The following limits are not enforced when the + assistant is saved, and anything past them is dropped when the conversation + starts: 64 agents per assistant, 64 skills per card, 128 derived tools per + assistant, and a 6 second budget for all card fetches combined. An agent whose + card cannot be fetched costs the assistant that capability for the conversation; + it does not fail the call. Omit this field to leave the assistant's agents + unchanged; send an empty array to remove them all. + """ + conversation_flow: ConversationFlowReqParam """Conversation flow as supplied by API clients (create / update). diff --git a/src/telnyx/types/ai/assistants/version_update_params.py b/src/telnyx/types/ai/assistants/version_update_params.py index 1aea2a2dc..66a52f5b6 100644 --- a/src/telnyx/types/ai/assistants/version_update_params.py +++ b/src/telnyx/types/ai/assistants/version_update_params.py @@ -17,6 +17,7 @@ from ..messaging_settings_param import MessagingSettingsParam from ..telephony_settings_param import TelephonySettingsParam from ..fallback_config_req_param import FallbackConfigReqParam +from ..assistant_a2_a_agent_param import AssistantA2AAgentParam from ..assistant_mcp_server_param import AssistantMcpServerParam from ..assistant_integration_param import AssistantIntegrationParam from ..conversation_flow_req_param import ConversationFlowReqParam @@ -30,6 +31,20 @@ class VersionUpdateParams(TypedDict, total=False): assistant_id: Required[str] + a2a_agents: Iterable[AssistantA2AAgentParam] + """A2A agents this assistant can delegate to. + + Tools are not stored here: at the start of every conversation each agent's card + is fetched and one tool is derived per skill the card advertises, named + `a2a__`. The following limits are not enforced when the + assistant is saved, and anything past them is dropped when the conversation + starts: 64 agents per assistant, 64 skills per card, 128 derived tools per + assistant, and a 6 second budget for all card fetches combined. An agent whose + card cannot be fetched costs the assistant that capability for the conversation; + it does not fail the call. Omit this field to leave the assistant's agents + unchanged; send an empty array to remove them all. + """ + conversation_flow: ConversationFlowReqParam """Conversation flow as supplied by API clients (create / update). diff --git a/src/telnyx/types/ai/inference_embedding.py b/src/telnyx/types/ai/inference_embedding.py index 65d1659cf..373c03b9e 100644 --- a/src/telnyx/types/ai/inference_embedding.py +++ b/src/telnyx/types/ai/inference_embedding.py @@ -19,6 +19,7 @@ from .conversation_flow import ConversationFlow from .messaging_settings import MessagingSettings from .telephony_settings import TelephonySettings +from .assistant_a2_a_agent import AssistantA2AAgent from .assistant_mcp_server import AssistantMcpServer from .assistant_integration import AssistantIntegration from .transcription_settings import TranscriptionSettings @@ -52,6 +53,19 @@ class InferenceEmbedding(BaseModel): name: str + a2a_agents: Optional[List[AssistantA2AAgent]] = None + """A2A agents this assistant can delegate to. + + Tools are not stored here: at the start of every conversation each agent's card + is fetched and one tool is derived per skill the card advertises, named + `a2a__`. The following limits are not enforced when the + assistant is saved, and anything past them is dropped when the conversation + starts: 64 agents per assistant, 64 skills per card, 128 derived tools per + assistant, and a 6 second budget for all card fetches combined. An agent whose + card cannot be fetched costs the assistant that capability for the conversation; + it does not fail the call. + """ + conversation_flow: Optional[ConversationFlow] = None """Conversation flow as returned by the API.""" 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 051918210..4570e5a4d 100644 --- a/src/telnyx/types/ai/openai/chat_create_completion_params.py +++ b/src/telnyx/types/ai/openai/chat_create_completion_params.py @@ -13,6 +13,10 @@ "Message", "MessageContentTextAndImageArray", "ResponseFormat", + "ResponseFormatResponseFormatText", + "ResponseFormatResponseFormatJsonObject", + "ResponseFormatResponseFormatJsonSchemaParam", + "ResponseFormatResponseFormatJsonSchemaParamJsonSchema", "Tool", "ToolFunction", "ToolFunctionFunction", @@ -56,18 +60,6 @@ class ChatCreateCompletionParams(TypedDict, total=False): frequency_penalty: float """Higher values will penalize the model from repeating the same output tokens.""" - guided_choice: SequenceNotStr[str] - """If specified, the output will be exactly one of the choices.""" - - guided_json: Dict[str, object] - """Must be a valid JSON schema. - - If specified, the output will follow the JSON schema. - """ - - guided_regex: str - """If specified, the output will follow the regex pattern.""" - length_penalty: float """This is used with `use_beam_search` to prefer shorter or longer completions.""" @@ -126,9 +118,12 @@ class ChatCreateCompletionParams(TypedDict, total=False): """ response_format: ResponseFormat - """Use this is you want to guarantee a JSON output without defining a schema. + """Controls the format of the model output. - For control over the schema, use `guided_json`. + `json_object` guarantees valid JSON output without defining a schema; + `json_schema` constrains the output to the JSON schema you supply via the + `json_schema` property and is the supported way to get guaranteed structured + output on Telnyx-hosted models. """ seed: int @@ -207,13 +202,69 @@ class Message(TypedDict, total=False): role: Required[Literal["system", "user", "assistant", "tool"]] -class ResponseFormat(TypedDict, total=False): - """Use this is you want to guarantee a JSON output without defining a schema. +class ResponseFormatResponseFormatText(TypedDict, total=False): + """Plain text output.""" + + type: Required[Literal["text"]] + + +class ResponseFormatResponseFormatJsonObject(TypedDict, total=False): + """JSON mode: the model output is valid JSON, without a schema.""" + + type: Required[Literal["json_object"]] - For control over the schema, use `guided_json`. + +class ResponseFormatResponseFormatJsonSchemaParamJsonSchema(TypedDict, total=False): + """The JSON schema configuration, required when `type` is `json_schema`. + + Matches the [OpenAI structured outputs](https://platform.openai.com/docs/guides/structured-outputs) `json_schema` response format. + """ + + name: Required[str] + """The name of the response format. Used for clarity only.""" + + description: str + """ + A description of what the response format is for, typically used to guide the + model. """ - type: Required[Literal["text", "json_object"]] + schema: Dict[str, object] + """The JSON schema the model output must conform to. + + A valid [JSON Schema](https://json-schema.org) object, e.g. a Pydantic + `model_json_schema()` export. + """ + + strict: bool + """Enables strict schema adherence when supported by the model. + + If the generated output does not match the provided schema, the request fails + instead of returning non-conformant output. + """ + + +class ResponseFormatResponseFormatJsonSchemaParam(TypedDict, total=False): + """ + Structured output: the model output is constrained to the JSON schema supplied in `json_schema`. + """ + + json_schema: Required[ResponseFormatResponseFormatJsonSchemaParamJsonSchema] + """The JSON schema configuration, required when `type` is `json_schema`. + + Matches the + [OpenAI structured outputs](https://platform.openai.com/docs/guides/structured-outputs) + `json_schema` response format. + """ + + type: Required[Literal["json_schema"]] + + +ResponseFormat: TypeAlias = Union[ + ResponseFormatResponseFormatText, + ResponseFormatResponseFormatJsonObject, + ResponseFormatResponseFormatJsonSchemaParam, +] class ToolFunctionFunction(TypedDict, total=False): diff --git a/src/telnyx/types/ai/telephony_settings.py b/src/telnyx/types/ai/telephony_settings.py index 44137d173..5e64f5302 100644 --- a/src/telnyx/types/ai/telephony_settings.py +++ b/src/telnyx/types/ai/telephony_settings.py @@ -116,6 +116,17 @@ class TelephonySettings(BaseModel): the main tool array or on any workflow node — enforced at write time. """ + fallback_destination: Optional[str] = None + """ + Destination number or SIP URI to transfer the caller to when the AI conversation + ends abnormally, for example because of an assistant-side error, so the caller + is not left in dead air. This only fires for abnormal ends: it does not fire + when the conversation ends on purpose (the caller hung up, the assistant + completed normally, the caller hung up after a relay handoff, or voicemail was + detected), and it does not fire when the assistant already transferred or + bridged the call. + """ + noise_suppression: Optional[Literal["krisp", "deepfilternet", "disabled"]] = None """The noise suppression engine to use. diff --git a/src/telnyx/types/ai/telephony_settings_param.py b/src/telnyx/types/ai/telephony_settings_param.py index ce37701ca..24348ded3 100644 --- a/src/telnyx/types/ai/telephony_settings_param.py +++ b/src/telnyx/types/ai/telephony_settings_param.py @@ -113,6 +113,17 @@ class TelephonySettingsParam(TypedDict, total=False): the main tool array or on any workflow node — enforced at write time. """ + fallback_destination: str + """ + Destination number or SIP URI to transfer the caller to when the AI conversation + ends abnormally, for example because of an assistant-side error, so the caller + is not left in dead air. This only fires for abnormal ends: it does not fire + when the conversation ends on purpose (the caller hung up, the assistant + completed normally, the caller hung up after a relay handoff, or voicemail was + detected), and it does not fire when the assistant already transferred or + bridged the call. + """ + noise_suppression: Literal["krisp", "deepfilternet", "disabled"] """The noise suppression engine to use. diff --git a/src/telnyx/types/compute/__init__.py b/src/telnyx/types/compute/__init__.py new file mode 100644 index 000000000..f8c6e7d70 --- /dev/null +++ b/src/telnyx/types/compute/__init__.py @@ -0,0 +1,49 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import TYPE_CHECKING, Any + +from .func_retrieve_logs_params import FuncRetrieveLogsParams as FuncRetrieveLogsParams +from .func_retrieve_logs_response import FuncRetrieveLogsResponse as FuncRetrieveLogsResponse +from .func_retrieve_revisions_params import FuncRetrieveRevisionsParams as FuncRetrieveRevisionsParams +from .func_retrieve_metric_aggregates_params import ( + FuncRetrieveMetricAggregatesParams as FuncRetrieveMetricAggregatesParams, +) + +if TYPE_CHECKING: + from .logs_meta import LogsMeta as LogsMeta + from .func_retrieve_revisions_response import FuncRetrieveRevisionsResponse as FuncRetrieveRevisionsResponse + from .func_retrieve_ship_inspection_response import ( + FuncRetrieveShipInspectionResponse as FuncRetrieveShipInspectionResponse, + ) + from .functions_observability_pagination_meta import ( + FunctionsObservabilityPaginationMeta as FunctionsObservabilityPaginationMeta, + ) + from .func_retrieve_metric_aggregates_response import ( + FuncRetrieveMetricAggregatesResponse as FuncRetrieveMetricAggregatesResponse, + ) + + +def __getattr__(name: str) -> Any: + if name == "FunctionsObservabilityPaginationMeta": + from .functions_observability_pagination_meta import FunctionsObservabilityPaginationMeta + + return FunctionsObservabilityPaginationMeta + if name == "LogsMeta": + from .logs_meta import LogsMeta + + return LogsMeta + if name == "FuncRetrieveMetricAggregatesResponse": + from .func_retrieve_metric_aggregates_response import FuncRetrieveMetricAggregatesResponse + + return FuncRetrieveMetricAggregatesResponse + if name == "FuncRetrieveRevisionsResponse": + from .func_retrieve_revisions_response import FuncRetrieveRevisionsResponse + + return FuncRetrieveRevisionsResponse + if name == "FuncRetrieveShipInspectionResponse": + from .func_retrieve_ship_inspection_response import FuncRetrieveShipInspectionResponse + + return FuncRetrieveShipInspectionResponse + raise AttributeError(f"module {__name__!r} has no attribute {name!r}") diff --git a/src/telnyx/types/compute/func_retrieve_logs_params.py b/src/telnyx/types/compute/func_retrieve_logs_params.py new file mode 100644 index 000000000..9f6801f19 --- /dev/null +++ b/src/telnyx/types/compute/func_retrieve_logs_params.py @@ -0,0 +1,25 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Union +from datetime import datetime +from typing_extensions import Literal, Annotated, TypedDict + +from ..._utils import PropertyInfo + +__all__ = ["FuncRetrieveLogsParams"] + + +class FuncRetrieveLogsParams(TypedDict, total=False): + end_time: Annotated[Union[str, datetime], PropertyInfo(format="iso8601")] + """Return records at or before this RFC 3339 timestamp.""" + + limit: int + """Maximum records to return.""" + + start_time: Annotated[Union[str, datetime], PropertyInfo(format="iso8601")] + """Return records at or after this RFC 3339 timestamp.""" + + type: Literal["runtime", "invocations"] + """Log stream to return.""" diff --git a/src/telnyx/types/compute/func_retrieve_logs_response.py b/src/telnyx/types/compute/func_retrieve_logs_response.py new file mode 100644 index 000000000..8759be2c5 --- /dev/null +++ b/src/telnyx/types/compute/func_retrieve_logs_response.py @@ -0,0 +1,63 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import List, Union, Optional +from datetime import datetime +from typing_extensions import Literal, TypeAlias + +from ..._models import BaseModel +from .logs_meta import LogsMeta + +__all__ = [ + "FuncRetrieveLogsResponse", + "FuncRuntimeLogsResponse", + "FuncRuntimeLogsResponseData", + "FuncInvocationLogsResponse", + "FuncInvocationLogsResponseData", +] + + +class FuncRuntimeLogsResponseData(BaseModel): + level: Optional[str] = None + + message: Optional[str] = None + + record_type: Optional[Literal["compute_func_runtime_log"]] = None + + timestamp: Optional[datetime] = None + + +class FuncRuntimeLogsResponse(BaseModel): + data: Optional[List[FuncRuntimeLogsResponseData]] = None + + meta: Optional[LogsMeta] = None + + +class FuncInvocationLogsResponseData(BaseModel): + duration_ms: Optional[float] = None + + method: Optional[str] = None + + path: Optional[str] = None + + record_type: Optional[Literal["compute_func_invocation_log"]] = None + + region: Optional[str] = None + + request_size_bytes: Optional[int] = None + + response_size_bytes: Optional[int] = None + + status_code: Optional[int] = None + + timestamp: Optional[datetime] = None + + +class FuncInvocationLogsResponse(BaseModel): + data: Optional[List[FuncInvocationLogsResponseData]] = None + + meta: Optional[LogsMeta] = None + + +FuncRetrieveLogsResponse: TypeAlias = Union[FuncRuntimeLogsResponse, FuncInvocationLogsResponse] diff --git a/src/telnyx/types/compute/func_retrieve_metric_aggregates_params.py b/src/telnyx/types/compute/func_retrieve_metric_aggregates_params.py new file mode 100644 index 000000000..f26bac5f4 --- /dev/null +++ b/src/telnyx/types/compute/func_retrieve_metric_aggregates_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 import Union +from datetime import datetime +from typing_extensions import Required, Annotated, TypedDict + +from ..._utils import PropertyInfo + +__all__ = ["FuncRetrieveMetricAggregatesParams"] + + +class FuncRetrieveMetricAggregatesParams(TypedDict, total=False): + end_time: Required[Annotated[Union[str, datetime], PropertyInfo(format="iso8601")]] + """Exclusive window end, UTC ISO 8601 with milliseconds""" + + start_time: Required[Annotated[Union[str, datetime], PropertyInfo(format="iso8601")]] + """Inclusive window start, UTC ISO 8601 with milliseconds""" + + filter_edge_site: Annotated[str, PropertyInfo(alias="filter[edge_site]")] + """Edge site filter""" + + filter_namespace: Annotated[str, PropertyInfo(alias="filter[namespace]")] + """Kubernetes namespace filter""" + + page_number: Annotated[int, PropertyInfo(alias="page[number]")] + + page_size: Annotated[int, PropertyInfo(alias="page[size]")] diff --git a/src/telnyx/types/compute/func_retrieve_metric_aggregates_response.py b/src/telnyx/types/compute/func_retrieve_metric_aggregates_response.py new file mode 100644 index 000000000..d8f6578b5 --- /dev/null +++ b/src/telnyx/types/compute/func_retrieve_metric_aggregates_response.py @@ -0,0 +1,55 @@ +# 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 ..._models import BaseModel +from .functions_observability_pagination_meta import FunctionsObservabilityPaginationMeta + +__all__ = ["FuncRetrieveMetricAggregatesResponse", "Data"] + + +class Data(BaseModel): + cpu_used_cores_avg: Optional[float] = None + + cpu_used_cores_max: Optional[float] = None + + end_time: Optional[datetime] = None + + function_id: Optional[str] = None + + function_name: Optional[str] = None + + memory_used_bytes_avg: Optional[float] = None + + memory_used_bytes_max: Optional[float] = None + + product: Optional[str] = None + + record_type: Optional[str] = None + + request_client_error_rate: Optional[float] = None + + request_count: Optional[float] = None + + request_error_rate: Optional[float] = None + + request_latency_avg_ms: Optional[float] = None + + request_latency_p50_ms: Optional[float] = None + + request_latency_p95_ms: Optional[float] = None + + request_latency_p99_ms: Optional[float] = None + + request_success_rate: Optional[float] = None + + start_time: Optional[datetime] = None + + +class FuncRetrieveMetricAggregatesResponse(BaseModel): + data: Optional[List[Data]] = None + + meta: Optional[FunctionsObservabilityPaginationMeta] = None diff --git a/src/telnyx/types/compute/func_retrieve_revisions_params.py b/src/telnyx/types/compute/func_retrieve_revisions_params.py new file mode 100644 index 000000000..7414dd84f --- /dev/null +++ b/src/telnyx/types/compute/func_retrieve_revisions_params.py @@ -0,0 +1,15 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Annotated, TypedDict + +from ..._utils import PropertyInfo + +__all__ = ["FuncRetrieveRevisionsParams"] + + +class FuncRetrieveRevisionsParams(TypedDict, total=False): + page_number: Annotated[int, PropertyInfo(alias="page[number]")] + + page_size: Annotated[int, PropertyInfo(alias="page[size]")] diff --git a/src/telnyx/types/compute/func_retrieve_revisions_response.py b/src/telnyx/types/compute/func_retrieve_revisions_response.py new file mode 100644 index 000000000..27e37975f --- /dev/null +++ b/src/telnyx/types/compute/func_retrieve_revisions_response.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 List, Optional +from datetime import datetime + +from ..._models import BaseModel +from .functions_observability_pagination_meta import FunctionsObservabilityPaginationMeta + +__all__ = ["FuncRetrieveRevisionsResponse", "Data"] + + +class Data(BaseModel): + active: Optional[bool] = None + + build_ok_at: Optional[datetime] = None + + build_status: Optional[str] = None + + commit_sha: Optional[str] = None + + deploy_status: Optional[str] = None + + failure_reason: Optional[str] = None + + failure_stage: Optional[str] = None + + image: Optional[str] = None + + record_type: Optional[str] = None + + revision_id: Optional[str] = None + + shipped_at: Optional[datetime] = None + + shipped_by: Optional[str] = None + + +class FuncRetrieveRevisionsResponse(BaseModel): + data: Optional[List[Data]] = None + + meta: Optional[FunctionsObservabilityPaginationMeta] = None diff --git a/src/telnyx/types/compute/func_retrieve_ship_inspection_response.py b/src/telnyx/types/compute/func_retrieve_ship_inspection_response.py new file mode 100644 index 000000000..f464d8fc2 --- /dev/null +++ b/src/telnyx/types/compute/func_retrieve_ship_inspection_response.py @@ -0,0 +1,30 @@ +# 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__ = ["FuncRetrieveShipInspectionResponse", "Data"] + + +class Data(BaseModel): + created_at: Optional[datetime] = None + + reason: Optional[str] = None + + record_type: Optional[Literal["build_log_inspection"]] = None + """Stable record type retained by both inspection path aliases.""" + + runtime: Optional[str] = None + + snippet: Optional[str] = None + + stage: Optional[Literal["build", "platform", "pre_build", "deploy", "security_review", "none", "pending"]] = None + + +class FuncRetrieveShipInspectionResponse(BaseModel): + data: Optional[Data] = None diff --git a/src/telnyx/types/compute/functions_observability_pagination_meta.py b/src/telnyx/types/compute/functions_observability_pagination_meta.py new file mode 100644 index 000000000..6217d57ed --- /dev/null +++ b/src/telnyx/types/compute/functions_observability_pagination_meta.py @@ -0,0 +1,19 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Optional + +from ..._models import BaseModel + +__all__ = ["FunctionsObservabilityPaginationMeta"] + + +class FunctionsObservabilityPaginationMeta(BaseModel): + page_number: Optional[int] = None + + page_size: Optional[int] = None + + total_pages: Optional[int] = None + + total_results: Optional[int] = None diff --git a/src/telnyx/types/compute/logs_meta.py b/src/telnyx/types/compute/logs_meta.py new file mode 100644 index 000000000..db984ecb2 --- /dev/null +++ b/src/telnyx/types/compute/logs_meta.py @@ -0,0 +1,15 @@ +# 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__ = ["LogsMeta"] + + +class LogsMeta(BaseModel): + has_more: Optional[bool] = None + + partial: Optional[bool] = None diff --git a/src/telnyx/types/credential_connection.py b/src/telnyx/types/credential_connection.py index 71a65d68a..ea5953cb7 100644 --- a/src/telnyx/types/credential_connection.py +++ b/src/telnyx/types/credential_connection.py @@ -120,7 +120,10 @@ class CredentialConnection(BaseModel): password: Optional[str] = None """The password to be used as part of the credentials. - Must be 8 to 128 characters long. + Must be 8 to 128 characters long. For primary accounts created on or after + September 8, 2026, this password is returned as `********`. The password is + returned in full on create, and on update only when that update changed the + password. Accounts created before September 8, 2026 are unaffected. """ record_type: Optional[str] = None diff --git a/src/telnyx/types/email_inboxes/email_message.py b/src/telnyx/types/email_inboxes/email_message.py index 9b6361b2e..6dfe80ac1 100644 --- a/src/telnyx/types/email_inboxes/email_message.py +++ b/src/telnyx/types/email_inboxes/email_message.py @@ -11,6 +11,7 @@ from ..._models import BaseModel from .email_address import EmailAddress from ..message_event import MessageEvent +from ..suppressed_recipient import SuppressedRecipient __all__ = ["EmailMessage", "Attachment"] @@ -113,3 +114,12 @@ class EmailMessage(BaseModel): Persists even after the scheduled send has been processed or cancelled. """ + + suppressed: Optional[List[SuppressedRecipient]] = None + """Recipients excluded from delivery by suppression checks, with reasons. + + On batch items, present when that item had suppressed recipients; all other + recipients of the item still receive the message. For single sends this + information appears at the top level of the response instead (see + EmailMessageResponse.suppressed). + """ diff --git a/src/telnyx/types/email_message_batch_params.py b/src/telnyx/types/email_message_batch_params.py index 2aa883e22..b78cd9cae 100644 --- a/src/telnyx/types/email_message_batch_params.py +++ b/src/telnyx/types/email_message_batch_params.py @@ -17,6 +17,11 @@ class EmailMessageBatchParams(TypedDict, total=False): messages: Required[Iterable[Message]] + """Array of email messages to send. + + Up to 1,000 messages per batch request. Each message is validated and sent + independently; per-message failures do not affect other messages in the batch. + """ sandbox_mode: bool """Applies sandbox mode to all messages in the batch. diff --git a/src/telnyx/types/email_message_batch_response.py b/src/telnyx/types/email_message_batch_response.py index aa23e1e97..a4485ee04 100644 --- a/src/telnyx/types/email_message_batch_response.py +++ b/src/telnyx/types/email_message_batch_response.py @@ -17,6 +17,7 @@ class Error(BaseModel): "not_found", "forbidden", "service_unavailable", + "unprocessable_entity", "validation_error", "recipient_suppressed", "reputation_suspended", diff --git a/src/telnyx/types/fqdn_connection.py b/src/telnyx/types/fqdn_connection.py index 679bc8e05..874826a47 100644 --- a/src/telnyx/types/fqdn_connection.py +++ b/src/telnyx/types/fqdn_connection.py @@ -135,7 +135,13 @@ class FqdnConnection(BaseModel): outbound: Optional[OutboundFqdn] = None password: Optional[str] = None - """The password for the FQDN connection.""" + """The password for the FQDN connection. + + For primary accounts created on or after September 8, 2026, this password is + returned as `********`. The password is returned in full on create, and on + update only when that update changed the password. Accounts created before + September 8, 2026 are unaffected. + """ record_type: Optional[str] = None """Identifies the type of the resource.""" diff --git a/src/telnyx/types/fqdn_connections/fqdn_authentication.py b/src/telnyx/types/fqdn_connections/fqdn_authentication.py index f2755af55..9a7d529fa 100644 --- a/src/telnyx/types/fqdn_connections/fqdn_authentication.py +++ b/src/telnyx/types/fqdn_connections/fqdn_authentication.py @@ -30,7 +30,13 @@ class FqdnAuthentication(BaseModel): """Whether the connection is a Microsoft Teams SBC.""" password: Optional[str] = None - """The password for authentication.""" + """The password for authentication. + + For primary accounts created on or after September 8, 2026, this password is + returned as `********`. The password is returned in full on create, and on + update only when that update changed the password. Accounts created before + September 8, 2026 are unaffected. + """ record_type: Optional[str] = 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 c06dbe415..0cdf0c60e 100644 --- a/src/telnyx/types/messaging_inbound_message_payload.py +++ b/src/telnyx/types/messaging_inbound_message_payload.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import List, Optional +from typing import TYPE_CHECKING, Dict, List, Union, Optional from datetime import datetime from typing_extensions import Literal @@ -13,6 +13,9 @@ __all__ = [ "MessagingInboundMessagePayload", + "Body", + "BodyEdit", + "BodyRevoke", "Cc", "Cost", "CostBreakdown", @@ -20,10 +23,76 @@ "CostBreakdownRate", "From", "Media", - "To", + "ToUnionMember0", ] +class BodyEdit(BaseModel): + """Details for an edited WhatsApp message.""" + + message: Dict[str, object] + """Replacement WhatsApp message content. Its shape depends on the message type.""" + + original_message_id: str + """ + Telnyx message ID when a mapping exists, otherwise the original Meta WhatsApp + message ID. Treat this value as opaque. + """ + + +class BodyRevoke(BaseModel): + """Details for a revoked WhatsApp message.""" + + original_message_id: str + """ + Telnyx message ID when a mapping exists, otherwise the original Meta WhatsApp + message ID. Treat this value as opaque. + """ + + +class Body(BaseModel): + """WhatsApp message body. + + For message edits and revocations, inspect `type` and the corresponding `edit` or `revoke` object. + """ + + id: Optional[str] = None + """Telnyx identifier for this webhook message.""" + + edit: Optional[BodyEdit] = None + """Details for an edited WhatsApp message.""" + + foreign_id: Optional[str] = None + """Meta WhatsApp message identifier for this webhook event.""" + + from_: Optional[str] = FieldInfo(alias="from", default=None) + """WhatsApp sender in E.164 format.""" + + revoke: Optional[BodyRevoke] = None + """Details for a revoked WhatsApp message.""" + + timestamp: Optional[str] = None + """Unix timestamp supplied by Meta.""" + + type: Optional[str] = None + """WhatsApp message body type. + + Edit and revoke events use `edit` and `revoke`, respectively. + """ + + 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] + + class Cc(BaseModel): carrier: Optional[str] = None """The carrier of the receiver.""" @@ -101,7 +170,7 @@ class Media(BaseModel): """The url of the media requested to be sent.""" -class To(BaseModel): +class ToUnionMember0(BaseModel): carrier: Optional[str] = None """The carrier of the receiver.""" @@ -129,6 +198,13 @@ class MessagingInboundMessagePayload(BaseModel): id: Optional[str] = None """Identifies the type of resource.""" + body: Optional[Body] = None + """WhatsApp message body. + + For message edits and revocations, inspect `type` and the corresponding `edit` + or `revoke` object. + """ + cc: Optional[List[Cc]] = None completed_at: Optional[datetime] = None @@ -200,10 +276,15 @@ class MessagingInboundMessagePayload(BaseModel): **Required for SMS** """ - to: Optional[List[To]] = None + 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. + """ - type: Optional[Literal["SMS", "MMS"]] = None - """The type of message. This value can be either 'sms' or 'mms'.""" + type: Optional[Literal["SMS", "MMS", "WHATSAPP"]] = None + """The messaging channel used for the message.""" valid_until: Optional[datetime] = None """Not used for inbound messages.""" diff --git a/src/telnyx/types/messaging_messaging_profile.py b/src/telnyx/types/messaging_messaging_profile.py index c650f12fb..ff57665b6 100644 --- a/src/telnyx/types/messaging_messaging_profile.py +++ b/src/telnyx/types/messaging_messaging_profile.py @@ -9,6 +9,7 @@ from .._models import BaseModel from .number_pool_settings import NumberPoolSettings from .url_shortener_settings import URLShortenerSettings +from .messaging_profile_features import MessagingProfileFeatures __all__ = ["MessagingMessagingProfile"] @@ -41,6 +42,13 @@ class MessagingMessagingProfile(BaseModel): enabled: Optional[bool] = None """Specifies whether the messaging profile is enabled or not.""" + features: Optional[MessagingProfileFeatures] = None + """ + Telnyx product features the messaging customer can enable on the messaging + profile. Keys map to individual feature flags; unknown keys are accepted and + preserved for forward compatibility with rolling deployments. + """ + health_webhook_url: Optional[str] = None """DEPRECATED: health check url service checking""" diff --git a/src/telnyx/types/messaging_profile_create_params.py b/src/telnyx/types/messaging_profile_create_params.py index 12b2c6ef5..badd3edc5 100644 --- a/src/telnyx/types/messaging_profile_create_params.py +++ b/src/telnyx/types/messaging_profile_create_params.py @@ -8,6 +8,7 @@ from .._types import SequenceNotStr from .number_pool_settings_param import NumberPoolSettingsParam from .url_shortener_settings_param import URLShortenerSettingsParam +from .messaging_profile_features_param import MessagingProfileFeaturesParam __all__ = ["MessagingProfileCreateParams"] @@ -44,6 +45,13 @@ class MessagingProfileCreateParams(TypedDict, total=False): enabled: bool """Specifies whether the messaging profile is enabled or not.""" + features: Optional[MessagingProfileFeaturesParam] + """ + Telnyx product features the messaging customer can enable on the messaging + profile. Keys map to individual feature flags; unknown keys are accepted and + preserved for forward compatibility with rolling deployments. + """ + health_webhook_url: Optional[str] """A URL to receive health check webhooks for numbers in this profile.""" diff --git a/src/telnyx/types/messaging_profile_features.py b/src/telnyx/types/messaging_profile_features.py new file mode 100644 index 000000000..2e27c79da --- /dev/null +++ b/src/telnyx/types/messaging_profile_features.py @@ -0,0 +1,37 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import TYPE_CHECKING, Dict, Optional + +from pydantic import Field as FieldInfo + +from .._models import BaseModel + +__all__ = ["MessagingProfileFeatures"] + + +class MessagingProfileFeatures(BaseModel): + """ + Telnyx product features the messaging customer can enable on the messaging profile. Keys map to individual feature flags; unknown keys are accepted and preserved for forward compatibility with rolling deployments. + """ + + ai_opt_out_detection_enabled: Optional[bool] = None + """ + Enables AI detection of inbound opt-out messages that do not follow the standard + STOP/UNSTOP/HELP opt-out keyword pattern. When enabled, the messaging platform + applies an AI model to identify non-standard opt-out requests (e.g. + natural-language phrases) and treats them as opt-outs. + """ + + 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] diff --git a/src/telnyx/types/messaging_profile_features_param.py b/src/telnyx/types/messaging_profile_features_param.py new file mode 100644 index 000000000..39cd7c236 --- /dev/null +++ b/src/telnyx/types/messaging_profile_features_param.py @@ -0,0 +1,21 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import TypedDict + +__all__ = ["MessagingProfileFeaturesParam"] + + +class MessagingProfileFeaturesParam(TypedDict, total=False, extra_items=object): # type: ignore[call-arg] + """ + Telnyx product features the messaging customer can enable on the messaging profile. Keys map to individual feature flags; unknown keys are accepted and preserved for forward compatibility with rolling deployments. + """ + + ai_opt_out_detection_enabled: bool + """ + Enables AI detection of inbound opt-out messages that do not follow the standard + STOP/UNSTOP/HELP opt-out keyword pattern. When enabled, the messaging platform + applies an AI model to identify non-standard opt-out requests (e.g. + natural-language phrases) and treats them as opt-outs. + """ diff --git a/src/telnyx/types/messaging_profile_update_params.py b/src/telnyx/types/messaging_profile_update_params.py index fa101a778..dcfdbb2e4 100644 --- a/src/telnyx/types/messaging_profile_update_params.py +++ b/src/telnyx/types/messaging_profile_update_params.py @@ -8,6 +8,7 @@ from .._types import SequenceNotStr from .number_pool_settings_param import NumberPoolSettingsParam from .url_shortener_settings_param import URLShortenerSettingsParam +from .messaging_profile_features_param import MessagingProfileFeaturesParam __all__ = ["MessagingProfileUpdateParams"] @@ -34,6 +35,13 @@ class MessagingProfileUpdateParams(TypedDict, total=False): enabled: bool """Specifies whether the messaging profile is enabled or not.""" + features: Optional[MessagingProfileFeaturesParam] + """ + Telnyx product features the messaging customer can enable on the messaging + profile. Keys map to individual feature flags; unknown keys are accepted and + preserved for forward compatibility with rolling deployments. + """ + mms_fall_back_to_sms: bool """enables SMS fallback for MMS messages.""" diff --git a/src/telnyx/types/uac_connection.py b/src/telnyx/types/uac_connection.py index 24a336e9d..c8aa17df5 100644 --- a/src/telnyx/types/uac_connection.py +++ b/src/telnyx/types/uac_connection.py @@ -141,7 +141,10 @@ class UacConnection(BaseModel): password: Optional[str] = None """The password to be used as part of the credentials. - Must be 8 to 128 characters long. + Must be 8 to 128 characters long. For primary accounts created on or after + September 8, 2026, this password is returned as `********`. The password is + returned in full on create, and on update only when that update changed the + password. Accounts created before September 8, 2026 are unaffected. """ record_type: Optional[str] = None diff --git a/src/telnyx/types/uac_external_settings.py b/src/telnyx/types/uac_external_settings.py index 765d8e4b2..ad1cc60a2 100644 --- a/src/telnyx/types/uac_external_settings.py +++ b/src/telnyx/types/uac_external_settings.py @@ -40,7 +40,13 @@ class UacExternalSettings(BaseModel): """ password: Optional[str] = None - """The SIP password used for digest authentication with the external SIP peer.""" + """The SIP password used for digest authentication with the external SIP peer. + + For primary accounts created on or after September 8, 2026, this password is + returned as `********`. The password is returned in full on create, and on + update only when that update changed the password. Accounts created before + September 8, 2026 are unaffected. + """ proxy: Optional[str] = None """ diff --git a/src/telnyx/types/uac_external_settings_param.py b/src/telnyx/types/uac_external_settings_param.py index 7e7c83d51..4a9e99064 100644 --- a/src/telnyx/types/uac_external_settings_param.py +++ b/src/telnyx/types/uac_external_settings_param.py @@ -38,7 +38,13 @@ class UacExternalSettingsParam(TypedDict, total=False): """ password: str - """The SIP password used for digest authentication with the external SIP peer.""" + """The SIP password used for digest authentication with the external SIP peer. + + For primary accounts created on or after September 8, 2026, this password is + returned as `********`. The password is returned in full on create, and on + update only when that update changed the password. Accounts created before + September 8, 2026 are unaffected. + """ proxy: str """ diff --git a/src/telnyx/types/unsafe_unwrap_webhook_event.py b/src/telnyx/types/unsafe_unwrap_webhook_event.py index 858d8f248..6ff39948c 100644 --- a/src/telnyx/types/unsafe_unwrap_webhook_event.py +++ b/src/telnyx/types/unsafe_unwrap_webhook_event.py @@ -10,9 +10,11 @@ from .fax_delivered import FaxDelivered from .fax_media_processed import FaxMediaProcessed from .fax_sending_started import FaxSendingStarted +from .whatsapp_message_echo import WhatsappMessageEcho from .campaign_status_update import CampaignStatusUpdate from .call_cost_webhook_event import CallCostWebhookEvent from .call_hold_webhook_event import CallHoldWebhookEvent +from .whatsapp_account_update import WhatsappAccountUpdate from .conference_floor_changed import ConferenceFloorChanged from .call_hangup_webhook_event import CallHangupWebhookEvent from .call_unhold_webhook_event import CallUnholdWebhookEvent @@ -155,4 +157,6 @@ SessionStatusChangedWebhookEvent, TranscriptCompletedWebhookEvent, TranscriptionWebhookEvent, + WhatsappAccountUpdate, + WhatsappMessageEcho, ] diff --git a/src/telnyx/types/unwrap_webhook_event.py b/src/telnyx/types/unwrap_webhook_event.py index 1747cbc40..d3faec93e 100644 --- a/src/telnyx/types/unwrap_webhook_event.py +++ b/src/telnyx/types/unwrap_webhook_event.py @@ -10,9 +10,11 @@ from .fax_delivered import FaxDelivered from .fax_media_processed import FaxMediaProcessed from .fax_sending_started import FaxSendingStarted +from .whatsapp_message_echo import WhatsappMessageEcho from .campaign_status_update import CampaignStatusUpdate from .call_cost_webhook_event import CallCostWebhookEvent from .call_hold_webhook_event import CallHoldWebhookEvent +from .whatsapp_account_update import WhatsappAccountUpdate from .conference_floor_changed import ConferenceFloorChanged from .call_hangup_webhook_event import CallHangupWebhookEvent from .call_unhold_webhook_event import CallUnholdWebhookEvent @@ -155,4 +157,6 @@ SessionStatusChangedWebhookEvent, TranscriptCompletedWebhookEvent, TranscriptionWebhookEvent, + WhatsappAccountUpdate, + WhatsappMessageEcho, ] diff --git a/src/telnyx/types/whatsapp/__init__.py b/src/telnyx/types/whatsapp/__init__.py index a9f8b7965..8756522d5 100644 --- a/src/telnyx/types/whatsapp/__init__.py +++ b/src/telnyx/types/whatsapp/__init__.py @@ -42,6 +42,9 @@ from .user_data_retrieve_response import UserDataRetrieveResponse as UserDataRetrieveResponse from .business_account_list_response import BusinessAccountListResponse as BusinessAccountListResponse from .business_account_retrieve_response import BusinessAccountRetrieveResponse as BusinessAccountRetrieveResponse + from .phone_number_retrieve_phone_number_response import ( + PhoneNumberRetrievePhoneNumberResponse as PhoneNumberRetrievePhoneNumberResponse, + ) from .phone_number_retrieve_conversation_window_response import ( PhoneNumberRetrieveConversationWindowResponse as PhoneNumberRetrieveConversationWindowResponse, ) @@ -72,6 +75,10 @@ def __getattr__(name: str) -> Any: from .phone_number_retrieve_conversation_window_response import PhoneNumberRetrieveConversationWindowResponse return PhoneNumberRetrieveConversationWindowResponse + if name == "PhoneNumberRetrievePhoneNumberResponse": + from .phone_number_retrieve_phone_number_response import PhoneNumberRetrievePhoneNumberResponse + + return PhoneNumberRetrievePhoneNumberResponse if name == "WhatsappUserData": from .whatsapp_user_data import WhatsappUserData diff --git a/src/telnyx/types/whatsapp/business_accounts/phone_number_list_response.py b/src/telnyx/types/whatsapp/business_accounts/phone_number_list_response.py index 2696da1af..50b736454 100644 --- a/src/telnyx/types/whatsapp/business_accounts/phone_number_list_response.py +++ b/src/telnyx/types/whatsapp/business_accounts/phone_number_list_response.py @@ -4,21 +4,63 @@ from typing import Optional from datetime import datetime +from typing_extensions import Literal from ...._models import BaseModel -__all__ = ["PhoneNumberListResponse"] +__all__ = ["PhoneNumberListResponse", "SyncProgress"] + + +class SyncProgress(BaseModel): + """Synchronization progress. + + This object is returned only while a coexistence number is synchronizing. + """ + + contacts_status: Optional[str] = None + + history_chunk_order: Optional[int] = None + + history_phase: Optional[int] = None + + history_progress: Optional[int] = None + + history_status: Optional[str] = None class PhoneNumberListResponse(BaseModel): calling_enabled: Optional[bool] = None + coexistence_state: Optional[ + Literal[ + "pending_onboarding", + "sync_pending", + "syncing", + "sync_complete", + "active", + "history_declined", + "sync_deadline_expired", + "offboarded", + "disconnected", + ] + ] = None + """Current lifecycle state for a coexistence number. + + This is null for a standard Cloud API number. + """ + created_at: Optional[datetime] = None display_name: Optional[str] = None enabled: Optional[bool] = None + is_on_biz_app: Optional[bool] = None + """ + Indicates whether the number is connected to both the WhatsApp Business app and + Cloud API through WhatsApp Coexistence. + """ + phone_number: Optional[str] = None """Phone number in E164 format""" @@ -32,6 +74,18 @@ class PhoneNumberListResponse(BaseModel): status: Optional[str] = None + sync_deadline: Optional[datetime] = None + """Deadline for initiating the current coexistence synchronization cycle. + + This is null when no deadline applies. + """ + + sync_progress: Optional[SyncProgress] = None + """Synchronization progress. + + This object is returned only while a coexistence number is synchronizing. + """ + user_id: Optional[str] = None """User ID""" diff --git a/src/telnyx/types/whatsapp/phone_number_get_response.py b/src/telnyx/types/whatsapp/phone_number_get_response.py index 7123ef8dc..e1caf5441 100644 --- a/src/telnyx/types/whatsapp/phone_number_get_response.py +++ b/src/telnyx/types/whatsapp/phone_number_get_response.py @@ -4,22 +4,64 @@ from typing import List, Optional from datetime import datetime +from typing_extensions import Literal from ..._models import BaseModel from ..shared.messaging_pagination_meta import MessagingPaginationMeta -__all__ = ["PhoneNumberGetResponse", "Data"] +__all__ = ["PhoneNumberGetResponse", "Data", "DataSyncProgress"] + + +class DataSyncProgress(BaseModel): + """Synchronization progress. + + This object is returned only while a coexistence number is synchronizing. + """ + + contacts_status: Optional[str] = None + + history_chunk_order: Optional[int] = None + + history_phase: Optional[int] = None + + history_progress: Optional[int] = None + + history_status: Optional[str] = None class Data(BaseModel): calling_enabled: Optional[bool] = None + coexistence_state: Optional[ + Literal[ + "pending_onboarding", + "sync_pending", + "syncing", + "sync_complete", + "active", + "history_declined", + "sync_deadline_expired", + "offboarded", + "disconnected", + ] + ] = None + """Current lifecycle state for a coexistence number. + + This is null for a standard Cloud API number. + """ + created_at: Optional[datetime] = None display_name: Optional[str] = None enabled: Optional[bool] = None + is_on_biz_app: Optional[bool] = None + """ + Indicates whether the number is connected to both the WhatsApp Business app and + Cloud API through WhatsApp Coexistence. + """ + phone_number: Optional[str] = None """Phone number in E164 format""" @@ -33,6 +75,18 @@ class Data(BaseModel): status: Optional[str] = None + sync_deadline: Optional[datetime] = None + """Deadline for initiating the current coexistence synchronization cycle. + + This is null when no deadline applies. + """ + + sync_progress: Optional[DataSyncProgress] = None + """Synchronization progress. + + This object is returned only while a coexistence number is synchronizing. + """ + user_id: Optional[str] = None """User ID""" diff --git a/src/telnyx/types/whatsapp/phone_number_list_response.py b/src/telnyx/types/whatsapp/phone_number_list_response.py index 6aefd3146..0d8e59fcf 100644 --- a/src/telnyx/types/whatsapp/phone_number_list_response.py +++ b/src/telnyx/types/whatsapp/phone_number_list_response.py @@ -4,21 +4,63 @@ from typing import Optional from datetime import datetime +from typing_extensions import Literal from ..._models import BaseModel -__all__ = ["PhoneNumberListResponse"] +__all__ = ["PhoneNumberListResponse", "SyncProgress"] + + +class SyncProgress(BaseModel): + """Synchronization progress. + + This object is returned only while a coexistence number is synchronizing. + """ + + contacts_status: Optional[str] = None + + history_chunk_order: Optional[int] = None + + history_phase: Optional[int] = None + + history_progress: Optional[int] = None + + history_status: Optional[str] = None class PhoneNumberListResponse(BaseModel): calling_enabled: Optional[bool] = None + coexistence_state: Optional[ + Literal[ + "pending_onboarding", + "sync_pending", + "syncing", + "sync_complete", + "active", + "history_declined", + "sync_deadline_expired", + "offboarded", + "disconnected", + ] + ] = None + """Current lifecycle state for a coexistence number. + + This is null for a standard Cloud API number. + """ + created_at: Optional[datetime] = None display_name: Optional[str] = None enabled: Optional[bool] = None + is_on_biz_app: Optional[bool] = None + """ + Indicates whether the number is connected to both the WhatsApp Business app and + Cloud API through WhatsApp Coexistence. + """ + phone_number: Optional[str] = None """Phone number in E164 format""" @@ -32,6 +74,18 @@ class PhoneNumberListResponse(BaseModel): status: Optional[str] = None + sync_deadline: Optional[datetime] = None + """Deadline for initiating the current coexistence synchronization cycle. + + This is null when no deadline applies. + """ + + sync_progress: Optional[SyncProgress] = None + """Synchronization progress. + + This object is returned only while a coexistence number is synchronizing. + """ + user_id: Optional[str] = None """User ID""" diff --git a/src/telnyx/types/whatsapp/phone_number_retrieve_phone_number_response.py b/src/telnyx/types/whatsapp/phone_number_retrieve_phone_number_response.py new file mode 100644 index 000000000..1bc577231 --- /dev/null +++ b/src/telnyx/types/whatsapp/phone_number_retrieve_phone_number_response.py @@ -0,0 +1,97 @@ +# 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__ = ["PhoneNumberRetrievePhoneNumberResponse", "Data", "DataSyncProgress"] + + +class DataSyncProgress(BaseModel): + """Synchronization progress. + + This object is returned only while a coexistence number is synchronizing. + """ + + contacts_status: Optional[str] = None + + history_chunk_order: Optional[int] = None + + history_phase: Optional[int] = None + + history_progress: Optional[int] = None + + history_status: Optional[str] = None + + +class Data(BaseModel): + calling_enabled: Optional[bool] = None + + coexistence_state: Optional[ + Literal[ + "pending_onboarding", + "sync_pending", + "syncing", + "sync_complete", + "active", + "history_declined", + "sync_deadline_expired", + "offboarded", + "disconnected", + ] + ] = None + """Current lifecycle state for a coexistence number. + + This is null for a standard Cloud API number. + """ + + created_at: Optional[datetime] = None + + display_name: Optional[str] = None + + enabled: Optional[bool] = None + + is_on_biz_app: Optional[bool] = None + """ + Indicates whether the number is connected to both the WhatsApp Business app and + Cloud API through WhatsApp Coexistence. + """ + + phone_number: Optional[str] = None + """Phone number in E164 format""" + + phone_number_id: Optional[str] = None + """Whatsapp phone number ID""" + + quality_rating: Optional[str] = None + """Whatsapp quality rating""" + + record_type: Optional[str] = None + + status: Optional[str] = None + + sync_deadline: Optional[datetime] = None + """Deadline for initiating the current coexistence synchronization cycle. + + This is null when no deadline applies. + """ + + sync_progress: Optional[DataSyncProgress] = None + """Synchronization progress. + + This object is returned only while a coexistence number is synchronizing. + """ + + user_id: Optional[str] = None + """User ID""" + + waba_id: Optional[str] = None + """WABA ID of Whatsapp business account""" + + +class PhoneNumberRetrievePhoneNumberResponse(BaseModel): + data: Data diff --git a/src/telnyx/types/whatsapp_account_update.py b/src/telnyx/types/whatsapp_account_update.py new file mode 100644 index 000000000..9ef28e4f6 --- /dev/null +++ b/src/telnyx/types/whatsapp_account_update.py @@ -0,0 +1,41 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from datetime import datetime +from typing_extensions import Literal + +from .._models import BaseModel + +__all__ = ["WhatsappAccountUpdate", "Data", "DataPayload"] + + +class DataPayload(BaseModel): + event: str + """Account event reported by Meta. + + Coexistence lifecycle values include `ACCOUNT_OFFBOARDED`, + `ACCOUNT_RECONNECTED`, and `PARTNER_REMOVED`. Preserve unknown values for + forward compatibility. + """ + + record_type: Literal["whatsapp_account"] + + waba_id: str + """Meta WhatsApp Business Account identifier.""" + + +class Data(BaseModel): + id: str + + event_type: Literal["whatsapp.account.update"] + + occurred_at: datetime + + payload: DataPayload + + record_type: Literal["event"] + + +class WhatsappAccountUpdate(BaseModel): + data: Data diff --git a/src/telnyx/types/whatsapp_message_echo.py b/src/telnyx/types/whatsapp_message_echo.py new file mode 100644 index 000000000..d0dc010bb --- /dev/null +++ b/src/telnyx/types/whatsapp_message_echo.py @@ -0,0 +1,127 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import TYPE_CHECKING, Dict, 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__ = ["WhatsappMessageEcho", "Data", "DataPayload", "DataPayloadBody", "DataPayloadCost", "DataPayloadFrom"] + + +class DataPayloadBody(BaseModel): + """Mirrored WhatsApp message content. + + The content property matches the value of `type`. + """ + + id: str + """Telnyx identifier for the mirrored message.""" + + foreign_id: str + """Meta WhatsApp message identifier, also known as a wamid.""" + + timestamp: str + """Unix timestamp supplied by Meta.""" + + type: str + """WhatsApp message content type.""" + + from_: Optional[str] = FieldInfo(alias="from", default=None) + """WhatsApp user who received the message.""" + + from_user_id: Optional[str] = None + """Opaque recipient identifier when Meta does not supply a phone number.""" + + 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] + + +class DataPayloadCost(BaseModel): + """No charge is created for a Business app message echo.""" + + amount: Optional[str] = None + + currency: Optional[str] = None + + +class DataPayloadFrom(BaseModel): + phone_number: str + """Coexistence-enabled business phone number in E.164 format.""" + + carrier: Optional[str] = None + + line_type: Optional[str] = None + + +class DataPayload(BaseModel): + id: str + """Telnyx identifier for the mirrored message.""" + + body: DataPayloadBody + """Mirrored WhatsApp message content. + + The content property matches the value of `type`. + """ + + cost: DataPayloadCost + """No charge is created for a Business app message echo.""" + + direction: Literal["outbound"] + """Indicates that the business sent the message to the WhatsApp user.""" + + errors: List[MessagingError0b38e7044b] + + from_: DataPayloadFrom = FieldInfo(alias="from") + + messaging_profile_id: str + + organization_id: str + + origin: Literal["whatsapp_business_app"] + """Identifies the WhatsApp Business app as the source of the message.""" + + record_type: Literal["message"] + + to: str + """WhatsApp user who received the Business app message.""" + + type: Literal["WHATSAPP"] + + received_at: Optional[datetime] = None + + tags: Optional[List[str]] = None + + webhook_failover_url: Optional[str] = None + + webhook_url: Optional[str] = None + + +class Data(BaseModel): + id: str + + event_type: Literal["message.echo"] + + occurred_at: datetime + + payload: DataPayload + + record_type: Literal["event"] + + +class WhatsappMessageEcho(BaseModel): + data: Data diff --git a/src/telnyx/types/x402/credit_account/__init__.py b/src/telnyx/types/x402/credit_account/__init__.py new file mode 100644 index 000000000..aaf3d85aa --- /dev/null +++ b/src/telnyx/types/x402/credit_account/__init__.py @@ -0,0 +1,23 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import TYPE_CHECKING, Any + +from .payment_list_params import PaymentListParams as PaymentListParams + +if TYPE_CHECKING: + from .x402_transaction_record import X402TransactionRecord as X402TransactionRecord + from .payment_retrieve_response import PaymentRetrieveResponse as PaymentRetrieveResponse + + +def __getattr__(name: str) -> Any: + if name == "X402TransactionRecord": + from .x402_transaction_record import X402TransactionRecord + + return X402TransactionRecord + if name == "PaymentRetrieveResponse": + from .payment_retrieve_response import PaymentRetrieveResponse + + return PaymentRetrieveResponse + raise AttributeError(f"module {__name__!r} has no attribute {name!r}") diff --git a/src/telnyx/types/x402/credit_account/payment_list_params.py b/src/telnyx/types/x402/credit_account/payment_list_params.py new file mode 100644 index 000000000..f697acd85 --- /dev/null +++ b/src/telnyx/types/x402/credit_account/payment_list_params.py @@ -0,0 +1,17 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Annotated, TypedDict + +from ...._utils import PropertyInfo + +__all__ = ["PaymentListParams"] + + +class PaymentListParams(TypedDict, total=False): + page_number: Annotated[int, PropertyInfo(alias="page[number]")] + """The page number to load.""" + + page_size: Annotated[int, PropertyInfo(alias="page[size]")] + """The size of the page.""" diff --git a/src/telnyx/types/x402/credit_account/payment_retrieve_response.py b/src/telnyx/types/x402/credit_account/payment_retrieve_response.py new file mode 100644 index 000000000..07fd68868 --- /dev/null +++ b/src/telnyx/types/x402/credit_account/payment_retrieve_response.py @@ -0,0 +1,15 @@ +# 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 +from .x402_transaction_record import X402TransactionRecord + +__all__ = ["PaymentRetrieveResponse"] + + +class PaymentRetrieveResponse(BaseModel): + data: Optional[X402TransactionRecord] = None + """An x402 payment transaction.""" diff --git a/src/telnyx/types/x402/credit_account/x402_transaction_record.py b/src/telnyx/types/x402/credit_account/x402_transaction_record.py new file mode 100644 index 000000000..bf5fa80b7 --- /dev/null +++ b/src/telnyx/types/x402/credit_account/x402_transaction_record.py @@ -0,0 +1,45 @@ +# 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__ = ["X402TransactionRecord"] + + +class X402TransactionRecord(BaseModel): + """An x402 payment transaction.""" + + id: Optional[str] = None + """Unique transaction identifier.""" + + amount: Optional[str] = None + """The transaction amount in the specified currency.""" + + created_at: Optional[datetime] = None + """ISO 8601 timestamp when the transaction was created.""" + + currency: Optional[str] = None + """The currency of the transaction amount (e.g. USD).""" + + quote_id: Optional[str] = None + """The original quote ID associated with this transaction.""" + + record_type: Optional[Literal["x402_transaction"]] = None + + status: Optional[Literal["settled"]] = None + """The settlement status of the transaction. + + x402 transactions are created after successful on-chain settlement, so the + status is `settled`. + """ + + tx_hash: Optional[str] = None + """The on-chain transaction hash, if available.""" + + updated_at: Optional[datetime] = None + """ISO 8601 timestamp when the transaction was last updated.""" diff --git a/tests/api_resources/ai/assistants/test_versions.py b/tests/api_resources/ai/assistants/test_versions.py index dca4e6a1c..76f1f978b 100644 --- a/tests/api_resources/ai/assistants/test_versions.py +++ b/tests/api_resources/ai/assistants/test_versions.py @@ -97,6 +97,28 @@ def test_method_update_with_all_params(self, client: Telnyx) -> None: version = client.ai.assistants.versions.update( version_id="version_id", assistant_id="assistant_id", + a2a_agents=[ + { + "name": "billing_agent", + "url": "https://agents.example.com", + "async": True, + "headers": [ + { + "name": "X-Api-Key", + "value": "{{#integration_secret}}my_agent_api_key{{/integration_secret}}", + } + ], + "messages": [ + { + "content": "x", + "type": "request_start", + "timing_ms": 100, + } + ], + "poll_interval_ms": 500, + "timeout_ms": 30000, + } + ], conversation_flow={ "nodes": [ { @@ -337,6 +359,7 @@ def test_method_update_with_all_params(self, client: Telnyx) -> None: telephony_settings={ "default_texml_app_id": "default_texml_app_id", "disable_dtmf": True, + "fallback_destination": "fallback_destination", "noise_suppression": "krisp", "noise_suppression_config": { "attenuation_limit": 0, @@ -760,6 +783,28 @@ async def test_method_update_with_all_params(self, async_client: AsyncTelnyx) -> version = await async_client.ai.assistants.versions.update( version_id="version_id", assistant_id="assistant_id", + a2a_agents=[ + { + "name": "billing_agent", + "url": "https://agents.example.com", + "async": True, + "headers": [ + { + "name": "X-Api-Key", + "value": "{{#integration_secret}}my_agent_api_key{{/integration_secret}}", + } + ], + "messages": [ + { + "content": "x", + "type": "request_start", + "timing_ms": 100, + } + ], + "poll_interval_ms": 500, + "timeout_ms": 30000, + } + ], conversation_flow={ "nodes": [ { @@ -1000,6 +1045,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncTelnyx) -> telephony_settings={ "default_texml_app_id": "default_texml_app_id", "disable_dtmf": True, + "fallback_destination": "fallback_destination", "noise_suppression": "krisp", "noise_suppression_config": { "attenuation_limit": 0, diff --git a/tests/api_resources/ai/openai/test_chat.py b/tests/api_resources/ai/openai/test_chat.py index fb94da2bb..bde11e416 100644 --- a/tests/api_resources/ai/openai/test_chat.py +++ b/tests/api_resources/ai/openai/test_chat.py @@ -53,9 +53,6 @@ def test_method_create_completion_with_all_params(self, client: Telnyx) -> None: early_stopping=True, enable_thinking=True, frequency_penalty=0, - guided_choice=["string"], - guided_json={"foo": "bar"}, - guided_regex="guided_regex", length_penalty=0, logprobs=True, max_tokens=0, @@ -175,9 +172,6 @@ async def test_method_create_completion_with_all_params(self, async_client: Asyn early_stopping=True, enable_thinking=True, frequency_penalty=0, - guided_choice=["string"], - guided_json={"foo": "bar"}, - guided_regex="guided_regex", length_penalty=0, logprobs=True, max_tokens=0, diff --git a/tests/api_resources/ai/test_assistants.py b/tests/api_resources/ai/test_assistants.py index 7b2e66ed1..4a7420ec0 100644 --- a/tests/api_resources/ai/test_assistants.py +++ b/tests/api_resources/ai/test_assistants.py @@ -38,6 +38,28 @@ def test_method_create_with_all_params(self, client: Telnyx) -> None: assistant = client.ai.assistants.create( instructions="instructions", name="name", + a2a_agents=[ + { + "name": "billing_agent", + "url": "https://agents.example.com", + "async": True, + "headers": [ + { + "name": "X-Api-Key", + "value": "{{#integration_secret}}my_agent_api_key{{/integration_secret}}", + } + ], + "messages": [ + { + "content": "x", + "type": "request_start", + "timing_ms": 100, + } + ], + "poll_interval_ms": 500, + "timeout_ms": 30000, + } + ], conversation_flow={ "nodes": [ { @@ -276,6 +298,7 @@ def test_method_create_with_all_params(self, client: Telnyx) -> None: telephony_settings={ "default_texml_app_id": "default_texml_app_id", "disable_dtmf": True, + "fallback_destination": "fallback_destination", "noise_suppression": "krisp", "noise_suppression_config": { "attenuation_limit": 0, @@ -522,6 +545,28 @@ def test_method_update(self, client: Telnyx) -> None: def test_method_update_with_all_params(self, client: Telnyx) -> None: assistant = client.ai.assistants.update( assistant_id="assistant_id", + a2a_agents=[ + { + "name": "billing_agent", + "url": "https://agents.example.com", + "async": True, + "headers": [ + { + "name": "X-Api-Key", + "value": "{{#integration_secret}}my_agent_api_key{{/integration_secret}}", + } + ], + "messages": [ + { + "content": "x", + "type": "request_start", + "timing_ms": 100, + } + ], + "poll_interval_ms": 500, + "timeout_ms": 30000, + } + ], conversation_flow={ "nodes": [ { @@ -763,6 +808,7 @@ def test_method_update_with_all_params(self, client: Telnyx) -> None: telephony_settings={ "default_texml_app_id": "default_texml_app_id", "disable_dtmf": True, + "fallback_destination": "fallback_destination", "noise_suppression": "krisp", "noise_suppression_config": { "attenuation_limit": 0, @@ -1306,6 +1352,28 @@ async def test_method_create_with_all_params(self, async_client: AsyncTelnyx) -> assistant = await async_client.ai.assistants.create( instructions="instructions", name="name", + a2a_agents=[ + { + "name": "billing_agent", + "url": "https://agents.example.com", + "async": True, + "headers": [ + { + "name": "X-Api-Key", + "value": "{{#integration_secret}}my_agent_api_key{{/integration_secret}}", + } + ], + "messages": [ + { + "content": "x", + "type": "request_start", + "timing_ms": 100, + } + ], + "poll_interval_ms": 500, + "timeout_ms": 30000, + } + ], conversation_flow={ "nodes": [ { @@ -1544,6 +1612,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncTelnyx) -> telephony_settings={ "default_texml_app_id": "default_texml_app_id", "disable_dtmf": True, + "fallback_destination": "fallback_destination", "noise_suppression": "krisp", "noise_suppression_config": { "attenuation_limit": 0, @@ -1790,6 +1859,28 @@ async def test_method_update(self, async_client: AsyncTelnyx) -> None: async def test_method_update_with_all_params(self, async_client: AsyncTelnyx) -> None: assistant = await async_client.ai.assistants.update( assistant_id="assistant_id", + a2a_agents=[ + { + "name": "billing_agent", + "url": "https://agents.example.com", + "async": True, + "headers": [ + { + "name": "X-Api-Key", + "value": "{{#integration_secret}}my_agent_api_key{{/integration_secret}}", + } + ], + "messages": [ + { + "content": "x", + "type": "request_start", + "timing_ms": 100, + } + ], + "poll_interval_ms": 500, + "timeout_ms": 30000, + } + ], conversation_flow={ "nodes": [ { @@ -2031,6 +2122,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncTelnyx) -> telephony_settings={ "default_texml_app_id": "default_texml_app_id", "disable_dtmf": True, + "fallback_destination": "fallback_destination", "noise_suppression": "krisp", "noise_suppression_config": { "attenuation_limit": 0, diff --git a/tests/api_resources/compute/__init__.py b/tests/api_resources/compute/__init__.py new file mode 100644 index 000000000..fd8019a9a --- /dev/null +++ b/tests/api_resources/compute/__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/test_funcs.py b/tests/api_resources/compute/test_funcs.py new file mode 100644 index 000000000..286d348ce --- /dev/null +++ b/tests/api_resources/compute/test_funcs.py @@ -0,0 +1,454 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from telnyx import Telnyx, AsyncTelnyx +from tests.utils import assert_matches_type +from telnyx._utils import parse_datetime +from telnyx.types.compute import ( + FuncRetrieveLogsResponse, + FuncRetrieveRevisionsResponse, + FuncRetrieveShipInspectionResponse, + FuncRetrieveMetricAggregatesResponse, +) + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestFuncs: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_retrieve_logs(self, client: Telnyx) -> None: + func = client.compute.funcs.retrieve_logs( + id="id", + ) + assert_matches_type(FuncRetrieveLogsResponse, func, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_retrieve_logs_with_all_params(self, client: Telnyx) -> None: + func = client.compute.funcs.retrieve_logs( + id="id", + end_time=parse_datetime("2019-12-27T18:11:19.117Z"), + limit=1, + start_time=parse_datetime("2019-12-27T18:11:19.117Z"), + type="runtime", + ) + assert_matches_type(FuncRetrieveLogsResponse, func, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_retrieve_logs(self, client: Telnyx) -> None: + response = client.compute.funcs.with_raw_response.retrieve_logs( + id="id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + func = response.parse() + assert_matches_type(FuncRetrieveLogsResponse, func, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_retrieve_logs(self, client: Telnyx) -> None: + with client.compute.funcs.with_streaming_response.retrieve_logs( + id="id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + func = response.parse() + assert_matches_type(FuncRetrieveLogsResponse, func, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_path_params_retrieve_logs(self, client: Telnyx) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.compute.funcs.with_raw_response.retrieve_logs( + id="", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_retrieve_metric_aggregates(self, client: Telnyx) -> None: + func = client.compute.funcs.retrieve_metric_aggregates( + id="id", + end_time=parse_datetime("2019-12-27T18:11:19.117Z"), + start_time=parse_datetime("2019-12-27T18:11:19.117Z"), + ) + assert_matches_type(FuncRetrieveMetricAggregatesResponse, func, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_retrieve_metric_aggregates_with_all_params(self, client: Telnyx) -> None: + func = client.compute.funcs.retrieve_metric_aggregates( + id="id", + end_time=parse_datetime("2019-12-27T18:11:19.117Z"), + start_time=parse_datetime("2019-12-27T18:11:19.117Z"), + filter_edge_site="filter[edge_site]", + filter_namespace="filter[namespace]", + page_number=0, + page_size=1, + ) + assert_matches_type(FuncRetrieveMetricAggregatesResponse, func, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_retrieve_metric_aggregates(self, client: Telnyx) -> None: + response = client.compute.funcs.with_raw_response.retrieve_metric_aggregates( + id="id", + end_time=parse_datetime("2019-12-27T18:11:19.117Z"), + start_time=parse_datetime("2019-12-27T18:11:19.117Z"), + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + func = response.parse() + assert_matches_type(FuncRetrieveMetricAggregatesResponse, func, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_retrieve_metric_aggregates(self, client: Telnyx) -> None: + with client.compute.funcs.with_streaming_response.retrieve_metric_aggregates( + id="id", + end_time=parse_datetime("2019-12-27T18:11:19.117Z"), + start_time=parse_datetime("2019-12-27T18:11:19.117Z"), + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + func = response.parse() + assert_matches_type(FuncRetrieveMetricAggregatesResponse, func, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_path_params_retrieve_metric_aggregates(self, client: Telnyx) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.compute.funcs.with_raw_response.retrieve_metric_aggregates( + id="", + end_time=parse_datetime("2019-12-27T18:11:19.117Z"), + start_time=parse_datetime("2019-12-27T18:11:19.117Z"), + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_retrieve_revisions(self, client: Telnyx) -> None: + func = client.compute.funcs.retrieve_revisions( + id="id", + ) + assert_matches_type(FuncRetrieveRevisionsResponse, func, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_retrieve_revisions_with_all_params(self, client: Telnyx) -> None: + func = client.compute.funcs.retrieve_revisions( + id="id", + page_number=1, + page_size=1, + ) + assert_matches_type(FuncRetrieveRevisionsResponse, func, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_retrieve_revisions(self, client: Telnyx) -> None: + response = client.compute.funcs.with_raw_response.retrieve_revisions( + id="id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + func = response.parse() + assert_matches_type(FuncRetrieveRevisionsResponse, func, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_retrieve_revisions(self, client: Telnyx) -> None: + with client.compute.funcs.with_streaming_response.retrieve_revisions( + id="id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + func = response.parse() + assert_matches_type(FuncRetrieveRevisionsResponse, func, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_path_params_retrieve_revisions(self, client: Telnyx) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.compute.funcs.with_raw_response.retrieve_revisions( + id="", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_retrieve_ship_inspection(self, client: Telnyx) -> None: + func = client.compute.funcs.retrieve_ship_inspection( + "id", + ) + assert_matches_type(FuncRetrieveShipInspectionResponse, func, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_retrieve_ship_inspection(self, client: Telnyx) -> None: + response = client.compute.funcs.with_raw_response.retrieve_ship_inspection( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + func = response.parse() + assert_matches_type(FuncRetrieveShipInspectionResponse, func, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_retrieve_ship_inspection(self, client: Telnyx) -> None: + with client.compute.funcs.with_streaming_response.retrieve_ship_inspection( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + func = response.parse() + assert_matches_type(FuncRetrieveShipInspectionResponse, func, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_path_params_retrieve_ship_inspection(self, client: Telnyx) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.compute.funcs.with_raw_response.retrieve_ship_inspection( + "", + ) + + +class TestAsyncFuncs: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_retrieve_logs(self, async_client: AsyncTelnyx) -> None: + func = await async_client.compute.funcs.retrieve_logs( + id="id", + ) + assert_matches_type(FuncRetrieveLogsResponse, func, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_retrieve_logs_with_all_params(self, async_client: AsyncTelnyx) -> None: + func = await async_client.compute.funcs.retrieve_logs( + id="id", + end_time=parse_datetime("2019-12-27T18:11:19.117Z"), + limit=1, + start_time=parse_datetime("2019-12-27T18:11:19.117Z"), + type="runtime", + ) + assert_matches_type(FuncRetrieveLogsResponse, func, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_retrieve_logs(self, async_client: AsyncTelnyx) -> None: + response = await async_client.compute.funcs.with_raw_response.retrieve_logs( + id="id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + func = await response.parse() + assert_matches_type(FuncRetrieveLogsResponse, func, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_retrieve_logs(self, async_client: AsyncTelnyx) -> None: + async with async_client.compute.funcs.with_streaming_response.retrieve_logs( + id="id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + func = await response.parse() + assert_matches_type(FuncRetrieveLogsResponse, func, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_path_params_retrieve_logs(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.with_raw_response.retrieve_logs( + id="", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_retrieve_metric_aggregates(self, async_client: AsyncTelnyx) -> None: + func = await async_client.compute.funcs.retrieve_metric_aggregates( + id="id", + end_time=parse_datetime("2019-12-27T18:11:19.117Z"), + start_time=parse_datetime("2019-12-27T18:11:19.117Z"), + ) + assert_matches_type(FuncRetrieveMetricAggregatesResponse, func, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_retrieve_metric_aggregates_with_all_params(self, async_client: AsyncTelnyx) -> None: + func = await async_client.compute.funcs.retrieve_metric_aggregates( + id="id", + end_time=parse_datetime("2019-12-27T18:11:19.117Z"), + start_time=parse_datetime("2019-12-27T18:11:19.117Z"), + filter_edge_site="filter[edge_site]", + filter_namespace="filter[namespace]", + page_number=0, + page_size=1, + ) + assert_matches_type(FuncRetrieveMetricAggregatesResponse, func, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_retrieve_metric_aggregates(self, async_client: AsyncTelnyx) -> None: + response = await async_client.compute.funcs.with_raw_response.retrieve_metric_aggregates( + id="id", + end_time=parse_datetime("2019-12-27T18:11:19.117Z"), + start_time=parse_datetime("2019-12-27T18:11:19.117Z"), + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + func = await response.parse() + assert_matches_type(FuncRetrieveMetricAggregatesResponse, func, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_retrieve_metric_aggregates(self, async_client: AsyncTelnyx) -> None: + async with async_client.compute.funcs.with_streaming_response.retrieve_metric_aggregates( + id="id", + end_time=parse_datetime("2019-12-27T18:11:19.117Z"), + start_time=parse_datetime("2019-12-27T18:11:19.117Z"), + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + func = await response.parse() + assert_matches_type(FuncRetrieveMetricAggregatesResponse, func, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_path_params_retrieve_metric_aggregates(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.with_raw_response.retrieve_metric_aggregates( + id="", + end_time=parse_datetime("2019-12-27T18:11:19.117Z"), + start_time=parse_datetime("2019-12-27T18:11:19.117Z"), + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_retrieve_revisions(self, async_client: AsyncTelnyx) -> None: + func = await async_client.compute.funcs.retrieve_revisions( + id="id", + ) + assert_matches_type(FuncRetrieveRevisionsResponse, func, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_retrieve_revisions_with_all_params(self, async_client: AsyncTelnyx) -> None: + func = await async_client.compute.funcs.retrieve_revisions( + id="id", + page_number=1, + page_size=1, + ) + assert_matches_type(FuncRetrieveRevisionsResponse, func, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_retrieve_revisions(self, async_client: AsyncTelnyx) -> None: + response = await async_client.compute.funcs.with_raw_response.retrieve_revisions( + id="id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + func = await response.parse() + assert_matches_type(FuncRetrieveRevisionsResponse, func, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_retrieve_revisions(self, async_client: AsyncTelnyx) -> None: + async with async_client.compute.funcs.with_streaming_response.retrieve_revisions( + id="id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + func = await response.parse() + assert_matches_type(FuncRetrieveRevisionsResponse, func, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_path_params_retrieve_revisions(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.with_raw_response.retrieve_revisions( + id="", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_retrieve_ship_inspection(self, async_client: AsyncTelnyx) -> None: + func = await async_client.compute.funcs.retrieve_ship_inspection( + "id", + ) + assert_matches_type(FuncRetrieveShipInspectionResponse, func, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_retrieve_ship_inspection(self, async_client: AsyncTelnyx) -> None: + response = await async_client.compute.funcs.with_raw_response.retrieve_ship_inspection( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + func = await response.parse() + assert_matches_type(FuncRetrieveShipInspectionResponse, func, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_retrieve_ship_inspection(self, async_client: AsyncTelnyx) -> None: + async with async_client.compute.funcs.with_streaming_response.retrieve_ship_inspection( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + func = await response.parse() + assert_matches_type(FuncRetrieveShipInspectionResponse, func, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_path_params_retrieve_ship_inspection(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.with_raw_response.retrieve_ship_inspection( + "", + ) diff --git a/tests/api_resources/test_messaging_profiles.py b/tests/api_resources/test_messaging_profiles.py index 0b5a166b6..dad0260e9 100644 --- a/tests/api_resources/test_messaging_profiles.py +++ b/tests/api_resources/test_messaging_profiles.py @@ -47,6 +47,7 @@ def test_method_create_with_all_params(self, client: Telnyx) -> None: daily_spend_limit="269125115713", daily_spend_limit_enabled=True, enabled=True, + features={"ai_opt_out_detection_enabled": True}, health_webhook_url="health_webhook_url", mms_fall_back_to_sms=True, mms_transcoding=True, @@ -160,6 +161,7 @@ def test_method_update_with_all_params(self, client: Telnyx) -> None: daily_spend_limit="269125115713", daily_spend_limit_enabled=True, enabled=True, + features={"ai_opt_out_detection_enabled": True}, mms_fall_back_to_sms=True, mms_transcoding=True, mobile_only=True, @@ -547,6 +549,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncTelnyx) -> daily_spend_limit="269125115713", daily_spend_limit_enabled=True, enabled=True, + features={"ai_opt_out_detection_enabled": True}, health_webhook_url="health_webhook_url", mms_fall_back_to_sms=True, mms_transcoding=True, @@ -660,6 +663,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncTelnyx) -> daily_spend_limit="269125115713", daily_spend_limit_enabled=True, enabled=True, + features={"ai_opt_out_detection_enabled": True}, mms_fall_back_to_sms=True, mms_transcoding=True, mobile_only=True, diff --git a/tests/api_resources/whatsapp/test_phone_numbers.py b/tests/api_resources/whatsapp/test_phone_numbers.py index 9c7d71ace..e96722396 100644 --- a/tests/api_resources/whatsapp/test_phone_numbers.py +++ b/tests/api_resources/whatsapp/test_phone_numbers.py @@ -13,6 +13,7 @@ from telnyx.types.whatsapp import ( PhoneNumberGetResponse, PhoneNumberListResponse, + PhoneNumberRetrievePhoneNumberResponse, PhoneNumberRetrieveConversationWindowResponse, ) @@ -235,6 +236,48 @@ def test_path_params_retrieve_conversation_window(self, client: Telnyx) -> None: destination_number="+353894650851", ) + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_retrieve_phone_number(self, client: Telnyx) -> None: + phone_number = client.whatsapp.phone_numbers.retrieve_phone_number( + "phone_number", + ) + assert_matches_type(PhoneNumberRetrievePhoneNumberResponse, phone_number, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_retrieve_phone_number(self, client: Telnyx) -> None: + response = client.whatsapp.phone_numbers.with_raw_response.retrieve_phone_number( + "phone_number", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + phone_number = response.parse() + assert_matches_type(PhoneNumberRetrievePhoneNumberResponse, phone_number, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_retrieve_phone_number(self, client: Telnyx) -> None: + with client.whatsapp.phone_numbers.with_streaming_response.retrieve_phone_number( + "phone_number", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + phone_number = response.parse() + assert_matches_type(PhoneNumberRetrievePhoneNumberResponse, phone_number, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_path_params_retrieve_phone_number(self, client: Telnyx) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `phone_number` but received ''"): + client.whatsapp.phone_numbers.with_raw_response.retrieve_phone_number( + "", + ) + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_method_verify(self, client: Telnyx) -> None: @@ -500,6 +543,48 @@ async def test_path_params_retrieve_conversation_window(self, async_client: Asyn destination_number="+353894650851", ) + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_retrieve_phone_number(self, async_client: AsyncTelnyx) -> None: + phone_number = await async_client.whatsapp.phone_numbers.retrieve_phone_number( + "phone_number", + ) + assert_matches_type(PhoneNumberRetrievePhoneNumberResponse, phone_number, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_retrieve_phone_number(self, async_client: AsyncTelnyx) -> None: + response = await async_client.whatsapp.phone_numbers.with_raw_response.retrieve_phone_number( + "phone_number", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + phone_number = await response.parse() + assert_matches_type(PhoneNumberRetrievePhoneNumberResponse, phone_number, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_retrieve_phone_number(self, async_client: AsyncTelnyx) -> None: + async with async_client.whatsapp.phone_numbers.with_streaming_response.retrieve_phone_number( + "phone_number", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + phone_number = await response.parse() + assert_matches_type(PhoneNumberRetrievePhoneNumberResponse, phone_number, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_path_params_retrieve_phone_number(self, async_client: AsyncTelnyx) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `phone_number` but received ''"): + await async_client.whatsapp.phone_numbers.with_raw_response.retrieve_phone_number( + "", + ) + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_method_verify(self, async_client: AsyncTelnyx) -> None: diff --git a/tests/api_resources/x402/credit_account/__init__.py b/tests/api_resources/x402/credit_account/__init__.py new file mode 100644 index 000000000..fd8019a9a --- /dev/null +++ b/tests/api_resources/x402/credit_account/__init__.py @@ -0,0 +1 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. diff --git a/tests/api_resources/x402/credit_account/test_payments.py b/tests/api_resources/x402/credit_account/test_payments.py new file mode 100644 index 000000000..74748ba5d --- /dev/null +++ b/tests/api_resources/x402/credit_account/test_payments.py @@ -0,0 +1,183 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from telnyx import Telnyx, AsyncTelnyx +from tests.utils import assert_matches_type +from telnyx.pagination import SyncDefaultFlatPagination, AsyncDefaultFlatPagination +from telnyx.types.x402.credit_account import X402TransactionRecord, PaymentRetrieveResponse + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestPayments: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_retrieve(self, client: Telnyx) -> None: + payment = client.x402.credit_account.payments.retrieve( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert_matches_type(PaymentRetrieveResponse, payment, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_retrieve(self, client: Telnyx) -> None: + response = client.x402.credit_account.payments.with_raw_response.retrieve( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + payment = response.parse() + assert_matches_type(PaymentRetrieveResponse, payment, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_retrieve(self, client: Telnyx) -> None: + with client.x402.credit_account.payments.with_streaming_response.retrieve( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + payment = response.parse() + assert_matches_type(PaymentRetrieveResponse, payment, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_path_params_retrieve(self, client: Telnyx) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.x402.credit_account.payments.with_raw_response.retrieve( + "", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_list(self, client: Telnyx) -> None: + payment = client.x402.credit_account.payments.list() + assert_matches_type(SyncDefaultFlatPagination[X402TransactionRecord], payment, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_list_with_all_params(self, client: Telnyx) -> None: + payment = client.x402.credit_account.payments.list( + page_number=1, + page_size=1, + ) + assert_matches_type(SyncDefaultFlatPagination[X402TransactionRecord], payment, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_list(self, client: Telnyx) -> None: + response = client.x402.credit_account.payments.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + payment = response.parse() + assert_matches_type(SyncDefaultFlatPagination[X402TransactionRecord], payment, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_list(self, client: Telnyx) -> None: + with client.x402.credit_account.payments.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + payment = response.parse() + assert_matches_type(SyncDefaultFlatPagination[X402TransactionRecord], payment, path=["response"]) + + assert cast(Any, response.is_closed) is True + + +class TestAsyncPayments: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_retrieve(self, async_client: AsyncTelnyx) -> None: + payment = await async_client.x402.credit_account.payments.retrieve( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + assert_matches_type(PaymentRetrieveResponse, payment, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_retrieve(self, async_client: AsyncTelnyx) -> None: + response = await async_client.x402.credit_account.payments.with_raw_response.retrieve( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + payment = await response.parse() + assert_matches_type(PaymentRetrieveResponse, payment, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_retrieve(self, async_client: AsyncTelnyx) -> None: + async with async_client.x402.credit_account.payments.with_streaming_response.retrieve( + "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + payment = await response.parse() + assert_matches_type(PaymentRetrieveResponse, payment, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_path_params_retrieve(self, async_client: AsyncTelnyx) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.x402.credit_account.payments.with_raw_response.retrieve( + "", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_list(self, async_client: AsyncTelnyx) -> None: + payment = await async_client.x402.credit_account.payments.list() + assert_matches_type(AsyncDefaultFlatPagination[X402TransactionRecord], payment, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_list_with_all_params(self, async_client: AsyncTelnyx) -> None: + payment = await async_client.x402.credit_account.payments.list( + page_number=1, + page_size=1, + ) + assert_matches_type(AsyncDefaultFlatPagination[X402TransactionRecord], payment, 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.x402.credit_account.payments.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + payment = await response.parse() + assert_matches_type(AsyncDefaultFlatPagination[X402TransactionRecord], payment, 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.x402.credit_account.payments.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + payment = await response.parse() + assert_matches_type(AsyncDefaultFlatPagination[X402TransactionRecord], payment, path=["response"]) + + assert cast(Any, response.is_closed) is True