diff --git a/.stats.yml b/.stats.yml
index ca71746c0ec..f2ae3e506be 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 2404
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/cloudflare/cloudflare-874436f83bd9c383144c69da47c4b767bb9c6f4f2bb4945af58cf3b6015f0f62.yml
-openapi_spec_hash: beaf9a654991bf65d642e05c03460e4c
-config_hash: 2f529580a17438fc62cd0b47db41b6f1
+configured_endpoints: 2409
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/cloudflare/cloudflare-2638067e2ee443dc7c7a5fa38c2a7ed38f7bbd6de7db58aa4b364539ea96000c.yml
+openapi_spec_hash: b955d89313a0c7f4e27f2aaa04cd13a8
+config_hash: bbf6df558b7c0807286a2085dd306dde
diff --git a/api.md b/api.md
index b05e7b8d057..7152ccab0d6 100644
--- a/api.md
+++ b/api.md
@@ -211,6 +211,8 @@ from cloudflare.types import (
# [Calls](src/cloudflare/resources/calls/api.md)
+# [Moq](src/cloudflare/resources/moq/api.md)
+
# [CloudforceOne](src/cloudflare/resources/cloudforce_one/api.md)
# [AIGateway](src/cloudflare/resources/ai_gateway/api.md)
diff --git a/src/cloudflare/_client.py b/src/cloudflare/_client.py
index af5c148ccc9..ef29c9e0f72 100644
--- a/src/cloudflare/_client.py
+++ b/src/cloudflare/_client.py
@@ -47,6 +47,7 @@
dns,
iam,
ips,
+ moq,
rum,
ssl,
argo,
@@ -163,6 +164,7 @@
from .resources.dns.dns import DNSResource, AsyncDNSResource
from .resources.iam.iam import IAMResource, AsyncIAMResource
from .resources.ips.ips import IPsResource, AsyncIPsResource
+ from .resources.moq.moq import MoqResource, AsyncMoqResource
from .resources.rum.rum import RUMResource, AsyncRUMResource
from .resources.ssl.ssl import SSLResource, AsyncSSLResource
from .resources.argo.argo import ArgoResource, AsyncArgoResource
@@ -965,6 +967,12 @@ def calls(self) -> CallsResource:
return CallsResource(self)
+ @cached_property
+ def moq(self) -> MoqResource:
+ from .resources.moq import MoqResource
+
+ return MoqResource(self)
+
@cached_property
def cloudforce_one(self) -> CloudforceOneResource:
from .resources.cloudforce_one import CloudforceOneResource
@@ -1917,6 +1925,12 @@ def calls(self) -> AsyncCallsResource:
return AsyncCallsResource(self)
+ @cached_property
+ def moq(self) -> AsyncMoqResource:
+ from .resources.moq import AsyncMoqResource
+
+ return AsyncMoqResource(self)
+
@cached_property
def cloudforce_one(self) -> AsyncCloudforceOneResource:
from .resources.cloudforce_one import AsyncCloudforceOneResource
@@ -2793,6 +2807,12 @@ def calls(self) -> calls.CallsResourceWithRawResponse:
return CallsResourceWithRawResponse(self._client.calls)
+ @cached_property
+ def moq(self) -> moq.MoqResourceWithRawResponse:
+ from .resources.moq import MoqResourceWithRawResponse
+
+ return MoqResourceWithRawResponse(self._client.moq)
+
@cached_property
def cloudforce_one(self) -> cloudforce_one.CloudforceOneResourceWithRawResponse:
from .resources.cloudforce_one import CloudforceOneResourceWithRawResponse
@@ -3496,6 +3516,12 @@ def calls(self) -> calls.AsyncCallsResourceWithRawResponse:
return AsyncCallsResourceWithRawResponse(self._client.calls)
+ @cached_property
+ def moq(self) -> moq.AsyncMoqResourceWithRawResponse:
+ from .resources.moq import AsyncMoqResourceWithRawResponse
+
+ return AsyncMoqResourceWithRawResponse(self._client.moq)
+
@cached_property
def cloudforce_one(self) -> cloudforce_one.AsyncCloudforceOneResourceWithRawResponse:
from .resources.cloudforce_one import AsyncCloudforceOneResourceWithRawResponse
@@ -4199,6 +4225,12 @@ def calls(self) -> calls.CallsResourceWithStreamingResponse:
return CallsResourceWithStreamingResponse(self._client.calls)
+ @cached_property
+ def moq(self) -> moq.MoqResourceWithStreamingResponse:
+ from .resources.moq import MoqResourceWithStreamingResponse
+
+ return MoqResourceWithStreamingResponse(self._client.moq)
+
@cached_property
def cloudforce_one(self) -> cloudforce_one.CloudforceOneResourceWithStreamingResponse:
from .resources.cloudforce_one import CloudforceOneResourceWithStreamingResponse
@@ -4910,6 +4942,12 @@ def calls(self) -> calls.AsyncCallsResourceWithStreamingResponse:
return AsyncCallsResourceWithStreamingResponse(self._client.calls)
+ @cached_property
+ def moq(self) -> moq.AsyncMoqResourceWithStreamingResponse:
+ from .resources.moq import AsyncMoqResourceWithStreamingResponse
+
+ return AsyncMoqResourceWithStreamingResponse(self._client.moq)
+
@cached_property
def cloudforce_one(self) -> cloudforce_one.AsyncCloudforceOneResourceWithStreamingResponse:
from .resources.cloudforce_one import AsyncCloudforceOneResourceWithStreamingResponse
diff --git a/src/cloudflare/resources/email_routing/api.md b/src/cloudflare/resources/email_routing/api.md
index 26a1d76019a..60551e95244 100644
--- a/src/cloudflare/resources/email_routing/api.md
+++ b/src/cloudflare/resources/email_routing/api.md
@@ -39,7 +39,6 @@ Methods:
- client.email_routing.rules.create(\*, zone_id, \*\*params) -> Optional[EmailRoutingRule]
- client.email_routing.rules.update(rule_identifier, \*, zone_id, \*\*params) -> Optional[EmailRoutingRule]
-- client.email_routing.rules.list(\*, zone_id, \*\*params) -> SyncV4PagePaginationArray[EmailRoutingRule]
- client.email_routing.rules.delete(rule_identifier, \*, zone_id) -> Optional[EmailRoutingRule]
- client.email_routing.rules.get(rule_identifier, \*, zone_id) -> Optional[EmailRoutingRule]
diff --git a/src/cloudflare/resources/email_routing/rules/rules.py b/src/cloudflare/resources/email_routing/rules/rules.py
index b38ce74c7a0..cff2f977c39 100644
--- a/src/cloudflare/resources/email_routing/rules/rules.py
+++ b/src/cloudflare/resources/email_routing/rules/rules.py
@@ -26,9 +26,8 @@
async_to_streamed_response_wrapper,
)
from ...._wrappers import ResultWrapper
-from ....pagination import SyncV4PagePaginationArray, AsyncV4PagePaginationArray
-from ...._base_client import AsyncPaginator, make_request_options
-from ....types.email_routing import rule_list_params, rule_create_params, rule_update_params
+from ...._base_client import make_request_options
+from ....types.email_routing import rule_create_params, rule_update_params
from ....types.email_routing.action_param import ActionParam
from ....types.email_routing.matcher_param import MatcherParam
from ....types.email_routing.email_routing_rule import EmailRoutingRule
@@ -202,62 +201,6 @@ def update(
cast_to=cast(Type[Optional[EmailRoutingRule]], ResultWrapper[EmailRoutingRule]),
)
- def list(
- self,
- *,
- zone_id: str,
- enabled: Literal[True, False] | Omit = omit,
- page: float | Omit = omit,
- per_page: float | 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,
- ) -> SyncV4PagePaginationArray[EmailRoutingRule]:
- """
- Lists existing routing rules.
-
- Args:
- zone_id: Identifier.
-
- enabled: Filter by enabled routing rules.
-
- page: Page number of paginated results.
-
- per_page: Maximum number of results per 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
- """
- if not zone_id:
- raise ValueError(f"Expected a non-empty value for `zone_id` but received {zone_id!r}")
- return self._get_api_list(
- path_template("/zones/{zone_id}/email/routing/rules", zone_id=zone_id),
- page=SyncV4PagePaginationArray[EmailRoutingRule],
- options=make_request_options(
- extra_headers=extra_headers,
- extra_query=extra_query,
- extra_body=extra_body,
- timeout=timeout,
- query=maybe_transform(
- {
- "enabled": enabled,
- "page": page,
- "per_page": per_page,
- },
- rule_list_params.RuleListParams,
- ),
- ),
- model=EmailRoutingRule,
- )
-
def delete(
self,
rule_identifier: str,
@@ -521,62 +464,6 @@ async def update(
cast_to=cast(Type[Optional[EmailRoutingRule]], ResultWrapper[EmailRoutingRule]),
)
- def list(
- self,
- *,
- zone_id: str,
- enabled: Literal[True, False] | Omit = omit,
- page: float | Omit = omit,
- per_page: float | 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[EmailRoutingRule, AsyncV4PagePaginationArray[EmailRoutingRule]]:
- """
- Lists existing routing rules.
-
- Args:
- zone_id: Identifier.
-
- enabled: Filter by enabled routing rules.
-
- page: Page number of paginated results.
-
- per_page: Maximum number of results per 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
- """
- if not zone_id:
- raise ValueError(f"Expected a non-empty value for `zone_id` but received {zone_id!r}")
- return self._get_api_list(
- path_template("/zones/{zone_id}/email/routing/rules", zone_id=zone_id),
- page=AsyncV4PagePaginationArray[EmailRoutingRule],
- options=make_request_options(
- extra_headers=extra_headers,
- extra_query=extra_query,
- extra_body=extra_body,
- timeout=timeout,
- query=maybe_transform(
- {
- "enabled": enabled,
- "page": page,
- "per_page": per_page,
- },
- rule_list_params.RuleListParams,
- ),
- ),
- model=EmailRoutingRule,
- )
-
async def delete(
self,
rule_identifier: str,
@@ -684,9 +571,6 @@ def __init__(self, rules: RulesResource) -> None:
self.update = to_raw_response_wrapper(
rules.update,
)
- self.list = to_raw_response_wrapper(
- rules.list,
- )
self.delete = to_raw_response_wrapper(
rules.delete,
)
@@ -709,9 +593,6 @@ def __init__(self, rules: AsyncRulesResource) -> None:
self.update = async_to_raw_response_wrapper(
rules.update,
)
- self.list = async_to_raw_response_wrapper(
- rules.list,
- )
self.delete = async_to_raw_response_wrapper(
rules.delete,
)
@@ -734,9 +615,6 @@ def __init__(self, rules: RulesResource) -> None:
self.update = to_streamed_response_wrapper(
rules.update,
)
- self.list = to_streamed_response_wrapper(
- rules.list,
- )
self.delete = to_streamed_response_wrapper(
rules.delete,
)
@@ -759,9 +637,6 @@ def __init__(self, rules: AsyncRulesResource) -> None:
self.update = async_to_streamed_response_wrapper(
rules.update,
)
- self.list = async_to_streamed_response_wrapper(
- rules.list,
- )
self.delete = async_to_streamed_response_wrapper(
rules.delete,
)
diff --git a/src/cloudflare/resources/email_security/investigate/move.py b/src/cloudflare/resources/email_security/investigate/move.py
index 8fa530641c6..d23739406cb 100644
--- a/src/cloudflare/resources/email_security/investigate/move.py
+++ b/src/cloudflare/resources/email_security/investigate/move.py
@@ -53,6 +53,19 @@ def create(
destination: Literal[
"Inbox", "JunkEmail", "DeletedItems", "RecoverableItemsDeletions", "RecoverableItemsPurges"
],
+ expected_disposition: Literal[
+ "MALICIOUS",
+ "MALICIOUS-BEC",
+ "SUSPICIOUS",
+ "SPOOF",
+ "SPAM",
+ "BULK",
+ "ENCRYPTED",
+ "EXTERNAL",
+ "UNKNOWN",
+ "NONE",
+ ]
+ | 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,
@@ -89,7 +102,13 @@ def create(
investigate_id=investigate_id,
),
page=SyncSinglePage[MoveCreateResponse],
- body=maybe_transform({"destination": destination}, move_create_params.MoveCreateParams),
+ body=maybe_transform(
+ {
+ "destination": destination,
+ "expected_disposition": expected_disposition,
+ },
+ move_create_params.MoveCreateParams,
+ ),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -104,6 +123,19 @@ def bulk(
destination: Literal[
"Inbox", "JunkEmail", "DeletedItems", "RecoverableItemsDeletions", "RecoverableItemsPurges"
],
+ expected_disposition: Literal[
+ "MALICIOUS",
+ "MALICIOUS-BEC",
+ "SUSPICIOUS",
+ "SPOOF",
+ "SPAM",
+ "BULK",
+ "ENCRYPTED",
+ "EXTERNAL",
+ "UNKNOWN",
+ "NONE",
+ ]
+ | Omit = omit,
ids: SequenceNotStr[str] | Omit = omit,
postfix_ids: SequenceNotStr[str] | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
@@ -142,6 +174,7 @@ def bulk(
body=maybe_transform(
{
"destination": destination,
+ "expected_disposition": expected_disposition,
"ids": ids,
"postfix_ids": postfix_ids,
},
@@ -183,6 +216,19 @@ def create(
destination: Literal[
"Inbox", "JunkEmail", "DeletedItems", "RecoverableItemsDeletions", "RecoverableItemsPurges"
],
+ expected_disposition: Literal[
+ "MALICIOUS",
+ "MALICIOUS-BEC",
+ "SUSPICIOUS",
+ "SPOOF",
+ "SPAM",
+ "BULK",
+ "ENCRYPTED",
+ "EXTERNAL",
+ "UNKNOWN",
+ "NONE",
+ ]
+ | 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,
@@ -219,7 +265,13 @@ def create(
investigate_id=investigate_id,
),
page=AsyncSinglePage[MoveCreateResponse],
- body=maybe_transform({"destination": destination}, move_create_params.MoveCreateParams),
+ body=maybe_transform(
+ {
+ "destination": destination,
+ "expected_disposition": expected_disposition,
+ },
+ move_create_params.MoveCreateParams,
+ ),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -234,6 +286,19 @@ def bulk(
destination: Literal[
"Inbox", "JunkEmail", "DeletedItems", "RecoverableItemsDeletions", "RecoverableItemsPurges"
],
+ expected_disposition: Literal[
+ "MALICIOUS",
+ "MALICIOUS-BEC",
+ "SUSPICIOUS",
+ "SPOOF",
+ "SPAM",
+ "BULK",
+ "ENCRYPTED",
+ "EXTERNAL",
+ "UNKNOWN",
+ "NONE",
+ ]
+ | Omit = omit,
ids: SequenceNotStr[str] | Omit = omit,
postfix_ids: SequenceNotStr[str] | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
@@ -272,6 +337,7 @@ def bulk(
body=maybe_transform(
{
"destination": destination,
+ "expected_disposition": expected_disposition,
"ids": ids,
"postfix_ids": postfix_ids,
},
diff --git a/src/cloudflare/resources/moq/__init__.py b/src/cloudflare/resources/moq/__init__.py
new file mode 100644
index 00000000000..02338c3f29f
--- /dev/null
+++ b/src/cloudflare/resources/moq/__init__.py
@@ -0,0 +1,33 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from .moq import (
+ MoqResource,
+ AsyncMoqResource,
+ MoqResourceWithRawResponse,
+ AsyncMoqResourceWithRawResponse,
+ MoqResourceWithStreamingResponse,
+ AsyncMoqResourceWithStreamingResponse,
+)
+from .relays import (
+ RelaysResource,
+ AsyncRelaysResource,
+ RelaysResourceWithRawResponse,
+ AsyncRelaysResourceWithRawResponse,
+ RelaysResourceWithStreamingResponse,
+ AsyncRelaysResourceWithStreamingResponse,
+)
+
+__all__ = [
+ "RelaysResource",
+ "AsyncRelaysResource",
+ "RelaysResourceWithRawResponse",
+ "AsyncRelaysResourceWithRawResponse",
+ "RelaysResourceWithStreamingResponse",
+ "AsyncRelaysResourceWithStreamingResponse",
+ "MoqResource",
+ "AsyncMoqResource",
+ "MoqResourceWithRawResponse",
+ "AsyncMoqResourceWithRawResponse",
+ "MoqResourceWithStreamingResponse",
+ "AsyncMoqResourceWithStreamingResponse",
+]
diff --git a/src/cloudflare/resources/moq/api.md b/src/cloudflare/resources/moq/api.md
new file mode 100644
index 00000000000..1e91155e3fa
--- /dev/null
+++ b/src/cloudflare/resources/moq/api.md
@@ -0,0 +1,34 @@
+# Moq
+
+## Relays
+
+Types:
+
+```python
+from cloudflare.types.moq import (
+ RelayCreateResponse,
+ RelayUpdateResponse,
+ RelayListResponse,
+ RelayGetResponse,
+)
+```
+
+Methods:
+
+- client.moq.relays.create(\*, account_id, \*\*params) -> Optional[RelayCreateResponse]
+- client.moq.relays.update(relay_id, \*, account_id, \*\*params) -> Optional[RelayUpdateResponse]
+- client.moq.relays.list(\*, account_id, \*\*params) -> SyncSinglePage[RelayListResponse]
+- client.moq.relays.delete(relay_id, \*, account_id) -> object
+- client.moq.relays.get(relay_id, \*, account_id) -> Optional[RelayGetResponse]
+
+### Tokens
+
+Types:
+
+```python
+from cloudflare.types.moq.relays import TokenRotateResponse
+```
+
+Methods:
+
+- client.moq.relays.tokens.rotate(relay_id, \*, account_id, \*\*params) -> Optional[TokenRotateResponse]
diff --git a/src/cloudflare/resources/moq/moq.py b/src/cloudflare/resources/moq/moq.py
new file mode 100644
index 00000000000..092ebafe1d1
--- /dev/null
+++ b/src/cloudflare/resources/moq/moq.py
@@ -0,0 +1,102 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from ..._compat import cached_property
+from ..._resource import SyncAPIResource, AsyncAPIResource
+from .relays.relays import (
+ RelaysResource,
+ AsyncRelaysResource,
+ RelaysResourceWithRawResponse,
+ AsyncRelaysResourceWithRawResponse,
+ RelaysResourceWithStreamingResponse,
+ AsyncRelaysResourceWithStreamingResponse,
+)
+
+__all__ = ["MoqResource", "AsyncMoqResource"]
+
+
+class MoqResource(SyncAPIResource):
+ @cached_property
+ def relays(self) -> RelaysResource:
+ return RelaysResource(self._client)
+
+ @cached_property
+ def with_raw_response(self) -> MoqResourceWithRawResponse:
+ """
+ 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/cloudflare/cloudflare-python#accessing-raw-response-data-eg-headers
+ """
+ return MoqResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> MoqResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/cloudflare/cloudflare-python#with_streaming_response
+ """
+ return MoqResourceWithStreamingResponse(self)
+
+
+class AsyncMoqResource(AsyncAPIResource):
+ @cached_property
+ def relays(self) -> AsyncRelaysResource:
+ return AsyncRelaysResource(self._client)
+
+ @cached_property
+ def with_raw_response(self) -> AsyncMoqResourceWithRawResponse:
+ """
+ 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/cloudflare/cloudflare-python#accessing-raw-response-data-eg-headers
+ """
+ return AsyncMoqResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncMoqResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/cloudflare/cloudflare-python#with_streaming_response
+ """
+ return AsyncMoqResourceWithStreamingResponse(self)
+
+
+class MoqResourceWithRawResponse:
+ def __init__(self, moq: MoqResource) -> None:
+ self._moq = moq
+
+ @cached_property
+ def relays(self) -> RelaysResourceWithRawResponse:
+ return RelaysResourceWithRawResponse(self._moq.relays)
+
+
+class AsyncMoqResourceWithRawResponse:
+ def __init__(self, moq: AsyncMoqResource) -> None:
+ self._moq = moq
+
+ @cached_property
+ def relays(self) -> AsyncRelaysResourceWithRawResponse:
+ return AsyncRelaysResourceWithRawResponse(self._moq.relays)
+
+
+class MoqResourceWithStreamingResponse:
+ def __init__(self, moq: MoqResource) -> None:
+ self._moq = moq
+
+ @cached_property
+ def relays(self) -> RelaysResourceWithStreamingResponse:
+ return RelaysResourceWithStreamingResponse(self._moq.relays)
+
+
+class AsyncMoqResourceWithStreamingResponse:
+ def __init__(self, moq: AsyncMoqResource) -> None:
+ self._moq = moq
+
+ @cached_property
+ def relays(self) -> AsyncRelaysResourceWithStreamingResponse:
+ return AsyncRelaysResourceWithStreamingResponse(self._moq.relays)
diff --git a/src/cloudflare/resources/moq/relays/__init__.py b/src/cloudflare/resources/moq/relays/__init__.py
new file mode 100644
index 00000000000..c69bba67272
--- /dev/null
+++ b/src/cloudflare/resources/moq/relays/__init__.py
@@ -0,0 +1,33 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from .relays import (
+ RelaysResource,
+ AsyncRelaysResource,
+ RelaysResourceWithRawResponse,
+ AsyncRelaysResourceWithRawResponse,
+ RelaysResourceWithStreamingResponse,
+ AsyncRelaysResourceWithStreamingResponse,
+)
+from .tokens import (
+ TokensResource,
+ AsyncTokensResource,
+ TokensResourceWithRawResponse,
+ AsyncTokensResourceWithRawResponse,
+ TokensResourceWithStreamingResponse,
+ AsyncTokensResourceWithStreamingResponse,
+)
+
+__all__ = [
+ "TokensResource",
+ "AsyncTokensResource",
+ "TokensResourceWithRawResponse",
+ "AsyncTokensResourceWithRawResponse",
+ "TokensResourceWithStreamingResponse",
+ "AsyncTokensResourceWithStreamingResponse",
+ "RelaysResource",
+ "AsyncRelaysResource",
+ "RelaysResourceWithRawResponse",
+ "AsyncRelaysResourceWithRawResponse",
+ "RelaysResourceWithStreamingResponse",
+ "AsyncRelaysResourceWithStreamingResponse",
+]
diff --git a/src/cloudflare/resources/moq/relays/relays.py b/src/cloudflare/resources/moq/relays/relays.py
new file mode 100644
index 00000000000..11eed213e54
--- /dev/null
+++ b/src/cloudflare/resources/moq/relays/relays.py
@@ -0,0 +1,709 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Type, Union, Optional, cast
+from datetime import datetime
+
+import httpx
+
+from .tokens import (
+ TokensResource,
+ AsyncTokensResource,
+ TokensResourceWithRawResponse,
+ AsyncTokensResourceWithRawResponse,
+ TokensResourceWithStreamingResponse,
+ AsyncTokensResourceWithStreamingResponse,
+)
+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 ...._wrappers import ResultWrapper
+from ....types.moq import relay_list_params, relay_create_params, relay_update_params
+from ....pagination import SyncSinglePage, AsyncSinglePage
+from ...._base_client import AsyncPaginator, make_request_options
+from ....types.moq.relay_get_response import RelayGetResponse
+from ....types.moq.relay_list_response import RelayListResponse
+from ....types.moq.relay_create_response import RelayCreateResponse
+from ....types.moq.relay_update_response import RelayUpdateResponse
+
+__all__ = ["RelaysResource", "AsyncRelaysResource"]
+
+
+class RelaysResource(SyncAPIResource):
+ @cached_property
+ def tokens(self) -> TokensResource:
+ return TokensResource(self._client)
+
+ @cached_property
+ def with_raw_response(self) -> RelaysResourceWithRawResponse:
+ """
+ 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/cloudflare/cloudflare-python#accessing-raw-response-data-eg-headers
+ """
+ return RelaysResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> RelaysResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/cloudflare/cloudflare-python#with_streaming_response
+ """
+ return RelaysResourceWithStreamingResponse(self)
+
+ def create(
+ self,
+ *,
+ account_id: str,
+ name: 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,
+ ) -> Optional[RelayCreateResponse]:
+ """Provisions a new MoQ relay instance.
+
+ Auto-creates a publish+subscribe token and
+ a subscribe-only token. Token values are included in the response (shown once).
+ Config is set to defaults (lingering subscribe enabled, 30s ceiling, origin
+ fallback off). Use PUT to modify.
+
+ Args:
+ account_id: Cloudflare account identifier.
+
+ name: Human-readable name for the relay.
+
+ 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 account_id:
+ raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}")
+ return self._post(
+ path_template("/accounts/{account_id}/moq/relays", account_id=account_id),
+ body=maybe_transform({"name": name}, relay_create_params.RelayCreateParams),
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ post_parser=ResultWrapper[Optional[RelayCreateResponse]]._unwrapper,
+ ),
+ cast_to=cast(Type[Optional[RelayCreateResponse]], ResultWrapper[RelayCreateResponse]),
+ )
+
+ def update(
+ self,
+ relay_id: str,
+ *,
+ account_id: str,
+ config: relay_update_params.Config | Omit = omit,
+ name: str | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> Optional[RelayUpdateResponse]:
+ """Updates a relay's name and/or configuration.
+
+ Partial updates: omitted fields are
+ preserved. Config sub-objects replace as whole objects when present.
+ origin_fallback and lingering_subscribe are mutually exclusive.
+
+ Args:
+ account_id: Cloudflare account identifier.
+
+ config: origin_fallback and lingering_subscribe are mutually exclusive.
+
+ 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 account_id:
+ raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}")
+ if not relay_id:
+ raise ValueError(f"Expected a non-empty value for `relay_id` but received {relay_id!r}")
+ return self._put(
+ path_template("/accounts/{account_id}/moq/relays/{relay_id}", account_id=account_id, relay_id=relay_id),
+ body=maybe_transform(
+ {
+ "config": config,
+ "name": name,
+ },
+ relay_update_params.RelayUpdateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ post_parser=ResultWrapper[Optional[RelayUpdateResponse]]._unwrapper,
+ ),
+ cast_to=cast(Type[Optional[RelayUpdateResponse]], ResultWrapper[RelayUpdateResponse]),
+ )
+
+ def list(
+ self,
+ *,
+ account_id: str,
+ asc: bool | Omit = omit,
+ created_after: Union[str, datetime] | Omit = omit,
+ created_before: Union[str, datetime] | Omit = omit,
+ per_page: 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,
+ ) -> SyncSinglePage[RelayListResponse]:
+ """Lists all MoQ relays for the account.
+
+ Returns only metadata. Config, status, and
+ tokens are omitted.
+
+ Results are cursor-paginated (keyset on the `created` timestamp). Use
+ `created_before` / `created_after` with the `created` value of the first/last
+ item in a page to fetch the adjacent page. `result_info` reports the page
+ `count` and the `total` matching the cursor filters.
+
+ Args:
+ account_id: Cloudflare account identifier.
+
+ asc: Sort order by `created`. When true, results are returned oldest-first
+ (ascending); otherwise newest-first (descending, the default).
+
+ created_after: Cursor for pagination. Returns relays created strictly after this RFC 3339
+ timestamp (typically the `created` value of the last item on the current page,
+ to fetch the next page).
+
+ created_before: Cursor for pagination. Returns relays created strictly before this RFC 3339
+ timestamp (typically the `created` value of the first item on the current page,
+ to fetch the previous page).
+
+ per_page: Maximum number of relays to return per 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
+ """
+ if not account_id:
+ raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}")
+ return self._get_api_list(
+ path_template("/accounts/{account_id}/moq/relays", account_id=account_id),
+ page=SyncSinglePage[RelayListResponse],
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {
+ "asc": asc,
+ "created_after": created_after,
+ "created_before": created_before,
+ "per_page": per_page,
+ },
+ relay_list_params.RelayListParams,
+ ),
+ ),
+ model=RelayListResponse,
+ )
+
+ def delete(
+ self,
+ relay_id: str,
+ *,
+ account_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,
+ ) -> object:
+ """
+ Soft-deletes a MoQ relay.
+
+ Args:
+ account_id: Cloudflare account identifier.
+
+ 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 account_id:
+ raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}")
+ if not relay_id:
+ raise ValueError(f"Expected a non-empty value for `relay_id` but received {relay_id!r}")
+ return self._delete(
+ path_template("/accounts/{account_id}/moq/relays/{relay_id}", account_id=account_id, relay_id=relay_id),
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ post_parser=ResultWrapper[Optional[object]]._unwrapper,
+ ),
+ cast_to=cast(Type[object], ResultWrapper[object]),
+ )
+
+ def get(
+ self,
+ relay_id: str,
+ *,
+ account_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,
+ ) -> Optional[RelayGetResponse]:
+ """Retrieves a single MoQ relay including config and status.
+
+ Tokens are NOT
+ included.
+
+ Args:
+ account_id: Cloudflare account identifier.
+
+ 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 account_id:
+ raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}")
+ if not relay_id:
+ raise ValueError(f"Expected a non-empty value for `relay_id` but received {relay_id!r}")
+ return self._get(
+ path_template("/accounts/{account_id}/moq/relays/{relay_id}", account_id=account_id, relay_id=relay_id),
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ post_parser=ResultWrapper[Optional[RelayGetResponse]]._unwrapper,
+ ),
+ cast_to=cast(Type[Optional[RelayGetResponse]], ResultWrapper[RelayGetResponse]),
+ )
+
+
+class AsyncRelaysResource(AsyncAPIResource):
+ @cached_property
+ def tokens(self) -> AsyncTokensResource:
+ return AsyncTokensResource(self._client)
+
+ @cached_property
+ def with_raw_response(self) -> AsyncRelaysResourceWithRawResponse:
+ """
+ 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/cloudflare/cloudflare-python#accessing-raw-response-data-eg-headers
+ """
+ return AsyncRelaysResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncRelaysResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/cloudflare/cloudflare-python#with_streaming_response
+ """
+ return AsyncRelaysResourceWithStreamingResponse(self)
+
+ async def create(
+ self,
+ *,
+ account_id: str,
+ name: 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,
+ ) -> Optional[RelayCreateResponse]:
+ """Provisions a new MoQ relay instance.
+
+ Auto-creates a publish+subscribe token and
+ a subscribe-only token. Token values are included in the response (shown once).
+ Config is set to defaults (lingering subscribe enabled, 30s ceiling, origin
+ fallback off). Use PUT to modify.
+
+ Args:
+ account_id: Cloudflare account identifier.
+
+ name: Human-readable name for the relay.
+
+ 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 account_id:
+ raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}")
+ return await self._post(
+ path_template("/accounts/{account_id}/moq/relays", account_id=account_id),
+ body=await async_maybe_transform({"name": name}, relay_create_params.RelayCreateParams),
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ post_parser=ResultWrapper[Optional[RelayCreateResponse]]._unwrapper,
+ ),
+ cast_to=cast(Type[Optional[RelayCreateResponse]], ResultWrapper[RelayCreateResponse]),
+ )
+
+ async def update(
+ self,
+ relay_id: str,
+ *,
+ account_id: str,
+ config: relay_update_params.Config | Omit = omit,
+ name: str | Omit = omit,
+ # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
+ # The extra values given here take precedence over values defined on the client or passed to this method.
+ extra_headers: Headers | None = None,
+ extra_query: Query | None = None,
+ extra_body: Body | None = None,
+ timeout: float | httpx.Timeout | None | NotGiven = not_given,
+ ) -> Optional[RelayUpdateResponse]:
+ """Updates a relay's name and/or configuration.
+
+ Partial updates: omitted fields are
+ preserved. Config sub-objects replace as whole objects when present.
+ origin_fallback and lingering_subscribe are mutually exclusive.
+
+ Args:
+ account_id: Cloudflare account identifier.
+
+ config: origin_fallback and lingering_subscribe are mutually exclusive.
+
+ 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 account_id:
+ raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}")
+ if not relay_id:
+ raise ValueError(f"Expected a non-empty value for `relay_id` but received {relay_id!r}")
+ return await self._put(
+ path_template("/accounts/{account_id}/moq/relays/{relay_id}", account_id=account_id, relay_id=relay_id),
+ body=await async_maybe_transform(
+ {
+ "config": config,
+ "name": name,
+ },
+ relay_update_params.RelayUpdateParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ post_parser=ResultWrapper[Optional[RelayUpdateResponse]]._unwrapper,
+ ),
+ cast_to=cast(Type[Optional[RelayUpdateResponse]], ResultWrapper[RelayUpdateResponse]),
+ )
+
+ def list(
+ self,
+ *,
+ account_id: str,
+ asc: bool | Omit = omit,
+ created_after: Union[str, datetime] | Omit = omit,
+ created_before: Union[str, datetime] | Omit = omit,
+ per_page: 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[RelayListResponse, AsyncSinglePage[RelayListResponse]]:
+ """Lists all MoQ relays for the account.
+
+ Returns only metadata. Config, status, and
+ tokens are omitted.
+
+ Results are cursor-paginated (keyset on the `created` timestamp). Use
+ `created_before` / `created_after` with the `created` value of the first/last
+ item in a page to fetch the adjacent page. `result_info` reports the page
+ `count` and the `total` matching the cursor filters.
+
+ Args:
+ account_id: Cloudflare account identifier.
+
+ asc: Sort order by `created`. When true, results are returned oldest-first
+ (ascending); otherwise newest-first (descending, the default).
+
+ created_after: Cursor for pagination. Returns relays created strictly after this RFC 3339
+ timestamp (typically the `created` value of the last item on the current page,
+ to fetch the next page).
+
+ created_before: Cursor for pagination. Returns relays created strictly before this RFC 3339
+ timestamp (typically the `created` value of the first item on the current page,
+ to fetch the previous page).
+
+ per_page: Maximum number of relays to return per 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
+ """
+ if not account_id:
+ raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}")
+ return self._get_api_list(
+ path_template("/accounts/{account_id}/moq/relays", account_id=account_id),
+ page=AsyncSinglePage[RelayListResponse],
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {
+ "asc": asc,
+ "created_after": created_after,
+ "created_before": created_before,
+ "per_page": per_page,
+ },
+ relay_list_params.RelayListParams,
+ ),
+ ),
+ model=RelayListResponse,
+ )
+
+ async def delete(
+ self,
+ relay_id: str,
+ *,
+ account_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,
+ ) -> object:
+ """
+ Soft-deletes a MoQ relay.
+
+ Args:
+ account_id: Cloudflare account identifier.
+
+ 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 account_id:
+ raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}")
+ if not relay_id:
+ raise ValueError(f"Expected a non-empty value for `relay_id` but received {relay_id!r}")
+ return await self._delete(
+ path_template("/accounts/{account_id}/moq/relays/{relay_id}", account_id=account_id, relay_id=relay_id),
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ post_parser=ResultWrapper[Optional[object]]._unwrapper,
+ ),
+ cast_to=cast(Type[object], ResultWrapper[object]),
+ )
+
+ async def get(
+ self,
+ relay_id: str,
+ *,
+ account_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,
+ ) -> Optional[RelayGetResponse]:
+ """Retrieves a single MoQ relay including config and status.
+
+ Tokens are NOT
+ included.
+
+ Args:
+ account_id: Cloudflare account identifier.
+
+ 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 account_id:
+ raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}")
+ if not relay_id:
+ raise ValueError(f"Expected a non-empty value for `relay_id` but received {relay_id!r}")
+ return await self._get(
+ path_template("/accounts/{account_id}/moq/relays/{relay_id}", account_id=account_id, relay_id=relay_id),
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ post_parser=ResultWrapper[Optional[RelayGetResponse]]._unwrapper,
+ ),
+ cast_to=cast(Type[Optional[RelayGetResponse]], ResultWrapper[RelayGetResponse]),
+ )
+
+
+class RelaysResourceWithRawResponse:
+ def __init__(self, relays: RelaysResource) -> None:
+ self._relays = relays
+
+ self.create = to_raw_response_wrapper(
+ relays.create,
+ )
+ self.update = to_raw_response_wrapper(
+ relays.update,
+ )
+ self.list = to_raw_response_wrapper(
+ relays.list,
+ )
+ self.delete = to_raw_response_wrapper(
+ relays.delete,
+ )
+ self.get = to_raw_response_wrapper(
+ relays.get,
+ )
+
+ @cached_property
+ def tokens(self) -> TokensResourceWithRawResponse:
+ return TokensResourceWithRawResponse(self._relays.tokens)
+
+
+class AsyncRelaysResourceWithRawResponse:
+ def __init__(self, relays: AsyncRelaysResource) -> None:
+ self._relays = relays
+
+ self.create = async_to_raw_response_wrapper(
+ relays.create,
+ )
+ self.update = async_to_raw_response_wrapper(
+ relays.update,
+ )
+ self.list = async_to_raw_response_wrapper(
+ relays.list,
+ )
+ self.delete = async_to_raw_response_wrapper(
+ relays.delete,
+ )
+ self.get = async_to_raw_response_wrapper(
+ relays.get,
+ )
+
+ @cached_property
+ def tokens(self) -> AsyncTokensResourceWithRawResponse:
+ return AsyncTokensResourceWithRawResponse(self._relays.tokens)
+
+
+class RelaysResourceWithStreamingResponse:
+ def __init__(self, relays: RelaysResource) -> None:
+ self._relays = relays
+
+ self.create = to_streamed_response_wrapper(
+ relays.create,
+ )
+ self.update = to_streamed_response_wrapper(
+ relays.update,
+ )
+ self.list = to_streamed_response_wrapper(
+ relays.list,
+ )
+ self.delete = to_streamed_response_wrapper(
+ relays.delete,
+ )
+ self.get = to_streamed_response_wrapper(
+ relays.get,
+ )
+
+ @cached_property
+ def tokens(self) -> TokensResourceWithStreamingResponse:
+ return TokensResourceWithStreamingResponse(self._relays.tokens)
+
+
+class AsyncRelaysResourceWithStreamingResponse:
+ def __init__(self, relays: AsyncRelaysResource) -> None:
+ self._relays = relays
+
+ self.create = async_to_streamed_response_wrapper(
+ relays.create,
+ )
+ self.update = async_to_streamed_response_wrapper(
+ relays.update,
+ )
+ self.list = async_to_streamed_response_wrapper(
+ relays.list,
+ )
+ self.delete = async_to_streamed_response_wrapper(
+ relays.delete,
+ )
+ self.get = async_to_streamed_response_wrapper(
+ relays.get,
+ )
+
+ @cached_property
+ def tokens(self) -> AsyncTokensResourceWithStreamingResponse:
+ return AsyncTokensResourceWithStreamingResponse(self._relays.tokens)
diff --git a/src/cloudflare/resources/moq/relays/tokens.py b/src/cloudflare/resources/moq/relays/tokens.py
new file mode 100644
index 00000000000..c09937159b1
--- /dev/null
+++ b/src/cloudflare/resources/moq/relays/tokens.py
@@ -0,0 +1,203 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Type, Optional, cast
+from typing_extensions import Literal
+
+import httpx
+
+from ...._types import Body, Query, Headers, NotGiven, not_given
+from ...._utils import path_template, maybe_transform, async_maybe_transform
+from ...._compat import cached_property
+from ...._resource import SyncAPIResource, AsyncAPIResource
+from ...._response import (
+ to_raw_response_wrapper,
+ to_streamed_response_wrapper,
+ async_to_raw_response_wrapper,
+ async_to_streamed_response_wrapper,
+)
+from ...._wrappers import ResultWrapper
+from ...._base_client import make_request_options
+from ....types.moq.relays import token_rotate_params
+from ....types.moq.relays.token_rotate_response import TokenRotateResponse
+
+__all__ = ["TokensResource", "AsyncTokensResource"]
+
+
+class TokensResource(SyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> TokensResourceWithRawResponse:
+ """
+ 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/cloudflare/cloudflare-python#accessing-raw-response-data-eg-headers
+ """
+ return TokensResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> TokensResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/cloudflare/cloudflare-python#with_streaming_response
+ """
+ return TokensResourceWithStreamingResponse(self)
+
+ def rotate(
+ self,
+ relay_id: str,
+ *,
+ account_id: str,
+ type: Literal["publish_subscribe", "subscribe"],
+ # 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,
+ ) -> Optional[TokenRotateResponse]:
+ """Generates a new token for the specified type.
+
+ The old token is immediately
+ invalidated. Token value is shown once in the response.
+
+ Args:
+ account_id: Cloudflare account identifier.
+
+ type: Which token type to rotate.
+
+ 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 account_id:
+ raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}")
+ if not relay_id:
+ raise ValueError(f"Expected a non-empty value for `relay_id` but received {relay_id!r}")
+ return self._post(
+ path_template(
+ "/accounts/{account_id}/moq/relays/{relay_id}/tokens/rotate", account_id=account_id, relay_id=relay_id
+ ),
+ body=maybe_transform({"type": type}, token_rotate_params.TokenRotateParams),
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ post_parser=ResultWrapper[Optional[TokenRotateResponse]]._unwrapper,
+ ),
+ cast_to=cast(Type[Optional[TokenRotateResponse]], ResultWrapper[TokenRotateResponse]),
+ )
+
+
+class AsyncTokensResource(AsyncAPIResource):
+ @cached_property
+ def with_raw_response(self) -> AsyncTokensResourceWithRawResponse:
+ """
+ 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/cloudflare/cloudflare-python#accessing-raw-response-data-eg-headers
+ """
+ return AsyncTokensResourceWithRawResponse(self)
+
+ @cached_property
+ def with_streaming_response(self) -> AsyncTokensResourceWithStreamingResponse:
+ """
+ An alternative to `.with_raw_response` that doesn't eagerly read the response body.
+
+ For more information, see https://www.github.com/cloudflare/cloudflare-python#with_streaming_response
+ """
+ return AsyncTokensResourceWithStreamingResponse(self)
+
+ async def rotate(
+ self,
+ relay_id: str,
+ *,
+ account_id: str,
+ type: Literal["publish_subscribe", "subscribe"],
+ # 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,
+ ) -> Optional[TokenRotateResponse]:
+ """Generates a new token for the specified type.
+
+ The old token is immediately
+ invalidated. Token value is shown once in the response.
+
+ Args:
+ account_id: Cloudflare account identifier.
+
+ type: Which token type to rotate.
+
+ 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 account_id:
+ raise ValueError(f"Expected a non-empty value for `account_id` but received {account_id!r}")
+ if not relay_id:
+ raise ValueError(f"Expected a non-empty value for `relay_id` but received {relay_id!r}")
+ return await self._post(
+ path_template(
+ "/accounts/{account_id}/moq/relays/{relay_id}/tokens/rotate", account_id=account_id, relay_id=relay_id
+ ),
+ body=await async_maybe_transform({"type": type}, token_rotate_params.TokenRotateParams),
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ post_parser=ResultWrapper[Optional[TokenRotateResponse]]._unwrapper,
+ ),
+ cast_to=cast(Type[Optional[TokenRotateResponse]], ResultWrapper[TokenRotateResponse]),
+ )
+
+
+class TokensResourceWithRawResponse:
+ def __init__(self, tokens: TokensResource) -> None:
+ self._tokens = tokens
+
+ self.rotate = to_raw_response_wrapper(
+ tokens.rotate,
+ )
+
+
+class AsyncTokensResourceWithRawResponse:
+ def __init__(self, tokens: AsyncTokensResource) -> None:
+ self._tokens = tokens
+
+ self.rotate = async_to_raw_response_wrapper(
+ tokens.rotate,
+ )
+
+
+class TokensResourceWithStreamingResponse:
+ def __init__(self, tokens: TokensResource) -> None:
+ self._tokens = tokens
+
+ self.rotate = to_streamed_response_wrapper(
+ tokens.rotate,
+ )
+
+
+class AsyncTokensResourceWithStreamingResponse:
+ def __init__(self, tokens: AsyncTokensResource) -> None:
+ self._tokens = tokens
+
+ self.rotate = async_to_streamed_response_wrapper(
+ tokens.rotate,
+ )
diff --git a/src/cloudflare/types/email_routing/__init__.py b/src/cloudflare/types/email_routing/__init__.py
index 553bab1e508..9eaa27e5189 100644
--- a/src/cloudflare/types/email_routing/__init__.py
+++ b/src/cloudflare/types/email_routing/__init__.py
@@ -12,7 +12,6 @@
from .dns_get_params import DNSGetParams as DNSGetParams
from .dns_edit_params import DNSEditParams as DNSEditParams
from .dns_get_response import DNSGetResponse as DNSGetResponse
-from .rule_list_params import RuleListParams as RuleListParams
from .dns_create_params import DNSCreateParams as DNSCreateParams
from .email_routing_rule import EmailRoutingRule as EmailRoutingRule
from .rule_create_params import RuleCreateParams as RuleCreateParams
diff --git a/src/cloudflare/types/email_routing/rule_list_params.py b/src/cloudflare/types/email_routing/rule_list_params.py
deleted file mode 100644
index bb27b3d4885..00000000000
--- a/src/cloudflare/types/email_routing/rule_list_params.py
+++ /dev/null
@@ -1,21 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing_extensions import Literal, Required, TypedDict
-
-__all__ = ["RuleListParams"]
-
-
-class RuleListParams(TypedDict, total=False):
- zone_id: Required[str]
- """Identifier."""
-
- enabled: Literal[True, False]
- """Filter by enabled routing rules."""
-
- page: float
- """Page number of paginated results."""
-
- per_page: float
- """Maximum number of results per page."""
diff --git a/src/cloudflare/types/email_routing/settings.py b/src/cloudflare/types/email_routing/settings.py
index 9688cfbe2d1..900c3cfce4d 100644
--- a/src/cloudflare/types/email_routing/settings.py
+++ b/src/cloudflare/types/email_routing/settings.py
@@ -31,6 +31,12 @@ class Settings(BaseModel):
status: Optional[Literal["ready", "unconfigured", "misconfigured", "misconfigured/locked", "unlocked"]] = None
"""Show the state of your account, and the type or configuration error."""
+ support_subaddress: Optional[Literal[True, False]] = None
+ """
+ Whether subaddressing (plus-addressing) is honored when matching incoming mail
+ against routing rules.
+ """
+
tag: Optional[str] = None
"""Email Routing settings tag.
diff --git a/src/cloudflare/types/email_security/investigate/move_bulk_params.py b/src/cloudflare/types/email_security/investigate/move_bulk_params.py
index 35a0e5ac6d6..1942bb4ded6 100644
--- a/src/cloudflare/types/email_security/investigate/move_bulk_params.py
+++ b/src/cloudflare/types/email_security/investigate/move_bulk_params.py
@@ -17,6 +17,10 @@ class MoveBulkParams(TypedDict, total=False):
Literal["Inbox", "JunkEmail", "DeletedItems", "RecoverableItemsDeletions", "RecoverableItemsPurges"]
]
+ expected_disposition: Literal[
+ "MALICIOUS", "MALICIOUS-BEC", "SUSPICIOUS", "SPOOF", "SPAM", "BULK", "ENCRYPTED", "EXTERNAL", "UNKNOWN", "NONE"
+ ]
+
ids: SequenceNotStr[str]
"""List of message IDs to move"""
diff --git a/src/cloudflare/types/email_security/investigate/move_create_params.py b/src/cloudflare/types/email_security/investigate/move_create_params.py
index 0e389b2ae93..fc7c88c605d 100644
--- a/src/cloudflare/types/email_security/investigate/move_create_params.py
+++ b/src/cloudflare/types/email_security/investigate/move_create_params.py
@@ -14,3 +14,7 @@ class MoveCreateParams(TypedDict, total=False):
destination: Required[
Literal["Inbox", "JunkEmail", "DeletedItems", "RecoverableItemsDeletions", "RecoverableItemsPurges"]
]
+
+ expected_disposition: Literal[
+ "MALICIOUS", "MALICIOUS-BEC", "SUSPICIOUS", "SPOOF", "SPAM", "BULK", "ENCRYPTED", "EXTERNAL", "UNKNOWN", "NONE"
+ ]
diff --git a/src/cloudflare/types/moq/__init__.py b/src/cloudflare/types/moq/__init__.py
new file mode 100644
index 00000000000..6c12a15de24
--- /dev/null
+++ b/src/cloudflare/types/moq/__init__.py
@@ -0,0 +1,11 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from .relay_list_params import RelayListParams as RelayListParams
+from .relay_get_response import RelayGetResponse as RelayGetResponse
+from .relay_create_params import RelayCreateParams as RelayCreateParams
+from .relay_list_response import RelayListResponse as RelayListResponse
+from .relay_update_params import RelayUpdateParams as RelayUpdateParams
+from .relay_create_response import RelayCreateResponse as RelayCreateResponse
+from .relay_update_response import RelayUpdateResponse as RelayUpdateResponse
diff --git a/src/cloudflare/types/moq/relay_create_params.py b/src/cloudflare/types/moq/relay_create_params.py
new file mode 100644
index 00000000000..104c3d032c1
--- /dev/null
+++ b/src/cloudflare/types/moq/relay_create_params.py
@@ -0,0 +1,15 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Required, TypedDict
+
+__all__ = ["RelayCreateParams"]
+
+
+class RelayCreateParams(TypedDict, total=False):
+ account_id: Required[str]
+ """Cloudflare account identifier."""
+
+ name: Required[str]
+ """Human-readable name for the relay."""
diff --git a/src/cloudflare/types/moq/relay_create_response.py b/src/cloudflare/types/moq/relay_create_response.py
new file mode 100644
index 00000000000..1cf2516282e
--- /dev/null
+++ b/src/cloudflare/types/moq/relay_create_response.py
@@ -0,0 +1,69 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List, Optional
+from datetime import datetime
+
+from ..._models import BaseModel
+
+__all__ = [
+ "RelayCreateResponse",
+ "Config",
+ "ConfigLingeringSubscribe",
+ "ConfigOriginFallback",
+ "ConfigOriginFallbackOrigin",
+]
+
+
+class ConfigLingeringSubscribe(BaseModel):
+ enabled: Optional[bool] = None
+
+ max_timeout_ms: Optional[int] = None
+ """Relay-level ceiling on lingering subscribe timeout (ms). Default 30000."""
+
+
+class ConfigOriginFallbackOrigin(BaseModel):
+ """A single upstream origin relay."""
+
+ url: Optional[str] = None
+ """Upstream origin relay URL."""
+
+
+class ConfigOriginFallback(BaseModel):
+ enabled: Optional[bool] = None
+
+ origins: Optional[List[ConfigOriginFallbackOrigin]] = None
+ """Ordered list of upstream origin relays.
+
+ Each entry is an object (not a bare string) so per-origin configuration can be
+ added in the future without another breaking change.
+ """
+
+
+class Config(BaseModel):
+ """origin_fallback and lingering_subscribe are mutually exclusive."""
+
+ lingering_subscribe: Optional[ConfigLingeringSubscribe] = None
+
+ origin_fallback: Optional[ConfigOriginFallback] = None
+
+
+class RelayCreateResponse(BaseModel):
+ """Relay with auto-generated tokens (shown once)."""
+
+ config: Config
+ """origin_fallback and lingering_subscribe are mutually exclusive."""
+
+ created: datetime
+
+ modified: datetime
+
+ name: str
+
+ token_publish_subscribe: str
+ """Full access token (publish + subscribe). Treat as sensitive."""
+
+ token_subscribe: str
+ """Subscribe-only token. Treat as sensitive."""
+
+ uid: str
+ """Server-generated unique identifier (32 hex chars)."""
diff --git a/src/cloudflare/types/moq/relay_get_response.py b/src/cloudflare/types/moq/relay_get_response.py
new file mode 100644
index 00000000000..b8d008ebd7e
--- /dev/null
+++ b/src/cloudflare/types/moq/relay_get_response.py
@@ -0,0 +1,66 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List, Optional
+from datetime import datetime
+from typing_extensions import Literal
+
+from ..._models import BaseModel
+
+__all__ = [
+ "RelayGetResponse",
+ "Config",
+ "ConfigLingeringSubscribe",
+ "ConfigOriginFallback",
+ "ConfigOriginFallbackOrigin",
+]
+
+
+class ConfigLingeringSubscribe(BaseModel):
+ enabled: Optional[bool] = None
+
+ max_timeout_ms: Optional[int] = None
+ """Relay-level ceiling on lingering subscribe timeout (ms). Default 30000."""
+
+
+class ConfigOriginFallbackOrigin(BaseModel):
+ """A single upstream origin relay."""
+
+ url: Optional[str] = None
+ """Upstream origin relay URL."""
+
+
+class ConfigOriginFallback(BaseModel):
+ enabled: Optional[bool] = None
+
+ origins: Optional[List[ConfigOriginFallbackOrigin]] = None
+ """Ordered list of upstream origin relays.
+
+ Each entry is an object (not a bare string) so per-origin configuration can be
+ added in the future without another breaking change.
+ """
+
+
+class Config(BaseModel):
+ """origin_fallback and lingering_subscribe are mutually exclusive."""
+
+ lingering_subscribe: Optional[ConfigLingeringSubscribe] = None
+
+ origin_fallback: Optional[ConfigOriginFallback] = None
+
+
+class RelayGetResponse(BaseModel):
+ """Full relay details (no tokens)."""
+
+ config: Config
+ """origin_fallback and lingering_subscribe are mutually exclusive."""
+
+ created: datetime
+
+ modified: datetime
+
+ name: str
+
+ uid: str
+
+ status: Optional[Literal["connected"]] = None
+ """\"connected" when active, omitted otherwise."""
diff --git a/src/cloudflare/types/moq/relay_list_params.py b/src/cloudflare/types/moq/relay_list_params.py
new file mode 100644
index 00000000000..6abd6a25248
--- /dev/null
+++ b/src/cloudflare/types/moq/relay_list_params.py
@@ -0,0 +1,41 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Union
+from datetime import datetime
+from typing_extensions import Required, Annotated, TypedDict
+
+from ..._utils import PropertyInfo
+
+__all__ = ["RelayListParams"]
+
+
+class RelayListParams(TypedDict, total=False):
+ account_id: Required[str]
+ """Cloudflare account identifier."""
+
+ asc: bool
+ """Sort order by `created`.
+
+ When true, results are returned oldest-first (ascending); otherwise newest-first
+ (descending, the default).
+ """
+
+ created_after: Annotated[Union[str, datetime], PropertyInfo(format="iso8601")]
+ """Cursor for pagination.
+
+ Returns relays created strictly after this RFC 3339 timestamp (typically the
+ `created` value of the last item on the current page, to fetch the next page).
+ """
+
+ created_before: Annotated[Union[str, datetime], PropertyInfo(format="iso8601")]
+ """Cursor for pagination.
+
+ Returns relays created strictly before this RFC 3339 timestamp (typically the
+ `created` value of the first item on the current page, to fetch the previous
+ page).
+ """
+
+ per_page: int
+ """Maximum number of relays to return per page."""
diff --git a/src/cloudflare/types/moq/relay_list_response.py b/src/cloudflare/types/moq/relay_list_response.py
new file mode 100644
index 00000000000..00576f6b42a
--- /dev/null
+++ b/src/cloudflare/types/moq/relay_list_response.py
@@ -0,0 +1,19 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from datetime import datetime
+
+from ..._models import BaseModel
+
+__all__ = ["RelayListResponse"]
+
+
+class RelayListResponse(BaseModel):
+ """Abbreviated relay for list responses."""
+
+ created: datetime
+
+ modified: datetime
+
+ name: str
+
+ uid: str
diff --git a/src/cloudflare/types/moq/relay_update_params.py b/src/cloudflare/types/moq/relay_update_params.py
new file mode 100644
index 00000000000..1a00e6e8cf2
--- /dev/null
+++ b/src/cloudflare/types/moq/relay_update_params.py
@@ -0,0 +1,57 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Iterable
+from typing_extensions import Required, TypedDict
+
+__all__ = [
+ "RelayUpdateParams",
+ "Config",
+ "ConfigLingeringSubscribe",
+ "ConfigOriginFallback",
+ "ConfigOriginFallbackOrigin",
+]
+
+
+class RelayUpdateParams(TypedDict, total=False):
+ account_id: Required[str]
+ """Cloudflare account identifier."""
+
+ config: Config
+ """origin_fallback and lingering_subscribe are mutually exclusive."""
+
+ name: str
+
+
+class ConfigLingeringSubscribe(TypedDict, total=False):
+ enabled: bool
+
+ max_timeout_ms: int
+ """Relay-level ceiling on lingering subscribe timeout (ms). Default 30000."""
+
+
+class ConfigOriginFallbackOrigin(TypedDict, total=False):
+ """A single upstream origin relay."""
+
+ url: str
+ """Upstream origin relay URL."""
+
+
+class ConfigOriginFallback(TypedDict, total=False):
+ enabled: bool
+
+ origins: Iterable[ConfigOriginFallbackOrigin]
+ """Ordered list of upstream origin relays.
+
+ Each entry is an object (not a bare string) so per-origin configuration can be
+ added in the future without another breaking change.
+ """
+
+
+class Config(TypedDict, total=False):
+ """origin_fallback and lingering_subscribe are mutually exclusive."""
+
+ lingering_subscribe: ConfigLingeringSubscribe
+
+ origin_fallback: ConfigOriginFallback
diff --git a/src/cloudflare/types/moq/relay_update_response.py b/src/cloudflare/types/moq/relay_update_response.py
new file mode 100644
index 00000000000..10e35818945
--- /dev/null
+++ b/src/cloudflare/types/moq/relay_update_response.py
@@ -0,0 +1,66 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List, Optional
+from datetime import datetime
+from typing_extensions import Literal
+
+from ..._models import BaseModel
+
+__all__ = [
+ "RelayUpdateResponse",
+ "Config",
+ "ConfigLingeringSubscribe",
+ "ConfigOriginFallback",
+ "ConfigOriginFallbackOrigin",
+]
+
+
+class ConfigLingeringSubscribe(BaseModel):
+ enabled: Optional[bool] = None
+
+ max_timeout_ms: Optional[int] = None
+ """Relay-level ceiling on lingering subscribe timeout (ms). Default 30000."""
+
+
+class ConfigOriginFallbackOrigin(BaseModel):
+ """A single upstream origin relay."""
+
+ url: Optional[str] = None
+ """Upstream origin relay URL."""
+
+
+class ConfigOriginFallback(BaseModel):
+ enabled: Optional[bool] = None
+
+ origins: Optional[List[ConfigOriginFallbackOrigin]] = None
+ """Ordered list of upstream origin relays.
+
+ Each entry is an object (not a bare string) so per-origin configuration can be
+ added in the future without another breaking change.
+ """
+
+
+class Config(BaseModel):
+ """origin_fallback and lingering_subscribe are mutually exclusive."""
+
+ lingering_subscribe: Optional[ConfigLingeringSubscribe] = None
+
+ origin_fallback: Optional[ConfigOriginFallback] = None
+
+
+class RelayUpdateResponse(BaseModel):
+ """Full relay details (no tokens)."""
+
+ config: Config
+ """origin_fallback and lingering_subscribe are mutually exclusive."""
+
+ created: datetime
+
+ modified: datetime
+
+ name: str
+
+ uid: str
+
+ status: Optional[Literal["connected"]] = None
+ """\"connected" when active, omitted otherwise."""
diff --git a/src/cloudflare/types/moq/relays/__init__.py b/src/cloudflare/types/moq/relays/__init__.py
new file mode 100644
index 00000000000..e1548b499d4
--- /dev/null
+++ b/src/cloudflare/types/moq/relays/__init__.py
@@ -0,0 +1,6 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from .token_rotate_params import TokenRotateParams as TokenRotateParams
+from .token_rotate_response import TokenRotateResponse as TokenRotateResponse
diff --git a/src/cloudflare/types/moq/relays/token_rotate_params.py b/src/cloudflare/types/moq/relays/token_rotate_params.py
new file mode 100644
index 00000000000..07611c3cffc
--- /dev/null
+++ b/src/cloudflare/types/moq/relays/token_rotate_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 Literal, Required, TypedDict
+
+__all__ = ["TokenRotateParams"]
+
+
+class TokenRotateParams(TypedDict, total=False):
+ account_id: Required[str]
+ """Cloudflare account identifier."""
+
+ type: Required[Literal["publish_subscribe", "subscribe"]]
+ """Which token type to rotate."""
diff --git a/src/cloudflare/types/moq/relays/token_rotate_response.py b/src/cloudflare/types/moq/relays/token_rotate_response.py
new file mode 100644
index 00000000000..5f71a3081dc
--- /dev/null
+++ b/src/cloudflare/types/moq/relays/token_rotate_response.py
@@ -0,0 +1,14 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing_extensions import Literal
+
+from ...._models import BaseModel
+
+__all__ = ["TokenRotateResponse"]
+
+
+class TokenRotateResponse(BaseModel):
+ token: str
+ """New token value (shown once). Treat as sensitive."""
+
+ type: Literal["publish_subscribe", "subscribe"]
diff --git a/src/cloudflare/types/rulesets/rule_create_params.py b/src/cloudflare/types/rulesets/rule_create_params.py
index 6a8c82757e1..9c5b7d9ea6b 100644
--- a/src/cloudflare/types/rulesets/rule_create_params.py
+++ b/src/cloudflare/types/rulesets/rule_create_params.py
@@ -220,6 +220,9 @@
"SetCacheSettingsRuleActionParametersEdgeTTLStatusCodeTTLStatusCodeRange",
"SetCacheSettingsRuleActionParametersServeStale",
"SetCacheSettingsRuleActionParametersSharedDictionary",
+ "SetCacheSettingsRuleActionParametersVary",
+ "SetCacheSettingsRuleActionParametersVaryDefault",
+ "SetCacheSettingsRuleActionParametersVaryHeaders",
"SetCacheSettingsRuleExposedCredentialCheck",
"SetCacheSettingsRulePosition",
"SetCacheSettingsRulePositionBeforePosition",
@@ -3425,6 +3428,64 @@ class SetCacheSettingsRuleActionParametersSharedDictionary(TypedDict, total=Fals
"""
+class SetCacheSettingsRuleActionParametersVaryDefault(TypedDict, total=False):
+ """
+ Controls how a single request header (or the default for all headers) contributes to the cache key.
+ """
+
+ action: Required[Literal["bypass", "passthrough", "normalize"]]
+ """How the header value is treated when building the cache key."""
+
+ languages: SequenceNotStr[str]
+ """The set of languages to normalize against.
+
+ Only valid for the `accept-language` header.
+ """
+
+ media_types: SequenceNotStr[str]
+ """The set of media types to normalize against.
+
+ Only valid for the `accept` header.
+ """
+
+
+class SetCacheSettingsRuleActionParametersVaryHeaders(TypedDict, total=False):
+ """
+ Controls how a single request header (or the default for all headers) contributes to the cache key.
+ """
+
+ action: Required[Literal["bypass", "passthrough", "normalize"]]
+ """How the header value is treated when building the cache key."""
+
+ languages: SequenceNotStr[str]
+ """The set of languages to normalize against.
+
+ Only valid for the `accept-language` header.
+ """
+
+ media_types: SequenceNotStr[str]
+ """The set of media types to normalize against.
+
+ Only valid for the `accept` header.
+ """
+
+
+class SetCacheSettingsRuleActionParametersVary(TypedDict, total=False):
+ """Controls how cached responses vary based on request headers.
+
+ At least one of `default` or `headers` must be set, and `default` is required when `headers` is set.
+ """
+
+ default: SetCacheSettingsRuleActionParametersVaryDefault
+ """
+ Controls how a single request header (or the default for all headers)
+ contributes to the cache key.
+ """
+
+ headers: Dict[str, SetCacheSettingsRuleActionParametersVaryHeaders]
+ """A mapping of lowercase request header names to their vary configuration."""
+
+
class SetCacheSettingsRuleActionParameters(TypedDict, total=False):
"""The parameters configuring the rule's action."""
@@ -3500,6 +3561,13 @@ class SetCacheSettingsRuleActionParameters(TypedDict, total=False):
strip_set_cookie: bool
"""Whether to strip Set-Cookie headers from the origin response before caching."""
+ vary: SetCacheSettingsRuleActionParametersVary
+ """Controls how cached responses vary based on request headers.
+
+ At least one of `default` or `headers` must be set, and `default` is required
+ when `headers` is set.
+ """
+
class SetCacheSettingsRuleExposedCredentialCheck(TypedDict, total=False):
"""Configuration for exposed credential checking."""
diff --git a/src/cloudflare/types/rulesets/rule_edit_params.py b/src/cloudflare/types/rulesets/rule_edit_params.py
index c914421bbdf..272ed9c3a2f 100644
--- a/src/cloudflare/types/rulesets/rule_edit_params.py
+++ b/src/cloudflare/types/rulesets/rule_edit_params.py
@@ -220,6 +220,9 @@
"SetCacheSettingsRuleActionParametersEdgeTTLStatusCodeTTLStatusCodeRange",
"SetCacheSettingsRuleActionParametersServeStale",
"SetCacheSettingsRuleActionParametersSharedDictionary",
+ "SetCacheSettingsRuleActionParametersVary",
+ "SetCacheSettingsRuleActionParametersVaryDefault",
+ "SetCacheSettingsRuleActionParametersVaryHeaders",
"SetCacheSettingsRuleExposedCredentialCheck",
"SetCacheSettingsRulePosition",
"SetCacheSettingsRulePositionBeforePosition",
@@ -3476,6 +3479,64 @@ class SetCacheSettingsRuleActionParametersSharedDictionary(TypedDict, total=Fals
"""
+class SetCacheSettingsRuleActionParametersVaryDefault(TypedDict, total=False):
+ """
+ Controls how a single request header (or the default for all headers) contributes to the cache key.
+ """
+
+ action: Required[Literal["bypass", "passthrough", "normalize"]]
+ """How the header value is treated when building the cache key."""
+
+ languages: SequenceNotStr[str]
+ """The set of languages to normalize against.
+
+ Only valid for the `accept-language` header.
+ """
+
+ media_types: SequenceNotStr[str]
+ """The set of media types to normalize against.
+
+ Only valid for the `accept` header.
+ """
+
+
+class SetCacheSettingsRuleActionParametersVaryHeaders(TypedDict, total=False):
+ """
+ Controls how a single request header (or the default for all headers) contributes to the cache key.
+ """
+
+ action: Required[Literal["bypass", "passthrough", "normalize"]]
+ """How the header value is treated when building the cache key."""
+
+ languages: SequenceNotStr[str]
+ """The set of languages to normalize against.
+
+ Only valid for the `accept-language` header.
+ """
+
+ media_types: SequenceNotStr[str]
+ """The set of media types to normalize against.
+
+ Only valid for the `accept` header.
+ """
+
+
+class SetCacheSettingsRuleActionParametersVary(TypedDict, total=False):
+ """Controls how cached responses vary based on request headers.
+
+ At least one of `default` or `headers` must be set, and `default` is required when `headers` is set.
+ """
+
+ default: SetCacheSettingsRuleActionParametersVaryDefault
+ """
+ Controls how a single request header (or the default for all headers)
+ contributes to the cache key.
+ """
+
+ headers: Dict[str, SetCacheSettingsRuleActionParametersVaryHeaders]
+ """A mapping of lowercase request header names to their vary configuration."""
+
+
class SetCacheSettingsRuleActionParameters(TypedDict, total=False):
"""The parameters configuring the rule's action."""
@@ -3551,6 +3612,13 @@ class SetCacheSettingsRuleActionParameters(TypedDict, total=False):
strip_set_cookie: bool
"""Whether to strip Set-Cookie headers from the origin response before caching."""
+ vary: SetCacheSettingsRuleActionParametersVary
+ """Controls how cached responses vary based on request headers.
+
+ At least one of `default` or `headers` must be set, and `default` is required
+ when `headers` is set.
+ """
+
class SetCacheSettingsRuleExposedCredentialCheck(TypedDict, total=False):
"""Configuration for exposed credential checking."""
diff --git a/src/cloudflare/types/rulesets/set_cache_settings_rule.py b/src/cloudflare/types/rulesets/set_cache_settings_rule.py
index 8b1f40e5af7..c5c8c06032f 100644
--- a/src/cloudflare/types/rulesets/set_cache_settings_rule.py
+++ b/src/cloudflare/types/rulesets/set_cache_settings_rule.py
@@ -28,6 +28,9 @@
"ActionParametersEdgeTTLStatusCodeTTLStatusCodeRange",
"ActionParametersServeStale",
"ActionParametersSharedDictionary",
+ "ActionParametersVary",
+ "ActionParametersVaryDefault",
+ "ActionParametersVaryHeaders",
"ExposedCredentialCheck",
"Ratelimit",
]
@@ -253,6 +256,64 @@ class ActionParametersSharedDictionary(BaseModel):
"""
+class ActionParametersVaryDefault(BaseModel):
+ """
+ Controls how a single request header (or the default for all headers) contributes to the cache key.
+ """
+
+ action: Literal["bypass", "passthrough", "normalize"]
+ """How the header value is treated when building the cache key."""
+
+ languages: Optional[List[str]] = None
+ """The set of languages to normalize against.
+
+ Only valid for the `accept-language` header.
+ """
+
+ media_types: Optional[List[str]] = None
+ """The set of media types to normalize against.
+
+ Only valid for the `accept` header.
+ """
+
+
+class ActionParametersVaryHeaders(BaseModel):
+ """
+ Controls how a single request header (or the default for all headers) contributes to the cache key.
+ """
+
+ action: Literal["bypass", "passthrough", "normalize"]
+ """How the header value is treated when building the cache key."""
+
+ languages: Optional[List[str]] = None
+ """The set of languages to normalize against.
+
+ Only valid for the `accept-language` header.
+ """
+
+ media_types: Optional[List[str]] = None
+ """The set of media types to normalize against.
+
+ Only valid for the `accept` header.
+ """
+
+
+class ActionParametersVary(BaseModel):
+ """Controls how cached responses vary based on request headers.
+
+ At least one of `default` or `headers` must be set, and `default` is required when `headers` is set.
+ """
+
+ default: Optional[ActionParametersVaryDefault] = None
+ """
+ Controls how a single request header (or the default for all headers)
+ contributes to the cache key.
+ """
+
+ headers: Optional[Dict[str, ActionParametersVaryHeaders]] = None
+ """A mapping of lowercase request header names to their vary configuration."""
+
+
class ActionParameters(BaseModel):
"""The parameters configuring the rule's action."""
@@ -328,6 +389,13 @@ class ActionParameters(BaseModel):
strip_set_cookie: Optional[bool] = None
"""Whether to strip Set-Cookie headers from the origin response before caching."""
+ vary: Optional[ActionParametersVary] = None
+ """Controls how cached responses vary based on request headers.
+
+ At least one of `default` or `headers` must be set, and `default` is required
+ when `headers` is set.
+ """
+
class ExposedCredentialCheck(BaseModel):
"""Configuration for exposed credential checking."""
diff --git a/src/cloudflare/types/rulesets/set_cache_settings_rule_param.py b/src/cloudflare/types/rulesets/set_cache_settings_rule_param.py
index b223d45297d..3ed01b1a11e 100644
--- a/src/cloudflare/types/rulesets/set_cache_settings_rule_param.py
+++ b/src/cloudflare/types/rulesets/set_cache_settings_rule_param.py
@@ -27,6 +27,9 @@
"ActionParametersEdgeTTLStatusCodeTTLStatusCodeRange",
"ActionParametersServeStale",
"ActionParametersSharedDictionary",
+ "ActionParametersVary",
+ "ActionParametersVaryDefault",
+ "ActionParametersVaryHeaders",
"ExposedCredentialCheck",
"Ratelimit",
]
@@ -260,6 +263,64 @@ class ActionParametersSharedDictionary(TypedDict, total=False):
"""
+class ActionParametersVaryDefault(TypedDict, total=False):
+ """
+ Controls how a single request header (or the default for all headers) contributes to the cache key.
+ """
+
+ action: Required[Literal["bypass", "passthrough", "normalize"]]
+ """How the header value is treated when building the cache key."""
+
+ languages: SequenceNotStr[str]
+ """The set of languages to normalize against.
+
+ Only valid for the `accept-language` header.
+ """
+
+ media_types: SequenceNotStr[str]
+ """The set of media types to normalize against.
+
+ Only valid for the `accept` header.
+ """
+
+
+class ActionParametersVaryHeaders(TypedDict, total=False):
+ """
+ Controls how a single request header (or the default for all headers) contributes to the cache key.
+ """
+
+ action: Required[Literal["bypass", "passthrough", "normalize"]]
+ """How the header value is treated when building the cache key."""
+
+ languages: SequenceNotStr[str]
+ """The set of languages to normalize against.
+
+ Only valid for the `accept-language` header.
+ """
+
+ media_types: SequenceNotStr[str]
+ """The set of media types to normalize against.
+
+ Only valid for the `accept` header.
+ """
+
+
+class ActionParametersVary(TypedDict, total=False):
+ """Controls how cached responses vary based on request headers.
+
+ At least one of `default` or `headers` must be set, and `default` is required when `headers` is set.
+ """
+
+ default: ActionParametersVaryDefault
+ """
+ Controls how a single request header (or the default for all headers)
+ contributes to the cache key.
+ """
+
+ headers: Dict[str, ActionParametersVaryHeaders]
+ """A mapping of lowercase request header names to their vary configuration."""
+
+
class ActionParameters(TypedDict, total=False):
"""The parameters configuring the rule's action."""
@@ -335,6 +396,13 @@ class ActionParameters(TypedDict, total=False):
strip_set_cookie: bool
"""Whether to strip Set-Cookie headers from the origin response before caching."""
+ vary: ActionParametersVary
+ """Controls how cached responses vary based on request headers.
+
+ At least one of `default` or `headers` must be set, and `default` is required
+ when `headers` is set.
+ """
+
class ExposedCredentialCheck(TypedDict, total=False):
"""Configuration for exposed credential checking."""
diff --git a/tests/api_resources/email_routing/test_rules.py b/tests/api_resources/email_routing/test_rules.py
index 33b96b74828..03090d5bfc2 100644
--- a/tests/api_resources/email_routing/test_rules.py
+++ b/tests/api_resources/email_routing/test_rules.py
@@ -9,7 +9,6 @@
from cloudflare import Cloudflare, AsyncCloudflare
from tests.utils import assert_matches_type
-from cloudflare.pagination import SyncV4PagePaginationArray, AsyncV4PagePaginationArray
from cloudflare.types.email_routing import EmailRoutingRule
base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
@@ -169,54 +168,6 @@ def test_path_params_update(self, client: Cloudflare) -> None:
matchers=[{"type": "literal"}],
)
- @parametrize
- def test_method_list(self, client: Cloudflare) -> None:
- rule = client.email_routing.rules.list(
- zone_id="023e105f4ecef8ad9ca31a8372d0c353",
- )
- assert_matches_type(SyncV4PagePaginationArray[EmailRoutingRule], rule, path=["response"])
-
- @parametrize
- def test_method_list_with_all_params(self, client: Cloudflare) -> None:
- rule = client.email_routing.rules.list(
- zone_id="023e105f4ecef8ad9ca31a8372d0c353",
- enabled=True,
- page=1,
- per_page=5,
- )
- assert_matches_type(SyncV4PagePaginationArray[EmailRoutingRule], rule, path=["response"])
-
- @parametrize
- def test_raw_response_list(self, client: Cloudflare) -> None:
- response = client.email_routing.rules.with_raw_response.list(
- zone_id="023e105f4ecef8ad9ca31a8372d0c353",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- rule = response.parse()
- assert_matches_type(SyncV4PagePaginationArray[EmailRoutingRule], rule, path=["response"])
-
- @parametrize
- def test_streaming_response_list(self, client: Cloudflare) -> None:
- with client.email_routing.rules.with_streaming_response.list(
- zone_id="023e105f4ecef8ad9ca31a8372d0c353",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- rule = response.parse()
- assert_matches_type(SyncV4PagePaginationArray[EmailRoutingRule], rule, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @parametrize
- def test_path_params_list(self, client: Cloudflare) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `zone_id` but received ''"):
- client.email_routing.rules.with_raw_response.list(
- zone_id="",
- )
-
@parametrize
def test_method_delete(self, client: Cloudflare) -> None:
rule = client.email_routing.rules.delete(
@@ -470,54 +421,6 @@ async def test_path_params_update(self, async_client: AsyncCloudflare) -> None:
matchers=[{"type": "literal"}],
)
- @parametrize
- async def test_method_list(self, async_client: AsyncCloudflare) -> None:
- rule = await async_client.email_routing.rules.list(
- zone_id="023e105f4ecef8ad9ca31a8372d0c353",
- )
- assert_matches_type(AsyncV4PagePaginationArray[EmailRoutingRule], rule, path=["response"])
-
- @parametrize
- async def test_method_list_with_all_params(self, async_client: AsyncCloudflare) -> None:
- rule = await async_client.email_routing.rules.list(
- zone_id="023e105f4ecef8ad9ca31a8372d0c353",
- enabled=True,
- page=1,
- per_page=5,
- )
- assert_matches_type(AsyncV4PagePaginationArray[EmailRoutingRule], rule, path=["response"])
-
- @parametrize
- async def test_raw_response_list(self, async_client: AsyncCloudflare) -> None:
- response = await async_client.email_routing.rules.with_raw_response.list(
- zone_id="023e105f4ecef8ad9ca31a8372d0c353",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- rule = await response.parse()
- assert_matches_type(AsyncV4PagePaginationArray[EmailRoutingRule], rule, path=["response"])
-
- @parametrize
- async def test_streaming_response_list(self, async_client: AsyncCloudflare) -> None:
- async with async_client.email_routing.rules.with_streaming_response.list(
- zone_id="023e105f4ecef8ad9ca31a8372d0c353",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- rule = await response.parse()
- assert_matches_type(AsyncV4PagePaginationArray[EmailRoutingRule], rule, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @parametrize
- async def test_path_params_list(self, async_client: AsyncCloudflare) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `zone_id` but received ''"):
- await async_client.email_routing.rules.with_raw_response.list(
- zone_id="",
- )
-
@parametrize
async def test_method_delete(self, async_client: AsyncCloudflare) -> None:
rule = await async_client.email_routing.rules.delete(
diff --git a/tests/api_resources/email_security/investigate/test_move.py b/tests/api_resources/email_security/investigate/test_move.py
index cf738cea491..19eadebcef0 100644
--- a/tests/api_resources/email_security/investigate/test_move.py
+++ b/tests/api_resources/email_security/investigate/test_move.py
@@ -30,6 +30,16 @@ def test_method_create(self, client: Cloudflare) -> None:
)
assert_matches_type(SyncSinglePage[MoveCreateResponse], move, path=["response"])
+ @parametrize
+ def test_method_create_with_all_params(self, client: Cloudflare) -> None:
+ move = client.email_security.investigate.move.create(
+ investigate_id="4Njp3P0STMz2c02Q-2024-01-05T10:00:00-12345678",
+ account_id="023e105f4ecef8ad9ca31a8372d0c353",
+ destination="Inbox",
+ expected_disposition="MALICIOUS",
+ )
+ assert_matches_type(SyncSinglePage[MoveCreateResponse], move, path=["response"])
+
@parametrize
def test_raw_response_create(self, client: Cloudflare) -> None:
response = client.email_security.investigate.move.with_raw_response.create(
@@ -87,6 +97,7 @@ def test_method_bulk_with_all_params(self, client: Cloudflare) -> None:
move = client.email_security.investigate.move.bulk(
account_id="023e105f4ecef8ad9ca31a8372d0c353",
destination="Inbox",
+ expected_disposition="MALICIOUS",
ids=["4Njp3P0STMz2c02Q-2024-01-05T10:00:00-12345678"],
postfix_ids=["4Njp3P0STMz2c02Q"],
)
@@ -141,6 +152,16 @@ async def test_method_create(self, async_client: AsyncCloudflare) -> None:
)
assert_matches_type(AsyncSinglePage[MoveCreateResponse], move, path=["response"])
+ @parametrize
+ async def test_method_create_with_all_params(self, async_client: AsyncCloudflare) -> None:
+ move = await async_client.email_security.investigate.move.create(
+ investigate_id="4Njp3P0STMz2c02Q-2024-01-05T10:00:00-12345678",
+ account_id="023e105f4ecef8ad9ca31a8372d0c353",
+ destination="Inbox",
+ expected_disposition="MALICIOUS",
+ )
+ assert_matches_type(AsyncSinglePage[MoveCreateResponse], move, path=["response"])
+
@parametrize
async def test_raw_response_create(self, async_client: AsyncCloudflare) -> None:
response = await async_client.email_security.investigate.move.with_raw_response.create(
@@ -198,6 +219,7 @@ async def test_method_bulk_with_all_params(self, async_client: AsyncCloudflare)
move = await async_client.email_security.investigate.move.bulk(
account_id="023e105f4ecef8ad9ca31a8372d0c353",
destination="Inbox",
+ expected_disposition="MALICIOUS",
ids=["4Njp3P0STMz2c02Q-2024-01-05T10:00:00-12345678"],
postfix_ids=["4Njp3P0STMz2c02Q"],
)
diff --git a/tests/api_resources/moq/__init__.py b/tests/api_resources/moq/__init__.py
new file mode 100644
index 00000000000..fd8019a9a1a
--- /dev/null
+++ b/tests/api_resources/moq/__init__.py
@@ -0,0 +1 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
diff --git a/tests/api_resources/moq/relays/__init__.py b/tests/api_resources/moq/relays/__init__.py
new file mode 100644
index 00000000000..fd8019a9a1a
--- /dev/null
+++ b/tests/api_resources/moq/relays/__init__.py
@@ -0,0 +1 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
diff --git a/tests/api_resources/moq/relays/test_tokens.py b/tests/api_resources/moq/relays/test_tokens.py
new file mode 100644
index 00000000000..f39caa3990e
--- /dev/null
+++ b/tests/api_resources/moq/relays/test_tokens.py
@@ -0,0 +1,130 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+import os
+from typing import Any, Optional, cast
+
+import pytest
+
+from cloudflare import Cloudflare, AsyncCloudflare
+from tests.utils import assert_matches_type
+from cloudflare.types.moq.relays import TokenRotateResponse
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestTokens:
+ parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
+
+ @parametrize
+ def test_method_rotate(self, client: Cloudflare) -> None:
+ token = client.moq.relays.tokens.rotate(
+ relay_id="a1b2c3d4e5f67890a1b2c3d4e5f67890",
+ account_id="023e105f4ecef8ad9ca31a8372d0c353",
+ type="publish_subscribe",
+ )
+ assert_matches_type(Optional[TokenRotateResponse], token, path=["response"])
+
+ @parametrize
+ def test_raw_response_rotate(self, client: Cloudflare) -> None:
+ response = client.moq.relays.tokens.with_raw_response.rotate(
+ relay_id="a1b2c3d4e5f67890a1b2c3d4e5f67890",
+ account_id="023e105f4ecef8ad9ca31a8372d0c353",
+ type="publish_subscribe",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ token = response.parse()
+ assert_matches_type(Optional[TokenRotateResponse], token, path=["response"])
+
+ @parametrize
+ def test_streaming_response_rotate(self, client: Cloudflare) -> None:
+ with client.moq.relays.tokens.with_streaming_response.rotate(
+ relay_id="a1b2c3d4e5f67890a1b2c3d4e5f67890",
+ account_id="023e105f4ecef8ad9ca31a8372d0c353",
+ type="publish_subscribe",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ token = response.parse()
+ assert_matches_type(Optional[TokenRotateResponse], token, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_path_params_rotate(self, client: Cloudflare) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"):
+ client.moq.relays.tokens.with_raw_response.rotate(
+ relay_id="a1b2c3d4e5f67890a1b2c3d4e5f67890",
+ account_id="",
+ type="publish_subscribe",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `relay_id` but received ''"):
+ client.moq.relays.tokens.with_raw_response.rotate(
+ relay_id="",
+ account_id="023e105f4ecef8ad9ca31a8372d0c353",
+ type="publish_subscribe",
+ )
+
+
+class TestAsyncTokens:
+ parametrize = pytest.mark.parametrize(
+ "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
+ )
+
+ @parametrize
+ async def test_method_rotate(self, async_client: AsyncCloudflare) -> None:
+ token = await async_client.moq.relays.tokens.rotate(
+ relay_id="a1b2c3d4e5f67890a1b2c3d4e5f67890",
+ account_id="023e105f4ecef8ad9ca31a8372d0c353",
+ type="publish_subscribe",
+ )
+ assert_matches_type(Optional[TokenRotateResponse], token, path=["response"])
+
+ @parametrize
+ async def test_raw_response_rotate(self, async_client: AsyncCloudflare) -> None:
+ response = await async_client.moq.relays.tokens.with_raw_response.rotate(
+ relay_id="a1b2c3d4e5f67890a1b2c3d4e5f67890",
+ account_id="023e105f4ecef8ad9ca31a8372d0c353",
+ type="publish_subscribe",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ token = await response.parse()
+ assert_matches_type(Optional[TokenRotateResponse], token, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_rotate(self, async_client: AsyncCloudflare) -> None:
+ async with async_client.moq.relays.tokens.with_streaming_response.rotate(
+ relay_id="a1b2c3d4e5f67890a1b2c3d4e5f67890",
+ account_id="023e105f4ecef8ad9ca31a8372d0c353",
+ type="publish_subscribe",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ token = await response.parse()
+ assert_matches_type(Optional[TokenRotateResponse], token, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_path_params_rotate(self, async_client: AsyncCloudflare) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"):
+ await async_client.moq.relays.tokens.with_raw_response.rotate(
+ relay_id="a1b2c3d4e5f67890a1b2c3d4e5f67890",
+ account_id="",
+ type="publish_subscribe",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `relay_id` but received ''"):
+ await async_client.moq.relays.tokens.with_raw_response.rotate(
+ relay_id="",
+ account_id="023e105f4ecef8ad9ca31a8372d0c353",
+ type="publish_subscribe",
+ )
diff --git a/tests/api_resources/moq/test_relays.py b/tests/api_resources/moq/test_relays.py
new file mode 100644
index 00000000000..ca73a9d4df8
--- /dev/null
+++ b/tests/api_resources/moq/test_relays.py
@@ -0,0 +1,539 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+import os
+from typing import Any, Optional, cast
+
+import pytest
+
+from cloudflare import Cloudflare, AsyncCloudflare
+from tests.utils import assert_matches_type
+from cloudflare._utils import parse_datetime
+from cloudflare.types.moq import (
+ RelayGetResponse,
+ RelayListResponse,
+ RelayCreateResponse,
+ RelayUpdateResponse,
+)
+from cloudflare.pagination import SyncSinglePage, AsyncSinglePage
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestRelays:
+ parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
+
+ @parametrize
+ def test_method_create(self, client: Cloudflare) -> None:
+ relay = client.moq.relays.create(
+ account_id="023e105f4ecef8ad9ca31a8372d0c353",
+ name="Production Live Stream",
+ )
+ assert_matches_type(Optional[RelayCreateResponse], relay, path=["response"])
+
+ @parametrize
+ def test_raw_response_create(self, client: Cloudflare) -> None:
+ response = client.moq.relays.with_raw_response.create(
+ account_id="023e105f4ecef8ad9ca31a8372d0c353",
+ name="Production Live Stream",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ relay = response.parse()
+ assert_matches_type(Optional[RelayCreateResponse], relay, path=["response"])
+
+ @parametrize
+ def test_streaming_response_create(self, client: Cloudflare) -> None:
+ with client.moq.relays.with_streaming_response.create(
+ account_id="023e105f4ecef8ad9ca31a8372d0c353",
+ name="Production Live Stream",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ relay = response.parse()
+ assert_matches_type(Optional[RelayCreateResponse], relay, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_path_params_create(self, client: Cloudflare) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"):
+ client.moq.relays.with_raw_response.create(
+ account_id="",
+ name="Production Live Stream",
+ )
+
+ @parametrize
+ def test_method_update(self, client: Cloudflare) -> None:
+ relay = client.moq.relays.update(
+ relay_id="a1b2c3d4e5f67890a1b2c3d4e5f67890",
+ account_id="023e105f4ecef8ad9ca31a8372d0c353",
+ )
+ assert_matches_type(Optional[RelayUpdateResponse], relay, path=["response"])
+
+ @parametrize
+ def test_method_update_with_all_params(self, client: Cloudflare) -> None:
+ relay = client.moq.relays.update(
+ relay_id="a1b2c3d4e5f67890a1b2c3d4e5f67890",
+ account_id="023e105f4ecef8ad9ca31a8372d0c353",
+ config={
+ "lingering_subscribe": {
+ "enabled": True,
+ "max_timeout_ms": 0,
+ },
+ "origin_fallback": {
+ "enabled": True,
+ "origins": [{"url": "url"}],
+ },
+ },
+ name="name",
+ )
+ assert_matches_type(Optional[RelayUpdateResponse], relay, path=["response"])
+
+ @parametrize
+ def test_raw_response_update(self, client: Cloudflare) -> None:
+ response = client.moq.relays.with_raw_response.update(
+ relay_id="a1b2c3d4e5f67890a1b2c3d4e5f67890",
+ account_id="023e105f4ecef8ad9ca31a8372d0c353",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ relay = response.parse()
+ assert_matches_type(Optional[RelayUpdateResponse], relay, path=["response"])
+
+ @parametrize
+ def test_streaming_response_update(self, client: Cloudflare) -> None:
+ with client.moq.relays.with_streaming_response.update(
+ relay_id="a1b2c3d4e5f67890a1b2c3d4e5f67890",
+ account_id="023e105f4ecef8ad9ca31a8372d0c353",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ relay = response.parse()
+ assert_matches_type(Optional[RelayUpdateResponse], relay, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_path_params_update(self, client: Cloudflare) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"):
+ client.moq.relays.with_raw_response.update(
+ relay_id="a1b2c3d4e5f67890a1b2c3d4e5f67890",
+ account_id="",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `relay_id` but received ''"):
+ client.moq.relays.with_raw_response.update(
+ relay_id="",
+ account_id="023e105f4ecef8ad9ca31a8372d0c353",
+ )
+
+ @parametrize
+ def test_method_list(self, client: Cloudflare) -> None:
+ relay = client.moq.relays.list(
+ account_id="023e105f4ecef8ad9ca31a8372d0c353",
+ )
+ assert_matches_type(SyncSinglePage[RelayListResponse], relay, path=["response"])
+
+ @parametrize
+ def test_method_list_with_all_params(self, client: Cloudflare) -> None:
+ relay = client.moq.relays.list(
+ account_id="023e105f4ecef8ad9ca31a8372d0c353",
+ asc=True,
+ created_after=parse_datetime("2026-03-27T15:00:00Z"),
+ created_before=parse_datetime("2026-03-27T15:00:00Z"),
+ per_page=50,
+ )
+ assert_matches_type(SyncSinglePage[RelayListResponse], relay, path=["response"])
+
+ @parametrize
+ def test_raw_response_list(self, client: Cloudflare) -> None:
+ response = client.moq.relays.with_raw_response.list(
+ account_id="023e105f4ecef8ad9ca31a8372d0c353",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ relay = response.parse()
+ assert_matches_type(SyncSinglePage[RelayListResponse], relay, path=["response"])
+
+ @parametrize
+ def test_streaming_response_list(self, client: Cloudflare) -> None:
+ with client.moq.relays.with_streaming_response.list(
+ account_id="023e105f4ecef8ad9ca31a8372d0c353",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ relay = response.parse()
+ assert_matches_type(SyncSinglePage[RelayListResponse], relay, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_path_params_list(self, client: Cloudflare) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"):
+ client.moq.relays.with_raw_response.list(
+ account_id="",
+ )
+
+ @parametrize
+ def test_method_delete(self, client: Cloudflare) -> None:
+ relay = client.moq.relays.delete(
+ relay_id="a1b2c3d4e5f67890a1b2c3d4e5f67890",
+ account_id="023e105f4ecef8ad9ca31a8372d0c353",
+ )
+ assert_matches_type(object, relay, path=["response"])
+
+ @parametrize
+ def test_raw_response_delete(self, client: Cloudflare) -> None:
+ response = client.moq.relays.with_raw_response.delete(
+ relay_id="a1b2c3d4e5f67890a1b2c3d4e5f67890",
+ account_id="023e105f4ecef8ad9ca31a8372d0c353",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ relay = response.parse()
+ assert_matches_type(object, relay, path=["response"])
+
+ @parametrize
+ def test_streaming_response_delete(self, client: Cloudflare) -> None:
+ with client.moq.relays.with_streaming_response.delete(
+ relay_id="a1b2c3d4e5f67890a1b2c3d4e5f67890",
+ account_id="023e105f4ecef8ad9ca31a8372d0c353",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ relay = response.parse()
+ assert_matches_type(object, relay, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_path_params_delete(self, client: Cloudflare) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"):
+ client.moq.relays.with_raw_response.delete(
+ relay_id="a1b2c3d4e5f67890a1b2c3d4e5f67890",
+ account_id="",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `relay_id` but received ''"):
+ client.moq.relays.with_raw_response.delete(
+ relay_id="",
+ account_id="023e105f4ecef8ad9ca31a8372d0c353",
+ )
+
+ @parametrize
+ def test_method_get(self, client: Cloudflare) -> None:
+ relay = client.moq.relays.get(
+ relay_id="a1b2c3d4e5f67890a1b2c3d4e5f67890",
+ account_id="023e105f4ecef8ad9ca31a8372d0c353",
+ )
+ assert_matches_type(Optional[RelayGetResponse], relay, path=["response"])
+
+ @parametrize
+ def test_raw_response_get(self, client: Cloudflare) -> None:
+ response = client.moq.relays.with_raw_response.get(
+ relay_id="a1b2c3d4e5f67890a1b2c3d4e5f67890",
+ account_id="023e105f4ecef8ad9ca31a8372d0c353",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ relay = response.parse()
+ assert_matches_type(Optional[RelayGetResponse], relay, path=["response"])
+
+ @parametrize
+ def test_streaming_response_get(self, client: Cloudflare) -> None:
+ with client.moq.relays.with_streaming_response.get(
+ relay_id="a1b2c3d4e5f67890a1b2c3d4e5f67890",
+ account_id="023e105f4ecef8ad9ca31a8372d0c353",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ relay = response.parse()
+ assert_matches_type(Optional[RelayGetResponse], relay, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_path_params_get(self, client: Cloudflare) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"):
+ client.moq.relays.with_raw_response.get(
+ relay_id="a1b2c3d4e5f67890a1b2c3d4e5f67890",
+ account_id="",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `relay_id` but received ''"):
+ client.moq.relays.with_raw_response.get(
+ relay_id="",
+ account_id="023e105f4ecef8ad9ca31a8372d0c353",
+ )
+
+
+class TestAsyncRelays:
+ parametrize = pytest.mark.parametrize(
+ "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
+ )
+
+ @parametrize
+ async def test_method_create(self, async_client: AsyncCloudflare) -> None:
+ relay = await async_client.moq.relays.create(
+ account_id="023e105f4ecef8ad9ca31a8372d0c353",
+ name="Production Live Stream",
+ )
+ assert_matches_type(Optional[RelayCreateResponse], relay, path=["response"])
+
+ @parametrize
+ async def test_raw_response_create(self, async_client: AsyncCloudflare) -> None:
+ response = await async_client.moq.relays.with_raw_response.create(
+ account_id="023e105f4ecef8ad9ca31a8372d0c353",
+ name="Production Live Stream",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ relay = await response.parse()
+ assert_matches_type(Optional[RelayCreateResponse], relay, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_create(self, async_client: AsyncCloudflare) -> None:
+ async with async_client.moq.relays.with_streaming_response.create(
+ account_id="023e105f4ecef8ad9ca31a8372d0c353",
+ name="Production Live Stream",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ relay = await response.parse()
+ assert_matches_type(Optional[RelayCreateResponse], relay, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_path_params_create(self, async_client: AsyncCloudflare) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"):
+ await async_client.moq.relays.with_raw_response.create(
+ account_id="",
+ name="Production Live Stream",
+ )
+
+ @parametrize
+ async def test_method_update(self, async_client: AsyncCloudflare) -> None:
+ relay = await async_client.moq.relays.update(
+ relay_id="a1b2c3d4e5f67890a1b2c3d4e5f67890",
+ account_id="023e105f4ecef8ad9ca31a8372d0c353",
+ )
+ assert_matches_type(Optional[RelayUpdateResponse], relay, path=["response"])
+
+ @parametrize
+ async def test_method_update_with_all_params(self, async_client: AsyncCloudflare) -> None:
+ relay = await async_client.moq.relays.update(
+ relay_id="a1b2c3d4e5f67890a1b2c3d4e5f67890",
+ account_id="023e105f4ecef8ad9ca31a8372d0c353",
+ config={
+ "lingering_subscribe": {
+ "enabled": True,
+ "max_timeout_ms": 0,
+ },
+ "origin_fallback": {
+ "enabled": True,
+ "origins": [{"url": "url"}],
+ },
+ },
+ name="name",
+ )
+ assert_matches_type(Optional[RelayUpdateResponse], relay, path=["response"])
+
+ @parametrize
+ async def test_raw_response_update(self, async_client: AsyncCloudflare) -> None:
+ response = await async_client.moq.relays.with_raw_response.update(
+ relay_id="a1b2c3d4e5f67890a1b2c3d4e5f67890",
+ account_id="023e105f4ecef8ad9ca31a8372d0c353",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ relay = await response.parse()
+ assert_matches_type(Optional[RelayUpdateResponse], relay, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_update(self, async_client: AsyncCloudflare) -> None:
+ async with async_client.moq.relays.with_streaming_response.update(
+ relay_id="a1b2c3d4e5f67890a1b2c3d4e5f67890",
+ account_id="023e105f4ecef8ad9ca31a8372d0c353",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ relay = await response.parse()
+ assert_matches_type(Optional[RelayUpdateResponse], relay, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_path_params_update(self, async_client: AsyncCloudflare) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"):
+ await async_client.moq.relays.with_raw_response.update(
+ relay_id="a1b2c3d4e5f67890a1b2c3d4e5f67890",
+ account_id="",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `relay_id` but received ''"):
+ await async_client.moq.relays.with_raw_response.update(
+ relay_id="",
+ account_id="023e105f4ecef8ad9ca31a8372d0c353",
+ )
+
+ @parametrize
+ async def test_method_list(self, async_client: AsyncCloudflare) -> None:
+ relay = await async_client.moq.relays.list(
+ account_id="023e105f4ecef8ad9ca31a8372d0c353",
+ )
+ assert_matches_type(AsyncSinglePage[RelayListResponse], relay, path=["response"])
+
+ @parametrize
+ async def test_method_list_with_all_params(self, async_client: AsyncCloudflare) -> None:
+ relay = await async_client.moq.relays.list(
+ account_id="023e105f4ecef8ad9ca31a8372d0c353",
+ asc=True,
+ created_after=parse_datetime("2026-03-27T15:00:00Z"),
+ created_before=parse_datetime("2026-03-27T15:00:00Z"),
+ per_page=50,
+ )
+ assert_matches_type(AsyncSinglePage[RelayListResponse], relay, path=["response"])
+
+ @parametrize
+ async def test_raw_response_list(self, async_client: AsyncCloudflare) -> None:
+ response = await async_client.moq.relays.with_raw_response.list(
+ account_id="023e105f4ecef8ad9ca31a8372d0c353",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ relay = await response.parse()
+ assert_matches_type(AsyncSinglePage[RelayListResponse], relay, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_list(self, async_client: AsyncCloudflare) -> None:
+ async with async_client.moq.relays.with_streaming_response.list(
+ account_id="023e105f4ecef8ad9ca31a8372d0c353",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ relay = await response.parse()
+ assert_matches_type(AsyncSinglePage[RelayListResponse], relay, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_path_params_list(self, async_client: AsyncCloudflare) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"):
+ await async_client.moq.relays.with_raw_response.list(
+ account_id="",
+ )
+
+ @parametrize
+ async def test_method_delete(self, async_client: AsyncCloudflare) -> None:
+ relay = await async_client.moq.relays.delete(
+ relay_id="a1b2c3d4e5f67890a1b2c3d4e5f67890",
+ account_id="023e105f4ecef8ad9ca31a8372d0c353",
+ )
+ assert_matches_type(object, relay, path=["response"])
+
+ @parametrize
+ async def test_raw_response_delete(self, async_client: AsyncCloudflare) -> None:
+ response = await async_client.moq.relays.with_raw_response.delete(
+ relay_id="a1b2c3d4e5f67890a1b2c3d4e5f67890",
+ account_id="023e105f4ecef8ad9ca31a8372d0c353",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ relay = await response.parse()
+ assert_matches_type(object, relay, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_delete(self, async_client: AsyncCloudflare) -> None:
+ async with async_client.moq.relays.with_streaming_response.delete(
+ relay_id="a1b2c3d4e5f67890a1b2c3d4e5f67890",
+ account_id="023e105f4ecef8ad9ca31a8372d0c353",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ relay = await response.parse()
+ assert_matches_type(object, relay, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_path_params_delete(self, async_client: AsyncCloudflare) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"):
+ await async_client.moq.relays.with_raw_response.delete(
+ relay_id="a1b2c3d4e5f67890a1b2c3d4e5f67890",
+ account_id="",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `relay_id` but received ''"):
+ await async_client.moq.relays.with_raw_response.delete(
+ relay_id="",
+ account_id="023e105f4ecef8ad9ca31a8372d0c353",
+ )
+
+ @parametrize
+ async def test_method_get(self, async_client: AsyncCloudflare) -> None:
+ relay = await async_client.moq.relays.get(
+ relay_id="a1b2c3d4e5f67890a1b2c3d4e5f67890",
+ account_id="023e105f4ecef8ad9ca31a8372d0c353",
+ )
+ assert_matches_type(Optional[RelayGetResponse], relay, path=["response"])
+
+ @parametrize
+ async def test_raw_response_get(self, async_client: AsyncCloudflare) -> None:
+ response = await async_client.moq.relays.with_raw_response.get(
+ relay_id="a1b2c3d4e5f67890a1b2c3d4e5f67890",
+ account_id="023e105f4ecef8ad9ca31a8372d0c353",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ relay = await response.parse()
+ assert_matches_type(Optional[RelayGetResponse], relay, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_get(self, async_client: AsyncCloudflare) -> None:
+ async with async_client.moq.relays.with_streaming_response.get(
+ relay_id="a1b2c3d4e5f67890a1b2c3d4e5f67890",
+ account_id="023e105f4ecef8ad9ca31a8372d0c353",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ relay = await response.parse()
+ assert_matches_type(Optional[RelayGetResponse], relay, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_path_params_get(self, async_client: AsyncCloudflare) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `account_id` but received ''"):
+ await async_client.moq.relays.with_raw_response.get(
+ relay_id="a1b2c3d4e5f67890a1b2c3d4e5f67890",
+ account_id="",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `relay_id` but received ''"):
+ await async_client.moq.relays.with_raw_response.get(
+ relay_id="",
+ account_id="023e105f4ecef8ad9ca31a8372d0c353",
+ )
diff --git a/tests/api_resources/rulesets/test_rules.py b/tests/api_resources/rulesets/test_rules.py
index 0270791a0b1..2b88ce437de 100644
--- a/tests/api_resources/rulesets/test_rules.py
+++ b/tests/api_resources/rulesets/test_rules.py
@@ -1688,6 +1688,20 @@ def test_method_create_with_all_params_overload_17(self, client: Cloudflare) ->
"strip_etags": True,
"strip_last_modified": True,
"strip_set_cookie": True,
+ "vary": {
+ "default": {
+ "action": "normalize",
+ "languages": ["en"],
+ "media_types": ["image/webp"],
+ },
+ "headers": {
+ "accept": {
+ "action": "normalize",
+ "languages": ["en"],
+ "media_types": ["image/webp", "image/png"],
+ }
+ },
+ },
},
description="Configure settings for how the response is cached.",
enabled=True,
@@ -4042,6 +4056,20 @@ def test_method_edit_with_all_params_overload_17(self, client: Cloudflare) -> No
"strip_etags": True,
"strip_last_modified": True,
"strip_set_cookie": True,
+ "vary": {
+ "default": {
+ "action": "normalize",
+ "languages": ["en"],
+ "media_types": ["image/webp"],
+ },
+ "headers": {
+ "accept": {
+ "action": "normalize",
+ "languages": ["en"],
+ "media_types": ["image/webp", "image/png"],
+ }
+ },
+ },
},
description="Configure settings for how the response is cached.",
enabled=True,
@@ -6149,6 +6177,20 @@ async def test_method_create_with_all_params_overload_17(self, async_client: Asy
"strip_etags": True,
"strip_last_modified": True,
"strip_set_cookie": True,
+ "vary": {
+ "default": {
+ "action": "normalize",
+ "languages": ["en"],
+ "media_types": ["image/webp"],
+ },
+ "headers": {
+ "accept": {
+ "action": "normalize",
+ "languages": ["en"],
+ "media_types": ["image/webp", "image/png"],
+ }
+ },
+ },
},
description="Configure settings for how the response is cached.",
enabled=True,
@@ -8503,6 +8545,20 @@ async def test_method_edit_with_all_params_overload_17(self, async_client: Async
"strip_etags": True,
"strip_last_modified": True,
"strip_set_cookie": True,
+ "vary": {
+ "default": {
+ "action": "normalize",
+ "languages": ["en"],
+ "media_types": ["image/webp"],
+ },
+ "headers": {
+ "accept": {
+ "action": "normalize",
+ "languages": ["en"],
+ "media_types": ["image/webp", "image/png"],
+ }
+ },
+ },
},
description="Configure settings for how the response is cached.",
enabled=True,