From b7dc001d77e093a2d93b4c8e7b7c93f5b4518edd Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 14 Apr 2026 00:56:28 +0000
Subject: [PATCH 1/3] fix(types): make note optional in ResultNotification,
flatten template response
---
.stats.yml | 6 +--
api.md | 8 +--
src/courier/resources/notifications/checks.py | 12 +++++
.../resources/notifications/notifications.py | 26 +++++-----
src/courier/types/__init__.py | 2 +-
.../types/notification_list_response.py | 4 +-
...e.py => notification_template_response.py} | 9 ++--
tests/api_resources/test_notifications.py | 50 +++++++++----------
8 files changed, 64 insertions(+), 53 deletions(-)
rename src/courier/types/{notification_template_get_response.py => notification_template_response.py} (78%)
diff --git a/.stats.yml b/.stats.yml
index 37cb440..998581c 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 103
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/courier%2Fcourier-f0ac5c2fa86eabda773c549f5809d3e2d109e3e1d5a07f6fe1ace18355e4680a.yml
-openapi_spec_hash: b25dc0b42dd9386ab4a025bb2143bde6
-config_hash: 6037e4a9909efb8b2edac2dcc907b84f
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/courier%2Fcourier-0f56d7860a1be3ffaea5dea291b20ac92e31c94d54e41cc8a30462dacf2f2d37.yml
+openapi_spec_hash: 7e7c6f963e83c5f626c09efa322f476a
+config_hash: afcc4f6f8c33ca3f338589e32e086f56
diff --git a/api.md b/api.md
index 80d82a8..7d5e528 100644
--- a/api.md
+++ b/api.md
@@ -351,9 +351,9 @@ from courier.types import (
NotificationGetContent,
NotificationLocalePutRequest,
NotificationTemplateCreateRequest,
- NotificationTemplateGetResponse,
NotificationTemplatePayload,
NotificationTemplatePublishRequest,
+ NotificationTemplateResponse,
NotificationTemplateState,
NotificationTemplateSummary,
NotificationTemplateUpdateRequest,
@@ -366,8 +366,8 @@ from courier.types import (
Methods:
-- client.notifications.create(\*\*params) -> NotificationTemplateGetResponse
-- client.notifications.retrieve(id, \*\*params) -> NotificationTemplateGetResponse
+- client.notifications.create(\*\*params) -> NotificationTemplateResponse
+- client.notifications.retrieve(id, \*\*params) -> NotificationTemplateResponse
- client.notifications.list(\*\*params) -> NotificationListResponse
- client.notifications.archive(id) -> None
- client.notifications.list_versions(id, \*\*params) -> NotificationTemplateVersionListResponse
@@ -375,7 +375,7 @@ Methods:
- client.notifications.put_content(id, \*\*params) -> NotificationContentMutationResponse
- client.notifications.put_element(element_id, \*, id, \*\*params) -> NotificationContentMutationResponse
- client.notifications.put_locale(locale_id, \*, id, \*\*params) -> NotificationContentMutationResponse
-- client.notifications.replace(id, \*\*params) -> NotificationTemplateGetResponse
+- client.notifications.replace(id, \*\*params) -> NotificationTemplateResponse
- client.notifications.retrieve_content(id, \*\*params) -> NotificationRetrieveContentResponse
## Checks
diff --git a/src/courier/resources/notifications/checks.py b/src/courier/resources/notifications/checks.py
index 0b2c523..fd666d9 100644
--- a/src/courier/resources/notifications/checks.py
+++ b/src/courier/resources/notifications/checks.py
@@ -59,6 +59,8 @@ def update(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> CheckUpdateResponse:
"""
+ Replace the checks for a notification template submission.
+
Args:
extra_headers: Send extra headers
@@ -94,6 +96,8 @@ def list(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> CheckListResponse:
"""
+ Retrieve the checks for a notification template submission.
+
Args:
extra_headers: Send extra headers
@@ -128,6 +132,8 @@ def delete(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> None:
"""
+ Cancel a notification template submission.
+
Args:
extra_headers: Send extra headers
@@ -185,6 +191,8 @@ async def update(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> CheckUpdateResponse:
"""
+ Replace the checks for a notification template submission.
+
Args:
extra_headers: Send extra headers
@@ -220,6 +228,8 @@ async def list(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> CheckListResponse:
"""
+ Retrieve the checks for a notification template submission.
+
Args:
extra_headers: Send extra headers
@@ -254,6 +264,8 @@ async def delete(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> None:
"""
+ Cancel a notification template submission.
+
Args:
extra_headers: Send extra headers
diff --git a/src/courier/resources/notifications/notifications.py b/src/courier/resources/notifications/notifications.py
index 93ac470..f12be4b 100644
--- a/src/courier/resources/notifications/notifications.py
+++ b/src/courier/resources/notifications/notifications.py
@@ -41,7 +41,7 @@
from ..._base_client import make_request_options
from ...types.notification_list_response import NotificationListResponse
from ...types.notification_template_state import NotificationTemplateState
-from ...types.notification_template_get_response import NotificationTemplateGetResponse
+from ...types.notification_template_response import NotificationTemplateResponse
from ...types.notification_template_payload_param import NotificationTemplatePayloadParam
from ...types.notification_content_mutation_response import NotificationContentMutationResponse
from ...types.notification_retrieve_content_response import NotificationRetrieveContentResponse
@@ -85,7 +85,7 @@ def create(
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> NotificationTemplateGetResponse:
+ ) -> NotificationTemplateResponse:
"""Create a notification template.
Requires all fields in the notification object.
@@ -118,7 +118,7 @@ def create(
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
- cast_to=NotificationTemplateGetResponse,
+ cast_to=NotificationTemplateResponse,
)
def retrieve(
@@ -132,7 +132,7 @@ def retrieve(
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> NotificationTemplateGetResponse:
+ ) -> NotificationTemplateResponse:
"""Retrieve a notification template by ID.
Returns the published version by
@@ -161,7 +161,7 @@ def retrieve(
timeout=timeout,
query=maybe_transform({"version": version}, notification_retrieve_params.NotificationRetrieveParams),
),
- cast_to=NotificationTemplateGetResponse,
+ cast_to=NotificationTemplateResponse,
)
def list(
@@ -511,7 +511,7 @@ def replace(
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> NotificationTemplateGetResponse:
+ ) -> NotificationTemplateResponse:
"""Replace a notification template.
All fields are required.
@@ -545,7 +545,7 @@ def replace(
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
- cast_to=NotificationTemplateGetResponse,
+ cast_to=NotificationTemplateResponse,
)
def retrieve_content(
@@ -636,7 +636,7 @@ async def create(
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> NotificationTemplateGetResponse:
+ ) -> NotificationTemplateResponse:
"""Create a notification template.
Requires all fields in the notification object.
@@ -669,7 +669,7 @@ async def create(
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
- cast_to=NotificationTemplateGetResponse,
+ cast_to=NotificationTemplateResponse,
)
async def retrieve(
@@ -683,7 +683,7 @@ async def retrieve(
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> NotificationTemplateGetResponse:
+ ) -> NotificationTemplateResponse:
"""Retrieve a notification template by ID.
Returns the published version by
@@ -714,7 +714,7 @@ async def retrieve(
{"version": version}, notification_retrieve_params.NotificationRetrieveParams
),
),
- cast_to=NotificationTemplateGetResponse,
+ cast_to=NotificationTemplateResponse,
)
async def list(
@@ -1066,7 +1066,7 @@ async def replace(
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> NotificationTemplateGetResponse:
+ ) -> NotificationTemplateResponse:
"""Replace a notification template.
All fields are required.
@@ -1100,7 +1100,7 @@ async def replace(
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
- cast_to=NotificationTemplateGetResponse,
+ cast_to=NotificationTemplateResponse,
)
async def retrieve_content(
diff --git a/src/courier/types/__init__.py b/src/courier/types/__init__.py
index 92eaece..31bd3e5 100644
--- a/src/courier/types/__init__.py
+++ b/src/courier/types/__init__.py
@@ -215,6 +215,7 @@
from .translation_retrieve_response import TranslationRetrieveResponse as TranslationRetrieveResponse
from .audience_list_members_response import AudienceListMembersResponse as AudienceListMembersResponse
from .notification_put_locale_params import NotificationPutLocaleParams as NotificationPutLocaleParams
+from .notification_template_response import NotificationTemplateResponse as NotificationTemplateResponse
from .routing_strategy_create_params import RoutingStrategyCreateParams as RoutingStrategyCreateParams
from .routing_strategy_list_response import RoutingStrategyListResponse as RoutingStrategyListResponse
from .inbound_bulk_message_user_param import InboundBulkMessageUserParam as InboundBulkMessageUserParam
@@ -226,7 +227,6 @@
from .notification_content_get_response import NotificationContentGetResponse as NotificationContentGetResponse
from .notification_list_versions_params import NotificationListVersionsParams as NotificationListVersionsParams
from .put_subscriptions_recipient_param import PutSubscriptionsRecipientParam as PutSubscriptionsRecipientParam
-from .notification_template_get_response import NotificationTemplateGetResponse as NotificationTemplateGetResponse
from .notification_template_payload_param import NotificationTemplatePayloadParam as NotificationTemplatePayloadParam
from .notification_retrieve_content_params import NotificationRetrieveContentParams as NotificationRetrieveContentParams
from .associated_notification_list_response import (
diff --git a/src/courier/types/notification_list_response.py b/src/courier/types/notification_list_response.py
index 717e07d..1be59f7 100644
--- a/src/courier/types/notification_list_response.py
+++ b/src/courier/types/notification_list_response.py
@@ -36,14 +36,14 @@ class ResultNotification(BaseModel):
event_ids: List[str]
"""Array of event IDs associated with this notification"""
- note: str
-
routing: "MessageRouting"
topic_id: str
updated_at: int
+ note: Optional[str] = None
+
tags: Optional[ResultNotificationTags] = None
title: Optional[str] = None
diff --git a/src/courier/types/notification_template_get_response.py b/src/courier/types/notification_template_response.py
similarity index 78%
rename from src/courier/types/notification_template_get_response.py
rename to src/courier/types/notification_template_response.py
index 8ec0009..823a6c4 100644
--- a/src/courier/types/notification_template_get_response.py
+++ b/src/courier/types/notification_template_response.py
@@ -6,7 +6,7 @@
from .._models import BaseModel
from .notification_template_payload import NotificationTemplatePayload
-__all__ = ["NotificationTemplateGetResponse", "Notification"]
+__all__ = ["NotificationTemplateResponse", "Notification"]
class Notification(NotificationTemplatePayload):
@@ -18,10 +18,9 @@ class Notification(NotificationTemplatePayload):
"""The template ID."""
-class NotificationTemplateGetResponse(BaseModel):
- """Envelope response for GET /notifications/{id}.
-
- The notification object mirrors the POST/PUT input shape. Nullable fields return null when unset.
+class NotificationTemplateResponse(BaseModel):
+ """
+ Response for GET /notifications/{id}, POST /notifications, and PUT /notifications/{id}. Wraps the template payload inside a `notification` key alongside metadata.
"""
created: int
diff --git a/tests/api_resources/test_notifications.py b/tests/api_resources/test_notifications.py
index 145a34b..f048b24 100644
--- a/tests/api_resources/test_notifications.py
+++ b/tests/api_resources/test_notifications.py
@@ -11,7 +11,7 @@
from tests.utils import assert_matches_type
from courier.types import (
NotificationListResponse,
- NotificationTemplateGetResponse,
+ NotificationTemplateResponse,
NotificationContentMutationResponse,
NotificationRetrieveContentResponse,
NotificationTemplateVersionListResponse,
@@ -39,7 +39,7 @@ def test_method_create(self, client: Courier) -> None:
"tags": ["onboarding", "welcome"],
},
)
- assert_matches_type(NotificationTemplateGetResponse, notification, path=["response"])
+ assert_matches_type(NotificationTemplateResponse, notification, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -58,7 +58,7 @@ def test_method_create_with_all_params(self, client: Courier) -> None:
},
state="DRAFT",
)
- assert_matches_type(NotificationTemplateGetResponse, notification, path=["response"])
+ assert_matches_type(NotificationTemplateResponse, notification, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -80,7 +80,7 @@ def test_raw_response_create(self, client: Courier) -> None:
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
notification = response.parse()
- assert_matches_type(NotificationTemplateGetResponse, notification, path=["response"])
+ assert_matches_type(NotificationTemplateResponse, notification, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -102,7 +102,7 @@ def test_streaming_response_create(self, client: Courier) -> None:
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
notification = response.parse()
- assert_matches_type(NotificationTemplateGetResponse, notification, path=["response"])
+ assert_matches_type(NotificationTemplateResponse, notification, path=["response"])
assert cast(Any, response.is_closed) is True
@@ -112,7 +112,7 @@ def test_method_retrieve(self, client: Courier) -> None:
notification = client.notifications.retrieve(
id="id",
)
- assert_matches_type(NotificationTemplateGetResponse, notification, path=["response"])
+ assert_matches_type(NotificationTemplateResponse, notification, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -121,7 +121,7 @@ def test_method_retrieve_with_all_params(self, client: Courier) -> None:
id="id",
version="version",
)
- assert_matches_type(NotificationTemplateGetResponse, notification, path=["response"])
+ assert_matches_type(NotificationTemplateResponse, notification, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -133,7 +133,7 @@ def test_raw_response_retrieve(self, client: Courier) -> None:
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
notification = response.parse()
- assert_matches_type(NotificationTemplateGetResponse, notification, path=["response"])
+ assert_matches_type(NotificationTemplateResponse, notification, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -145,7 +145,7 @@ def test_streaming_response_retrieve(self, client: Courier) -> None:
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
notification = response.parse()
- assert_matches_type(NotificationTemplateGetResponse, notification, path=["response"])
+ assert_matches_type(NotificationTemplateResponse, notification, path=["response"])
assert cast(Any, response.is_closed) is True
@@ -557,7 +557,7 @@ def test_method_replace(self, client: Courier) -> None:
"tags": ["updated"],
},
)
- assert_matches_type(NotificationTemplateGetResponse, notification, path=["response"])
+ assert_matches_type(NotificationTemplateResponse, notification, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -577,7 +577,7 @@ def test_method_replace_with_all_params(self, client: Courier) -> None:
},
state="PUBLISHED",
)
- assert_matches_type(NotificationTemplateGetResponse, notification, path=["response"])
+ assert_matches_type(NotificationTemplateResponse, notification, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -600,7 +600,7 @@ def test_raw_response_replace(self, client: Courier) -> None:
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
notification = response.parse()
- assert_matches_type(NotificationTemplateGetResponse, notification, path=["response"])
+ assert_matches_type(NotificationTemplateResponse, notification, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -623,7 +623,7 @@ def test_streaming_response_replace(self, client: Courier) -> None:
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
notification = response.parse()
- assert_matches_type(NotificationTemplateGetResponse, notification, path=["response"])
+ assert_matches_type(NotificationTemplateResponse, notification, path=["response"])
assert cast(Any, response.is_closed) is True
@@ -719,7 +719,7 @@ async def test_method_create(self, async_client: AsyncCourier) -> None:
"tags": ["onboarding", "welcome"],
},
)
- assert_matches_type(NotificationTemplateGetResponse, notification, path=["response"])
+ assert_matches_type(NotificationTemplateResponse, notification, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -738,7 +738,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncCourier) -
},
state="DRAFT",
)
- assert_matches_type(NotificationTemplateGetResponse, notification, path=["response"])
+ assert_matches_type(NotificationTemplateResponse, notification, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -760,7 +760,7 @@ async def test_raw_response_create(self, async_client: AsyncCourier) -> None:
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
notification = await response.parse()
- assert_matches_type(NotificationTemplateGetResponse, notification, path=["response"])
+ assert_matches_type(NotificationTemplateResponse, notification, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -782,7 +782,7 @@ async def test_streaming_response_create(self, async_client: AsyncCourier) -> No
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
notification = await response.parse()
- assert_matches_type(NotificationTemplateGetResponse, notification, path=["response"])
+ assert_matches_type(NotificationTemplateResponse, notification, path=["response"])
assert cast(Any, response.is_closed) is True
@@ -792,7 +792,7 @@ async def test_method_retrieve(self, async_client: AsyncCourier) -> None:
notification = await async_client.notifications.retrieve(
id="id",
)
- assert_matches_type(NotificationTemplateGetResponse, notification, path=["response"])
+ assert_matches_type(NotificationTemplateResponse, notification, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -801,7 +801,7 @@ async def test_method_retrieve_with_all_params(self, async_client: AsyncCourier)
id="id",
version="version",
)
- assert_matches_type(NotificationTemplateGetResponse, notification, path=["response"])
+ assert_matches_type(NotificationTemplateResponse, notification, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -813,7 +813,7 @@ async def test_raw_response_retrieve(self, async_client: AsyncCourier) -> None:
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
notification = await response.parse()
- assert_matches_type(NotificationTemplateGetResponse, notification, path=["response"])
+ assert_matches_type(NotificationTemplateResponse, notification, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -825,7 +825,7 @@ async def test_streaming_response_retrieve(self, async_client: AsyncCourier) ->
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
notification = await response.parse()
- assert_matches_type(NotificationTemplateGetResponse, notification, path=["response"])
+ assert_matches_type(NotificationTemplateResponse, notification, path=["response"])
assert cast(Any, response.is_closed) is True
@@ -1237,7 +1237,7 @@ async def test_method_replace(self, async_client: AsyncCourier) -> None:
"tags": ["updated"],
},
)
- assert_matches_type(NotificationTemplateGetResponse, notification, path=["response"])
+ assert_matches_type(NotificationTemplateResponse, notification, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -1257,7 +1257,7 @@ async def test_method_replace_with_all_params(self, async_client: AsyncCourier)
},
state="PUBLISHED",
)
- assert_matches_type(NotificationTemplateGetResponse, notification, path=["response"])
+ assert_matches_type(NotificationTemplateResponse, notification, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -1280,7 +1280,7 @@ async def test_raw_response_replace(self, async_client: AsyncCourier) -> None:
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
notification = await response.parse()
- assert_matches_type(NotificationTemplateGetResponse, notification, path=["response"])
+ assert_matches_type(NotificationTemplateResponse, notification, path=["response"])
@pytest.mark.skip(reason="Mock server tests are disabled")
@parametrize
@@ -1303,7 +1303,7 @@ async def test_streaming_response_replace(self, async_client: AsyncCourier) -> N
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
notification = await response.parse()
- assert_matches_type(NotificationTemplateGetResponse, notification, path=["response"])
+ assert_matches_type(NotificationTemplateResponse, notification, path=["response"])
assert cast(Any, response.is_closed) is True
From de82b206f9d038b259de06360a6e52420c97c156 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 14 Apr 2026 16:54:39 +0000
Subject: [PATCH 2/3] fix(types): flatten NotificationTemplateResponse
structure
---
.stats.yml | 4 ++--
.../resources/notifications/notifications.py | 16 ++++++++--------
.../types/notification_create_params.py | 4 ++--
.../types/notification_replace_params.py | 4 ++--
.../types/notification_template_payload.py | 2 +-
.../notification_template_payload_param.py | 2 +-
.../types/notification_template_response.py | 19 +++----------------
7 files changed, 19 insertions(+), 32 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 998581c..effa635 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 103
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/courier%2Fcourier-0f56d7860a1be3ffaea5dea291b20ac92e31c94d54e41cc8a30462dacf2f2d37.yml
-openapi_spec_hash: 7e7c6f963e83c5f626c09efa322f476a
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/courier%2Fcourier-3f78581b4e078a1f620d9f587f18d77bcde6d20f56b0e4ae798648f4236494fb.yml
+openapi_spec_hash: 6bd33e0396d85e11bb46f0d549af93a3
config_hash: afcc4f6f8c33ca3f338589e32e086f56
diff --git a/src/courier/resources/notifications/notifications.py b/src/courier/resources/notifications/notifications.py
index f12be4b..bb0dd50 100644
--- a/src/courier/resources/notifications/notifications.py
+++ b/src/courier/resources/notifications/notifications.py
@@ -92,8 +92,8 @@ def create(
Templates are created in draft state by default.
Args:
- notification: Full document shape used in POST and PUT request bodies, and returned inside the
- GET response envelope.
+ notification: Core template fields used in POST and PUT request bodies (nested under a
+ `notification` key) and returned at the top level in responses.
state: Template state after creation. Case-insensitive input, normalized to uppercase
in the response. Defaults to "DRAFT".
@@ -517,8 +517,8 @@ def replace(
All fields are required.
Args:
- notification: Full document shape used in POST and PUT request bodies, and returned inside the
- GET response envelope.
+ notification: Core template fields used in POST and PUT request bodies (nested under a
+ `notification` key) and returned at the top level in responses.
state: Template state after update. Case-insensitive input, normalized to uppercase in
the response. Defaults to "DRAFT".
@@ -643,8 +643,8 @@ async def create(
Templates are created in draft state by default.
Args:
- notification: Full document shape used in POST and PUT request bodies, and returned inside the
- GET response envelope.
+ notification: Core template fields used in POST and PUT request bodies (nested under a
+ `notification` key) and returned at the top level in responses.
state: Template state after creation. Case-insensitive input, normalized to uppercase
in the response. Defaults to "DRAFT".
@@ -1072,8 +1072,8 @@ async def replace(
All fields are required.
Args:
- notification: Full document shape used in POST and PUT request bodies, and returned inside the
- GET response envelope.
+ notification: Core template fields used in POST and PUT request bodies (nested under a
+ `notification` key) and returned at the top level in responses.
state: Template state after update. Case-insensitive input, normalized to uppercase in
the response. Defaults to "DRAFT".
diff --git a/src/courier/types/notification_create_params.py b/src/courier/types/notification_create_params.py
index b64d3a1..242017c 100644
--- a/src/courier/types/notification_create_params.py
+++ b/src/courier/types/notification_create_params.py
@@ -12,8 +12,8 @@
class NotificationCreateParams(TypedDict, total=False):
notification: Required[NotificationTemplatePayloadParam]
"""
- Full document shape used in POST and PUT request bodies, and returned inside the
- GET response envelope.
+ Core template fields used in POST and PUT request bodies (nested under a
+ `notification` key) and returned at the top level in responses.
"""
state: Literal["DRAFT", "PUBLISHED"]
diff --git a/src/courier/types/notification_replace_params.py b/src/courier/types/notification_replace_params.py
index e48eb1b..5ee1d7d 100644
--- a/src/courier/types/notification_replace_params.py
+++ b/src/courier/types/notification_replace_params.py
@@ -12,8 +12,8 @@
class NotificationReplaceParams(TypedDict, total=False):
notification: Required[NotificationTemplatePayloadParam]
"""
- Full document shape used in POST and PUT request bodies, and returned inside the
- GET response envelope.
+ Core template fields used in POST and PUT request bodies (nested under a
+ `notification` key) and returned at the top level in responses.
"""
state: Literal["DRAFT", "PUBLISHED"]
diff --git a/src/courier/types/notification_template_payload.py b/src/courier/types/notification_template_payload.py
index dd6d89f..379534b 100644
--- a/src/courier/types/notification_template_payload.py
+++ b/src/courier/types/notification_template_payload.py
@@ -28,7 +28,7 @@ class Subscription(BaseModel):
class NotificationTemplatePayload(BaseModel):
"""
- Full document shape used in POST and PUT request bodies, and returned inside the GET response envelope.
+ Core template fields used in POST and PUT request bodies (nested under a `notification` key) and returned at the top level in responses.
"""
brand: Optional[Brand] = None
diff --git a/src/courier/types/notification_template_payload_param.py b/src/courier/types/notification_template_payload_param.py
index 258eb93..52f321d 100644
--- a/src/courier/types/notification_template_payload_param.py
+++ b/src/courier/types/notification_template_payload_param.py
@@ -31,7 +31,7 @@ class Subscription(TypedDict, total=False):
class NotificationTemplatePayloadParam(TypedDict, total=False):
"""
- Full document shape used in POST and PUT request bodies, and returned inside the GET response envelope.
+ Core template fields used in POST and PUT request bodies (nested under a `notification` key) and returned at the top level in responses.
"""
brand: Required[Optional[Brand]]
diff --git a/src/courier/types/notification_template_response.py b/src/courier/types/notification_template_response.py
index 823a6c4..7d52ccf 100644
--- a/src/courier/types/notification_template_response.py
+++ b/src/courier/types/notification_template_response.py
@@ -3,38 +3,25 @@
from typing import Optional
from typing_extensions import Literal
-from .._models import BaseModel
from .notification_template_payload import NotificationTemplatePayload
-__all__ = ["NotificationTemplateResponse", "Notification"]
+__all__ = ["NotificationTemplateResponse"]
-class Notification(NotificationTemplatePayload):
+class NotificationTemplateResponse(NotificationTemplatePayload):
"""
- Full document shape used in POST and PUT request bodies, and returned inside the GET response envelope.
+ Response for GET /notifications/{id}, POST /notifications, and PUT /notifications/{id}. Returns all template fields at the top level.
"""
id: str
"""The template ID."""
-
-class NotificationTemplateResponse(BaseModel):
- """
- Response for GET /notifications/{id}, POST /notifications, and PUT /notifications/{id}. Wraps the template payload inside a `notification` key alongside metadata.
- """
-
created: int
"""Epoch milliseconds when the template was created."""
creator: str
"""User ID of the creator."""
- notification: Notification
- """
- Full document shape used in POST and PUT request bodies, and returned inside the
- GET response envelope.
- """
-
state: Literal["DRAFT", "PUBLISHED"]
"""The template state. Always uppercase."""
From 97e7d31b80ea3b23389cf1ec62c73835f466e806 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 14 Apr 2026 16:55:03 +0000
Subject: [PATCH 3/3] release: 7.11.2
---
.release-please-manifest.json | 2 +-
CHANGELOG.md | 9 +++++++++
pyproject.toml | 2 +-
src/courier/_version.py | 2 +-
4 files changed, 12 insertions(+), 3 deletions(-)
diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index e8175f5..46da4bb 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "7.11.1"
+ ".": "7.11.2"
}
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 12e7bb5..fb710bf 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,14 @@
# Changelog
+## 7.11.2 (2026-04-14)
+
+Full Changelog: [v7.11.1...v7.11.2](https://github.com/trycourier/courier-python/compare/v7.11.1...v7.11.2)
+
+### Bug Fixes
+
+* **types:** flatten NotificationTemplateResponse structure ([de82b20](https://github.com/trycourier/courier-python/commit/de82b206f9d038b259de06360a6e52420c97c156))
+* **types:** make note optional in ResultNotification, flatten template response ([b7dc001](https://github.com/trycourier/courier-python/commit/b7dc001d77e093a2d93b4c8e7b7c93f5b4518edd))
+
## 7.11.1 (2026-04-13)
Full Changelog: [v7.11.0...v7.11.1](https://github.com/trycourier/courier-python/compare/v7.11.0...v7.11.1)
diff --git a/pyproject.toml b/pyproject.toml
index f23035e..6402835 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "trycourier"
-version = "7.11.1"
+version = "7.11.2"
description = "The official Python library for the Courier API"
dynamic = ["readme"]
license = "Apache-2.0"
diff --git a/src/courier/_version.py b/src/courier/_version.py
index a93f7c7..73243ee 100644
--- a/src/courier/_version.py
+++ b/src/courier/_version.py
@@ -1,4 +1,4 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
__title__ = "courier"
-__version__ = "7.11.1" # x-release-please-version
+__version__ = "7.11.2" # x-release-please-version