From b4e4ce8a56859a87137349e5f97ede2c8acaad25 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 20 Feb 2026 07:26:59 +0000 Subject: [PATCH 1/3] chore: update mock server docs --- CONTRIBUTING.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1a02fdd..e40b567 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -88,8 +88,7 @@ $ pip install ./path-to-wheel-file.whl Most tests require you to [set up a mock server](https://github.com/stoplightio/prism) against the OpenAPI spec to run the tests. ```sh -# you will need npm installed -$ npx prism mock path/to/your/openapi.yml +$ ./scripts/mock ``` ```sh From 3eddd677b69f387149336e11abe71a6143290ac4 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 20 Feb 2026 10:20:04 +0000 Subject: [PATCH 2/3] feat(api): add tenantId to send --- .stats.yml | 4 +- src/ark/resources/emails.py | 60 +++++++++++++++++++ src/ark/types/email_list_response.py | 3 + .../email_retrieve_deliveries_response.py | 3 + src/ark/types/email_retrieve_response.py | 3 + src/ark/types/email_retry_response.py | 5 ++ src/ark/types/email_send_batch_params.py | 11 ++++ src/ark/types/email_send_batch_response.py | 5 ++ src/ark/types/email_send_params.py | 11 ++++ src/ark/types/email_send_raw_params.py | 11 ++++ src/ark/types/email_send_raw_response.py | 3 + src/ark/types/email_send_response.py | 3 + tests/api_resources/test_emails.py | 6 ++ 13 files changed, 126 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index c8ee129..e530c9b 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 58 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/ark%2Fark-98a90852ffca49f4e26c613afff433b17023ee1f81f38ad38a5dad60a0d09881.yml -openapi_spec_hash: c6fd865dd6995df15cf9e6ada2ae791e +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/ark%2Fark-06c3025bf12b191c3906b28173c9b359e24481dd2839dbf3e6dd0b80c1de3fd6.yml +openapi_spec_hash: d8f8fb1f78579997b6381d64cba4e826 config_hash: b70b11b10fc614f91f1c6f028b40780f diff --git a/src/ark/resources/emails.py b/src/ark/resources/emails.py index 77631ce..508b5e9 100644 --- a/src/ark/resources/emails.py +++ b/src/ark/resources/emails.py @@ -317,6 +317,7 @@ def send( metadata: Optional[Dict[str, str]] | Omit = omit, reply_to: Optional[str] | Omit = omit, tag: Optional[str] | Omit = omit, + tenant_id: Optional[str] | Omit = omit, text: Optional[str] | Omit = omit, idempotency_key: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -396,6 +397,14 @@ def send( tag: Tag for categorization and filtering (accepts null) + tenant_id: The tenant ID to send this email from. Determines which tenant's configuration + (domains, webhooks, tracking) is used. + + - If your API key is scoped to a specific tenant, this must match that tenant or + be omitted. + - If your API key is org-level, specify the tenant to send from. + - If omitted, the organization's default tenant is used. + text: Plain text body (accepts null, auto-generated from HTML if not provided). Maximum 5MB (5,242,880 characters). @@ -423,6 +432,7 @@ def send( "metadata": metadata, "reply_to": reply_to, "tag": tag, + "tenant_id": tenant_id, "text": text, }, email_send_params.EmailSendParams, @@ -438,6 +448,7 @@ def send_batch( *, emails: Iterable[email_send_batch_params.Email], from_: str, + tenant_id: Optional[str] | Omit = omit, idempotency_key: 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. @@ -459,6 +470,14 @@ def send_batch( Args: from_: Sender email for all messages + tenant_id: The tenant ID to send this batch from. Determines which tenant's configuration + (domains, webhooks, tracking) is used. + + - If your API key is scoped to a specific tenant, this must match that tenant or + be omitted. + - If your API key is org-level, specify the tenant to send from. + - If omitted, the organization's default tenant is used. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -474,6 +493,7 @@ def send_batch( { "emails": emails, "from_": from_, + "tenant_id": tenant_id, }, email_send_batch_params.EmailSendBatchParams, ), @@ -490,6 +510,7 @@ def send_raw( raw_message: str, to: SequenceNotStr[str], bounce: Optional[bool] | Omit = omit, + tenant_id: Optional[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, @@ -527,6 +548,14 @@ def send_raw( bounce: Whether this is a bounce message (accepts null) + tenant_id: The tenant ID to send this email from. Determines which tenant's configuration + (domains, webhooks, tracking) is used. + + - If your API key is scoped to a specific tenant, this must match that tenant or + be omitted. + - If your API key is org-level, specify the tenant to send from. + - If omitted, the organization's default tenant is used. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -543,6 +572,7 @@ def send_raw( "raw_message": raw_message, "to": to, "bounce": bounce, + "tenant_id": tenant_id, }, email_send_raw_params.EmailSendRawParams, ), @@ -833,6 +863,7 @@ async def send( metadata: Optional[Dict[str, str]] | Omit = omit, reply_to: Optional[str] | Omit = omit, tag: Optional[str] | Omit = omit, + tenant_id: Optional[str] | Omit = omit, text: Optional[str] | Omit = omit, idempotency_key: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -912,6 +943,14 @@ async def send( tag: Tag for categorization and filtering (accepts null) + tenant_id: The tenant ID to send this email from. Determines which tenant's configuration + (domains, webhooks, tracking) is used. + + - If your API key is scoped to a specific tenant, this must match that tenant or + be omitted. + - If your API key is org-level, specify the tenant to send from. + - If omitted, the organization's default tenant is used. + text: Plain text body (accepts null, auto-generated from HTML if not provided). Maximum 5MB (5,242,880 characters). @@ -939,6 +978,7 @@ async def send( "metadata": metadata, "reply_to": reply_to, "tag": tag, + "tenant_id": tenant_id, "text": text, }, email_send_params.EmailSendParams, @@ -954,6 +994,7 @@ async def send_batch( *, emails: Iterable[email_send_batch_params.Email], from_: str, + tenant_id: Optional[str] | Omit = omit, idempotency_key: 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. @@ -975,6 +1016,14 @@ async def send_batch( Args: from_: Sender email for all messages + tenant_id: The tenant ID to send this batch from. Determines which tenant's configuration + (domains, webhooks, tracking) is used. + + - If your API key is scoped to a specific tenant, this must match that tenant or + be omitted. + - If your API key is org-level, specify the tenant to send from. + - If omitted, the organization's default tenant is used. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -990,6 +1039,7 @@ async def send_batch( { "emails": emails, "from_": from_, + "tenant_id": tenant_id, }, email_send_batch_params.EmailSendBatchParams, ), @@ -1006,6 +1056,7 @@ async def send_raw( raw_message: str, to: SequenceNotStr[str], bounce: Optional[bool] | Omit = omit, + tenant_id: Optional[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, @@ -1043,6 +1094,14 @@ async def send_raw( bounce: Whether this is a bounce message (accepts null) + tenant_id: The tenant ID to send this email from. Determines which tenant's configuration + (domains, webhooks, tracking) is used. + + - If your API key is scoped to a specific tenant, this must match that tenant or + be omitted. + - If your API key is org-level, specify the tenant to send from. + - If omitted, the organization's default tenant is used. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -1059,6 +1118,7 @@ async def send_raw( "raw_message": raw_message, "to": to, "bounce": bounce, + "tenant_id": tenant_id, }, email_send_raw_params.EmailSendRawParams, ), diff --git a/src/ark/types/email_list_response.py b/src/ark/types/email_list_response.py index dce7d39..21bd18e 100644 --- a/src/ark/types/email_list_response.py +++ b/src/ark/types/email_list_response.py @@ -30,6 +30,9 @@ class EmailListResponse(BaseModel): subject: str + tenant_id: str = FieldInfo(alias="tenantId") + """The tenant ID this email belongs to""" + timestamp: float timestamp_iso: datetime = FieldInfo(alias="timestampIso") diff --git a/src/ark/types/email_retrieve_deliveries_response.py b/src/ark/types/email_retrieve_deliveries_response.py index a923d98..1f3c1bc 100644 --- a/src/ark/types/email_retrieve_deliveries_response.py +++ b/src/ark/types/email_retrieve_deliveries_response.py @@ -170,6 +170,9 @@ class Data(BaseModel): - `bounced` - Bounced by recipient server """ + tenant_id: str = FieldInfo(alias="tenantId") + """The tenant ID this email belongs to""" + class EmailRetrieveDeliveriesResponse(BaseModel): data: Data diff --git a/src/ark/types/email_retrieve_response.py b/src/ark/types/email_retrieve_response.py index d9bc54c..c0de6b1 100644 --- a/src/ark/types/email_retrieve_response.py +++ b/src/ark/types/email_retrieve_response.py @@ -179,6 +179,9 @@ class Data(BaseModel): subject: str """Email subject line""" + tenant_id: str = FieldInfo(alias="tenantId") + """The tenant ID this email belongs to""" + timestamp: float """Unix timestamp when the email was sent""" diff --git a/src/ark/types/email_retry_response.py b/src/ark/types/email_retry_response.py index f63cc99..fe5d8ce 100644 --- a/src/ark/types/email_retry_response.py +++ b/src/ark/types/email_retry_response.py @@ -2,6 +2,8 @@ from typing_extensions import Literal +from pydantic import Field as FieldInfo + from .._models import BaseModel from .shared.api_meta import APIMeta @@ -14,6 +16,9 @@ class Data(BaseModel): message: str + tenant_id: str = FieldInfo(alias="tenantId") + """The tenant ID this email belongs to""" + class EmailRetryResponse(BaseModel): data: Data diff --git a/src/ark/types/email_send_batch_params.py b/src/ark/types/email_send_batch_params.py index ba54d41..38c9caf 100644 --- a/src/ark/types/email_send_batch_params.py +++ b/src/ark/types/email_send_batch_params.py @@ -17,6 +17,17 @@ class EmailSendBatchParams(TypedDict, total=False): from_: Required[Annotated[str, PropertyInfo(alias="from")]] """Sender email for all messages""" + tenant_id: Annotated[Optional[str], PropertyInfo(alias="tenantId")] + """The tenant ID to send this batch from. + + Determines which tenant's configuration (domains, webhooks, tracking) is used. + + - If your API key is scoped to a specific tenant, this must match that tenant or + be omitted. + - If your API key is org-level, specify the tenant to send from. + - If omitted, the organization's default tenant is used. + """ + idempotency_key: Annotated[str, PropertyInfo(alias="Idempotency-Key")] diff --git a/src/ark/types/email_send_batch_response.py b/src/ark/types/email_send_batch_response.py index d32e3fc..06fe526 100644 --- a/src/ark/types/email_send_batch_response.py +++ b/src/ark/types/email_send_batch_response.py @@ -3,6 +3,8 @@ from typing import Dict, Optional from typing_extensions import Literal +from pydantic import Field as FieldInfo + from .._models import BaseModel from .shared.api_meta import APIMeta @@ -24,6 +26,9 @@ class Data(BaseModel): messages: Dict[str, DataMessages] """Map of recipient email to message info""" + tenant_id: str = FieldInfo(alias="tenantId") + """The tenant ID this batch was sent from""" + total: int """Total emails in the batch""" diff --git a/src/ark/types/email_send_params.py b/src/ark/types/email_send_params.py index 0363339..af3e94f 100644 --- a/src/ark/types/email_send_params.py +++ b/src/ark/types/email_send_params.py @@ -79,6 +79,17 @@ class EmailSendParams(TypedDict, total=False): tag: Optional[str] """Tag for categorization and filtering (accepts null)""" + tenant_id: Annotated[Optional[str], PropertyInfo(alias="tenantId")] + """The tenant ID to send this email from. + + Determines which tenant's configuration (domains, webhooks, tracking) is used. + + - If your API key is scoped to a specific tenant, this must match that tenant or + be omitted. + - If your API key is org-level, specify the tenant to send from. + - If omitted, the organization's default tenant is used. + """ + text: Optional[str] """ Plain text body (accepts null, auto-generated from HTML if not provided). diff --git a/src/ark/types/email_send_raw_params.py b/src/ark/types/email_send_raw_params.py index d957f74..56c038b 100644 --- a/src/ark/types/email_send_raw_params.py +++ b/src/ark/types/email_send_raw_params.py @@ -37,3 +37,14 @@ class EmailSendRawParams(TypedDict, total=False): bounce: Optional[bool] """Whether this is a bounce message (accepts null)""" + + tenant_id: Annotated[Optional[str], PropertyInfo(alias="tenantId")] + """The tenant ID to send this email from. + + Determines which tenant's configuration (domains, webhooks, tracking) is used. + + - If your API key is scoped to a specific tenant, this must match that tenant or + be omitted. + - If your API key is org-level, specify the tenant to send from. + - If omitted, the organization's default tenant is used. + """ diff --git a/src/ark/types/email_send_raw_response.py b/src/ark/types/email_send_raw_response.py index 46e7c96..80a61fb 100644 --- a/src/ark/types/email_send_raw_response.py +++ b/src/ark/types/email_send_raw_response.py @@ -18,6 +18,9 @@ class Data(BaseModel): status: Literal["pending", "sent"] """Current delivery status""" + tenant_id: str = FieldInfo(alias="tenantId") + """The tenant ID this email was sent from""" + to: List[str] """List of recipient addresses""" diff --git a/src/ark/types/email_send_response.py b/src/ark/types/email_send_response.py index cb7d814..7c54d65 100644 --- a/src/ark/types/email_send_response.py +++ b/src/ark/types/email_send_response.py @@ -18,6 +18,9 @@ class Data(BaseModel): status: Literal["pending", "sent"] """Current delivery status""" + tenant_id: str = FieldInfo(alias="tenantId") + """The tenant ID this email was sent from""" + to: List[str] """List of recipient addresses""" diff --git a/tests/api_resources/test_emails.py b/tests/api_resources/test_emails.py index 0e37b72..daa4744 100644 --- a/tests/api_resources/test_emails.py +++ b/tests/api_resources/test_emails.py @@ -219,6 +219,7 @@ def test_method_send_with_all_params(self, client: Ark) -> None: }, reply_to="dev@stainless.com", tag="tag", + tenant_id="cm6abc123def456", text="text", idempotency_key="user_123_order_456", ) @@ -299,6 +300,7 @@ def test_method_send_batch_with_all_params(self, client: Ark) -> None: }, ], from_="notifications@myapp.com", + tenant_id="cm6abc123def456", idempotency_key="user_123_order_456", ) assert_matches_type(EmailSendBatchResponse, email, path=["response"]) @@ -363,6 +365,7 @@ def test_method_send_raw_with_all_params(self, client: Ark) -> None: raw_message="x", to=["user@example.com"], bounce=True, + tenant_id="cm6abc123def456", ) assert_matches_type(EmailSendRawResponse, email, path=["response"]) @@ -593,6 +596,7 @@ async def test_method_send_with_all_params(self, async_client: AsyncArk) -> None }, reply_to="dev@stainless.com", tag="tag", + tenant_id="cm6abc123def456", text="text", idempotency_key="user_123_order_456", ) @@ -673,6 +677,7 @@ async def test_method_send_batch_with_all_params(self, async_client: AsyncArk) - }, ], from_="notifications@myapp.com", + tenant_id="cm6abc123def456", idempotency_key="user_123_order_456", ) assert_matches_type(EmailSendBatchResponse, email, path=["response"]) @@ -737,6 +742,7 @@ async def test_method_send_raw_with_all_params(self, async_client: AsyncArk) -> raw_message="x", to=["user@example.com"], bounce=True, + tenant_id="cm6abc123def456", ) assert_matches_type(EmailSendRawResponse, email, path=["response"]) From b56adb49f3f1ac7cae4bcec94ce92826abc8c96c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 20 Feb 2026 10:20:44 +0000 Subject: [PATCH 3/3] release: 0.19.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 13 +++++++++++++ pyproject.toml | 2 +- src/ark/_version.py | 2 +- 4 files changed, 16 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index d661066..e756293 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.18.1" + ".": "0.19.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index a755aaa..2a4443c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,18 @@ # Changelog +## 0.19.0 (2026-02-20) + +Full Changelog: [v0.18.1...v0.19.0](https://github.com/ArkHQ-io/ark-python/compare/v0.18.1...v0.19.0) + +### Features + +* **api:** add tenantId to send ([3eddd67](https://github.com/ArkHQ-io/ark-python/commit/3eddd677b69f387149336e11abe71a6143290ac4)) + + +### Chores + +* update mock server docs ([b4e4ce8](https://github.com/ArkHQ-io/ark-python/commit/b4e4ce8a56859a87137349e5f97ede2c8acaad25)) + ## 0.18.1 (2026-02-18) Full Changelog: [v0.18.0...v0.18.1](https://github.com/ArkHQ-io/ark-python/compare/v0.18.0...v0.18.1) diff --git a/pyproject.toml b/pyproject.toml index 0adad94..d762cba 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "ark-email" -version = "0.18.1" +version = "0.19.0" description = "The official Python library for the ark API" dynamic = ["readme"] license = "Apache-2.0" diff --git a/src/ark/_version.py b/src/ark/_version.py index 39f8f2d..a626377 100644 --- a/src/ark/_version.py +++ b/src/ark/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "ark" -__version__ = "0.18.1" # x-release-please-version +__version__ = "0.19.0" # x-release-please-version