From 044758a95673f15a0a7b01b3021ff0359ef6c5bd Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 29 Jul 2026 20:44:15 +0000 Subject: [PATCH 1/3] feat: spec: reorder API reference sections to match the Studio nav (#180) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Follow-up to #179, rebased onto the Broadcasts merge (#170). Three changes to `specs/openapi.yml`: 1. **Reorders the sections** so the API reference reads in the same order as the Studio left nav — Content (Templates, Brands, Routing) → Orchestration (Journeys, Broadcasts) → Directory (Users, Tenants, Audiences, Lists) → Platform (Providers, Preferences) — with Send first and everything that has no nav home below. 2. **Declares the missing `Broadcasts` tag.** #170 added 11 Broadcasts operations but no entry in the top-level `tags:` array, so they were rendering as an undeclared group at the end of the sidebar, and the paths themselves sat inside the Templates section. They now have their own section, in the Studio nav's position right after Journeys. 3. **Renames `Profiles` → `User Profiles`**, matching the endpoints under it and the "user profile" language used everywhere else in the docs. Authentication moves off the top to the bottom: it is one endpoint that only client-side SDKs call, so it was crowding out Send. New order: Send · Templates · Brands · Routing Strategies · Journeys · Broadcasts · User Profiles · Tenants · Audiences · Lists · Providers · Preference Topics · User Preferences then, below the fold: Messages · Device Tokens · Tenant Memberships · Tenant Templates · Automations · Digests · Translations · Inbox · Track Events · Audit Events · Authentication Verified mechanical: parsing the spec before and after shows 85 paths and 147 operations in both, zero operation-body differences, and the only semantic changes are the `Profiles` → `User Profiles` tag on the 8 `/profiles/*` operations and the added `Broadcasts` tag declaration. `components:`, `servers:`, `info:`, and `security:` are unchanged, as are all 23 pre-existing tag descriptions. Every tag an operation carries is now declared, and every declared tag is used. No SDK surface is affected — Stainless resources come from `stainless.yml`, which this PR does not touch. Renaming the section changes its API reference slugs, so the docs side needs `/api-reference/profiles/*` → `/api-reference/user-profiles/*` redirects. Co-authored-by: Claude Opus 5 (1M context) --- .stats.yml | 4 ++-- src/courier/_client.py | 18 ++++++++++++++++++ src/courier/resources/broadcasts.py | 8 ++++++++ 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 29ea7c7..a3e38b1 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 147 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/courier/courier-ca32540df5bca42c8113de4004e7751b74bb440e3d73267e7cbad84dd3c3e82a.yml -openapi_spec_hash: 5576c8cf8e5be1f250b5dd1eb6d30571 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/courier/courier-8d00597aee6759fa5829bdf61637a9d5f6abf7b4826cb2c7b8af491771dca0e9.yml +openapi_spec_hash: 1766885553f6733706f8a807b1e8c31b config_hash: c6cefb51165221f01d442a42ac4a13b9 diff --git a/src/courier/_client.py b/src/courier/_client.py index b6797bf..b34b36e 100644 --- a/src/courier/_client.py +++ b/src/courier/_client.py @@ -215,6 +215,9 @@ def journeys(self) -> JourneysResource: @cached_property def broadcasts(self) -> BroadcastsResource: + """ + Create a one-off send to a list or audience, author its content, then send it immediately or schedule it for later. + """ from .resources.broadcasts import BroadcastsResource return BroadcastsResource(self) @@ -576,6 +579,9 @@ def journeys(self) -> AsyncJourneysResource: @cached_property def broadcasts(self) -> AsyncBroadcastsResource: + """ + Create a one-off send to a list or audience, author its content, then send it immediately or schedule it for later. + """ from .resources.broadcasts import AsyncBroadcastsResource return AsyncBroadcastsResource(self) @@ -879,6 +885,9 @@ def journeys(self) -> journeys.JourneysResourceWithRawResponse: @cached_property def broadcasts(self) -> broadcasts.BroadcastsResourceWithRawResponse: + """ + Create a one-off send to a list or audience, author its content, then send it immediately or schedule it for later. + """ from .resources.broadcasts import BroadcastsResourceWithRawResponse return BroadcastsResourceWithRawResponse(self._client.broadcasts) @@ -1070,6 +1079,9 @@ def journeys(self) -> journeys.AsyncJourneysResourceWithRawResponse: @cached_property def broadcasts(self) -> broadcasts.AsyncBroadcastsResourceWithRawResponse: + """ + Create a one-off send to a list or audience, author its content, then send it immediately or schedule it for later. + """ from .resources.broadcasts import AsyncBroadcastsResourceWithRawResponse return AsyncBroadcastsResourceWithRawResponse(self._client.broadcasts) @@ -1261,6 +1273,9 @@ def journeys(self) -> journeys.JourneysResourceWithStreamingResponse: @cached_property def broadcasts(self) -> broadcasts.BroadcastsResourceWithStreamingResponse: + """ + Create a one-off send to a list or audience, author its content, then send it immediately or schedule it for later. + """ from .resources.broadcasts import BroadcastsResourceWithStreamingResponse return BroadcastsResourceWithStreamingResponse(self._client.broadcasts) @@ -1452,6 +1467,9 @@ def journeys(self) -> journeys.AsyncJourneysResourceWithStreamingResponse: @cached_property def broadcasts(self) -> broadcasts.AsyncBroadcastsResourceWithStreamingResponse: + """ + Create a one-off send to a list or audience, author its content, then send it immediately or schedule it for later. + """ from .resources.broadcasts import AsyncBroadcastsResourceWithStreamingResponse return AsyncBroadcastsResourceWithStreamingResponse(self._client.broadcasts) diff --git a/src/courier/resources/broadcasts.py b/src/courier/resources/broadcasts.py index 0465e10..aa55c88 100644 --- a/src/courier/resources/broadcasts.py +++ b/src/courier/resources/broadcasts.py @@ -38,6 +38,10 @@ class BroadcastsResource(SyncAPIResource): + """ + Create a one-off send to a list or audience, author its content, then send it immediately or schedule it for later. + """ + @cached_property def with_raw_response(self) -> BroadcastsResourceWithRawResponse: """ @@ -529,6 +533,10 @@ def send( class AsyncBroadcastsResource(AsyncAPIResource): + """ + Create a one-off send to a list or audience, author its content, then send it immediately or schedule it for later. + """ + @cached_property def with_raw_response(self) -> AsyncBroadcastsResourceWithRawResponse: """ From dfdc63d3d184091ddc3f81a851aa156d43f6b61e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 30 Jul 2026 17:24:23 +0000 Subject: [PATCH 2/3] feat: spec: remove inbox message delete/restore endpoints for now (C-19268) (#182) Reverts the public documentation of DELETE /inbox/messages/{message_id} and PUT /inbox/messages/{message_id}/restore (added in #175). The server-side delete endpoint authenticates and returns 204, but the soft-delete is not reflected in the inbox read path the SDK/clients use (deleted messages still appear in the in-app inbox). Pulling the endpoints from the public API surface + SDK generation until the read-path issue is resolved. Removes: - openapi.yml: both paths + the Inbox tag (only used by these two operations) - stainless.yml: the inbox.messages resource (delete + restore) Co-authored-by: Mike Miller Co-authored-by: Claude Opus 4.8 --- .stats.yml | 8 +- api.md | 9 - src/courier/_client.py | 38 ---- src/courier/resources/__init__.py | 14 -- src/courier/resources/inbox/__init__.py | 33 --- src/courier/resources/inbox/inbox.py | 108 --------- src/courier/resources/inbox/messages.py | 253 --------------------- src/courier/types/inbox/__init__.py | 3 - tests/api_resources/inbox/__init__.py | 1 - tests/api_resources/inbox/test_messages.py | 190 ---------------- 10 files changed, 4 insertions(+), 653 deletions(-) delete mode 100644 src/courier/resources/inbox/__init__.py delete mode 100644 src/courier/resources/inbox/inbox.py delete mode 100644 src/courier/resources/inbox/messages.py delete mode 100644 src/courier/types/inbox/__init__.py delete mode 100644 tests/api_resources/inbox/__init__.py delete mode 100644 tests/api_resources/inbox/test_messages.py diff --git a/.stats.yml b/.stats.yml index a3e38b1..06502c4 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 147 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/courier/courier-8d00597aee6759fa5829bdf61637a9d5f6abf7b4826cb2c7b8af491771dca0e9.yml -openapi_spec_hash: 1766885553f6733706f8a807b1e8c31b -config_hash: c6cefb51165221f01d442a42ac4a13b9 +configured_endpoints: 145 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/courier/courier-b4485f5c4897c26d52a46aeb39b8a22415bcd529b0ad326fd43a30d7fadf1376.yml +openapi_spec_hash: db619c8991994dc8016fc4327f6917a2 +config_hash: 3eb0070d128aef7a6da16173f7050177 diff --git a/api.md b/api.md index 4603c9d..856a963 100644 --- a/api.md +++ b/api.md @@ -385,15 +385,6 @@ Methods: - client.lists.subscriptions.subscribe_user(user_id, \*, list_id, \*\*params) -> None - client.lists.subscriptions.unsubscribe_user(user_id, \*, list_id) -> None -# Inbox - -## Messages - -Methods: - -- client.inbox.messages.delete(message_id) -> None -- client.inbox.messages.restore(message_id) -> None - # Messages Types: diff --git a/src/courier/_client.py b/src/courier/_client.py index b34b36e..f548a44 100644 --- a/src/courier/_client.py +++ b/src/courier/_client.py @@ -38,7 +38,6 @@ from .resources import ( auth, send, - inbox, lists, users, brands, @@ -67,7 +66,6 @@ from .resources.requests import RequestsResource, AsyncRequestsResource from .resources.audiences import AudiencesResource, AsyncAudiencesResource from .resources.broadcasts import BroadcastsResource, AsyncBroadcastsResource - from .resources.inbox.inbox import InboxResource, AsyncInboxResource from .resources.lists.lists import ListsResource, AsyncListsResource from .resources.users.users import UsersResource, AsyncUsersResource from .resources.audit_events import AuditEventsResource, AsyncAuditEventsResource @@ -255,12 +253,6 @@ def lists(self) -> ListsResource: return ListsResource(self) - @cached_property - def inbox(self) -> InboxResource: - from .resources.inbox import InboxResource - - return InboxResource(self) - @cached_property def messages(self) -> MessagesResource: """ @@ -619,12 +611,6 @@ def lists(self) -> AsyncListsResource: return AsyncListsResource(self) - @cached_property - def inbox(self) -> AsyncInboxResource: - from .resources.inbox import AsyncInboxResource - - return AsyncInboxResource(self) - @cached_property def messages(self) -> AsyncMessagesResource: """ @@ -925,12 +911,6 @@ def lists(self) -> lists.ListsResourceWithRawResponse: return ListsResourceWithRawResponse(self._client.lists) - @cached_property - def inbox(self) -> inbox.InboxResourceWithRawResponse: - from .resources.inbox import InboxResourceWithRawResponse - - return InboxResourceWithRawResponse(self._client.inbox) - @cached_property def messages(self) -> messages.MessagesResourceWithRawResponse: """ @@ -1119,12 +1099,6 @@ def lists(self) -> lists.AsyncListsResourceWithRawResponse: return AsyncListsResourceWithRawResponse(self._client.lists) - @cached_property - def inbox(self) -> inbox.AsyncInboxResourceWithRawResponse: - from .resources.inbox import AsyncInboxResourceWithRawResponse - - return AsyncInboxResourceWithRawResponse(self._client.inbox) - @cached_property def messages(self) -> messages.AsyncMessagesResourceWithRawResponse: """ @@ -1313,12 +1287,6 @@ def lists(self) -> lists.ListsResourceWithStreamingResponse: return ListsResourceWithStreamingResponse(self._client.lists) - @cached_property - def inbox(self) -> inbox.InboxResourceWithStreamingResponse: - from .resources.inbox import InboxResourceWithStreamingResponse - - return InboxResourceWithStreamingResponse(self._client.inbox) - @cached_property def messages(self) -> messages.MessagesResourceWithStreamingResponse: """ @@ -1507,12 +1475,6 @@ def lists(self) -> lists.AsyncListsResourceWithStreamingResponse: return AsyncListsResourceWithStreamingResponse(self._client.lists) - @cached_property - def inbox(self) -> inbox.AsyncInboxResourceWithStreamingResponse: - from .resources.inbox import AsyncInboxResourceWithStreamingResponse - - return AsyncInboxResourceWithStreamingResponse(self._client.inbox) - @cached_property def messages(self) -> messages.AsyncMessagesResourceWithStreamingResponse: """ diff --git a/src/courier/resources/__init__.py b/src/courier/resources/__init__.py index 1528692..036149d 100644 --- a/src/courier/resources/__init__.py +++ b/src/courier/resources/__init__.py @@ -16,14 +16,6 @@ SendResourceWithStreamingResponse, AsyncSendResourceWithStreamingResponse, ) -from .inbox import ( - InboxResource, - AsyncInboxResource, - InboxResourceWithRawResponse, - AsyncInboxResourceWithRawResponse, - InboxResourceWithStreamingResponse, - AsyncInboxResourceWithStreamingResponse, -) from .lists import ( ListsResource, AsyncListsResource, @@ -250,12 +242,6 @@ "AsyncListsResourceWithRawResponse", "ListsResourceWithStreamingResponse", "AsyncListsResourceWithStreamingResponse", - "InboxResource", - "AsyncInboxResource", - "InboxResourceWithRawResponse", - "AsyncInboxResourceWithRawResponse", - "InboxResourceWithStreamingResponse", - "AsyncInboxResourceWithStreamingResponse", "MessagesResource", "AsyncMessagesResource", "MessagesResourceWithRawResponse", diff --git a/src/courier/resources/inbox/__init__.py b/src/courier/resources/inbox/__init__.py deleted file mode 100644 index 13574c1..0000000 --- a/src/courier/resources/inbox/__init__.py +++ /dev/null @@ -1,33 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from .inbox import ( - InboxResource, - AsyncInboxResource, - InboxResourceWithRawResponse, - AsyncInboxResourceWithRawResponse, - InboxResourceWithStreamingResponse, - AsyncInboxResourceWithStreamingResponse, -) -from .messages import ( - MessagesResource, - AsyncMessagesResource, - MessagesResourceWithRawResponse, - AsyncMessagesResourceWithRawResponse, - MessagesResourceWithStreamingResponse, - AsyncMessagesResourceWithStreamingResponse, -) - -__all__ = [ - "MessagesResource", - "AsyncMessagesResource", - "MessagesResourceWithRawResponse", - "AsyncMessagesResourceWithRawResponse", - "MessagesResourceWithStreamingResponse", - "AsyncMessagesResourceWithStreamingResponse", - "InboxResource", - "AsyncInboxResource", - "InboxResourceWithRawResponse", - "AsyncInboxResourceWithRawResponse", - "InboxResourceWithStreamingResponse", - "AsyncInboxResourceWithStreamingResponse", -] diff --git a/src/courier/resources/inbox/inbox.py b/src/courier/resources/inbox/inbox.py deleted file mode 100644 index 4ab7084..0000000 --- a/src/courier/resources/inbox/inbox.py +++ /dev/null @@ -1,108 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from .messages import ( - MessagesResource, - AsyncMessagesResource, - MessagesResourceWithRawResponse, - AsyncMessagesResourceWithRawResponse, - MessagesResourceWithStreamingResponse, - AsyncMessagesResourceWithStreamingResponse, -) -from ..._compat import cached_property -from ..._resource import SyncAPIResource, AsyncAPIResource - -__all__ = ["InboxResource", "AsyncInboxResource"] - - -class InboxResource(SyncAPIResource): - @cached_property - def messages(self) -> MessagesResource: - """Manage the messages in a user's in-app inbox.""" - return MessagesResource(self._client) - - @cached_property - def with_raw_response(self) -> InboxResourceWithRawResponse: - """ - 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/trycourier/courier-python#accessing-raw-response-data-eg-headers - """ - return InboxResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> InboxResourceWithStreamingResponse: - """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. - - For more information, see https://www.github.com/trycourier/courier-python#with_streaming_response - """ - return InboxResourceWithStreamingResponse(self) - - -class AsyncInboxResource(AsyncAPIResource): - @cached_property - def messages(self) -> AsyncMessagesResource: - """Manage the messages in a user's in-app inbox.""" - return AsyncMessagesResource(self._client) - - @cached_property - def with_raw_response(self) -> AsyncInboxResourceWithRawResponse: - """ - 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/trycourier/courier-python#accessing-raw-response-data-eg-headers - """ - return AsyncInboxResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> AsyncInboxResourceWithStreamingResponse: - """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. - - For more information, see https://www.github.com/trycourier/courier-python#with_streaming_response - """ - return AsyncInboxResourceWithStreamingResponse(self) - - -class InboxResourceWithRawResponse: - def __init__(self, inbox: InboxResource) -> None: - self._inbox = inbox - - @cached_property - def messages(self) -> MessagesResourceWithRawResponse: - """Manage the messages in a user's in-app inbox.""" - return MessagesResourceWithRawResponse(self._inbox.messages) - - -class AsyncInboxResourceWithRawResponse: - def __init__(self, inbox: AsyncInboxResource) -> None: - self._inbox = inbox - - @cached_property - def messages(self) -> AsyncMessagesResourceWithRawResponse: - """Manage the messages in a user's in-app inbox.""" - return AsyncMessagesResourceWithRawResponse(self._inbox.messages) - - -class InboxResourceWithStreamingResponse: - def __init__(self, inbox: InboxResource) -> None: - self._inbox = inbox - - @cached_property - def messages(self) -> MessagesResourceWithStreamingResponse: - """Manage the messages in a user's in-app inbox.""" - return MessagesResourceWithStreamingResponse(self._inbox.messages) - - -class AsyncInboxResourceWithStreamingResponse: - def __init__(self, inbox: AsyncInboxResource) -> None: - self._inbox = inbox - - @cached_property - def messages(self) -> AsyncMessagesResourceWithStreamingResponse: - """Manage the messages in a user's in-app inbox.""" - return AsyncMessagesResourceWithStreamingResponse(self._inbox.messages) diff --git a/src/courier/resources/inbox/messages.py b/src/courier/resources/inbox/messages.py deleted file mode 100644 index 75bf3da..0000000 --- a/src/courier/resources/inbox/messages.py +++ /dev/null @@ -1,253 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -import httpx - -from ..._types import Body, Query, Headers, NoneType, NotGiven, not_given -from ..._utils import path_template -from ..._compat import cached_property -from ..._resource import SyncAPIResource, AsyncAPIResource -from ..._response import ( - to_raw_response_wrapper, - to_streamed_response_wrapper, - async_to_raw_response_wrapper, - async_to_streamed_response_wrapper, -) -from ..._base_client import make_request_options - -__all__ = ["MessagesResource", "AsyncMessagesResource"] - - -class MessagesResource(SyncAPIResource): - """Manage the messages in a user's in-app inbox.""" - - @cached_property - def with_raw_response(self) -> MessagesResourceWithRawResponse: - """ - 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/trycourier/courier-python#accessing-raw-response-data-eg-headers - """ - return MessagesResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> MessagesResourceWithStreamingResponse: - """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. - - For more information, see https://www.github.com/trycourier/courier-python#with_streaming_response - """ - return MessagesResourceWithStreamingResponse(self) - - def delete( - self, - message_id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> None: - """Delete a user's inbox message. - - The message is removed from every inbox read (it - stops appearing in the recipient's Inbox); it can be restored. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not message_id: - raise ValueError(f"Expected a non-empty value for `message_id` but received {message_id!r}") - extra_headers = {"Accept": "*/*", **(extra_headers or {})} - return self._delete( - path_template("/inbox/messages/{message_id}", message_id=message_id), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=NoneType, - ) - - def restore( - self, - message_id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> None: - """ - Restore a previously deleted inbox message. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not message_id: - raise ValueError(f"Expected a non-empty value for `message_id` but received {message_id!r}") - extra_headers = {"Accept": "*/*", **(extra_headers or {})} - return self._put( - path_template("/inbox/messages/{message_id}/restore", message_id=message_id), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=NoneType, - ) - - -class AsyncMessagesResource(AsyncAPIResource): - """Manage the messages in a user's in-app inbox.""" - - @cached_property - def with_raw_response(self) -> AsyncMessagesResourceWithRawResponse: - """ - 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/trycourier/courier-python#accessing-raw-response-data-eg-headers - """ - return AsyncMessagesResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> AsyncMessagesResourceWithStreamingResponse: - """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. - - For more information, see https://www.github.com/trycourier/courier-python#with_streaming_response - """ - return AsyncMessagesResourceWithStreamingResponse(self) - - async def delete( - self, - message_id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> None: - """Delete a user's inbox message. - - The message is removed from every inbox read (it - stops appearing in the recipient's Inbox); it can be restored. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not message_id: - raise ValueError(f"Expected a non-empty value for `message_id` but received {message_id!r}") - extra_headers = {"Accept": "*/*", **(extra_headers or {})} - return await self._delete( - path_template("/inbox/messages/{message_id}", message_id=message_id), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=NoneType, - ) - - async def restore( - self, - message_id: str, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> None: - """ - Restore a previously deleted inbox message. - - Args: - extra_headers: Send extra headers - - extra_query: Add additional query parameters to the request - - extra_body: Add additional JSON properties to the request - - timeout: Override the client-level default timeout for this request, in seconds - """ - if not message_id: - raise ValueError(f"Expected a non-empty value for `message_id` but received {message_id!r}") - extra_headers = {"Accept": "*/*", **(extra_headers or {})} - return await self._put( - path_template("/inbox/messages/{message_id}/restore", message_id=message_id), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=NoneType, - ) - - -class MessagesResourceWithRawResponse: - def __init__(self, messages: MessagesResource) -> None: - self._messages = messages - - self.delete = to_raw_response_wrapper( - messages.delete, - ) - self.restore = to_raw_response_wrapper( - messages.restore, - ) - - -class AsyncMessagesResourceWithRawResponse: - def __init__(self, messages: AsyncMessagesResource) -> None: - self._messages = messages - - self.delete = async_to_raw_response_wrapper( - messages.delete, - ) - self.restore = async_to_raw_response_wrapper( - messages.restore, - ) - - -class MessagesResourceWithStreamingResponse: - def __init__(self, messages: MessagesResource) -> None: - self._messages = messages - - self.delete = to_streamed_response_wrapper( - messages.delete, - ) - self.restore = to_streamed_response_wrapper( - messages.restore, - ) - - -class AsyncMessagesResourceWithStreamingResponse: - def __init__(self, messages: AsyncMessagesResource) -> None: - self._messages = messages - - self.delete = async_to_streamed_response_wrapper( - messages.delete, - ) - self.restore = async_to_streamed_response_wrapper( - messages.restore, - ) diff --git a/src/courier/types/inbox/__init__.py b/src/courier/types/inbox/__init__.py deleted file mode 100644 index f8ee8b1..0000000 --- a/src/courier/types/inbox/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations diff --git a/tests/api_resources/inbox/__init__.py b/tests/api_resources/inbox/__init__.py deleted file mode 100644 index fd8019a..0000000 --- a/tests/api_resources/inbox/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. diff --git a/tests/api_resources/inbox/test_messages.py b/tests/api_resources/inbox/test_messages.py deleted file mode 100644 index 129fbfe..0000000 --- a/tests/api_resources/inbox/test_messages.py +++ /dev/null @@ -1,190 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -import os -from typing import Any, cast - -import pytest - -from courier import Courier, AsyncCourier - -base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") - - -class TestMessages: - parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_method_delete(self, client: Courier) -> None: - message = client.inbox.messages.delete( - "message_id", - ) - assert message is None - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_raw_response_delete(self, client: Courier) -> None: - response = client.inbox.messages.with_raw_response.delete( - "message_id", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - message = response.parse() - assert message is None - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_streaming_response_delete(self, client: Courier) -> None: - with client.inbox.messages.with_streaming_response.delete( - "message_id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - message = response.parse() - assert message is None - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_path_params_delete(self, client: Courier) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `message_id` but received ''"): - client.inbox.messages.with_raw_response.delete( - "", - ) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_method_restore(self, client: Courier) -> None: - message = client.inbox.messages.restore( - "message_id", - ) - assert message is None - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_raw_response_restore(self, client: Courier) -> None: - response = client.inbox.messages.with_raw_response.restore( - "message_id", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - message = response.parse() - assert message is None - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_streaming_response_restore(self, client: Courier) -> None: - with client.inbox.messages.with_streaming_response.restore( - "message_id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - message = response.parse() - assert message is None - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - def test_path_params_restore(self, client: Courier) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `message_id` but received ''"): - client.inbox.messages.with_raw_response.restore( - "", - ) - - -class TestAsyncMessages: - parametrize = pytest.mark.parametrize( - "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] - ) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_method_delete(self, async_client: AsyncCourier) -> None: - message = await async_client.inbox.messages.delete( - "message_id", - ) - assert message is None - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_raw_response_delete(self, async_client: AsyncCourier) -> None: - response = await async_client.inbox.messages.with_raw_response.delete( - "message_id", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - message = await response.parse() - assert message is None - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_streaming_response_delete(self, async_client: AsyncCourier) -> None: - async with async_client.inbox.messages.with_streaming_response.delete( - "message_id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - message = await response.parse() - assert message is None - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_path_params_delete(self, async_client: AsyncCourier) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `message_id` but received ''"): - await async_client.inbox.messages.with_raw_response.delete( - "", - ) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_method_restore(self, async_client: AsyncCourier) -> None: - message = await async_client.inbox.messages.restore( - "message_id", - ) - assert message is None - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_raw_response_restore(self, async_client: AsyncCourier) -> None: - response = await async_client.inbox.messages.with_raw_response.restore( - "message_id", - ) - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - message = await response.parse() - assert message is None - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_streaming_response_restore(self, async_client: AsyncCourier) -> None: - async with async_client.inbox.messages.with_streaming_response.restore( - "message_id", - ) as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - message = await response.parse() - assert message is None - - assert cast(Any, response.is_closed) is True - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_path_params_restore(self, async_client: AsyncCourier) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `message_id` but received ''"): - await async_client.inbox.messages.with_raw_response.restore( - "", - ) From 4c7b0e1571d4be93728ccd2d835212a726582694 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 30 Jul 2026 17:24:44 +0000 Subject: [PATCH 3/3] release: 7.24.0 --- .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 821a1fc..c6500a3 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "7.23.0" + ".": "7.24.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 112e207..f03333e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +## 7.24.0 (2026-07-30) + +Full Changelog: [v7.23.0...v7.24.0](https://github.com/trycourier/courier-python/compare/v7.23.0...v7.24.0) + +### Features + +* spec: remove inbox message delete/restore endpoints for now (C-19268) ([#182](https://github.com/trycourier/courier-python/issues/182)) ([dfdc63d](https://github.com/trycourier/courier-python/commit/dfdc63d3d184091ddc3f81a851aa156d43f6b61e)) +* spec: reorder API reference sections to match the Studio nav ([#180](https://github.com/trycourier/courier-python/issues/180)) ([044758a](https://github.com/trycourier/courier-python/commit/044758a95673f15a0a7b01b3021ff0359ef6c5bd)) + ## 7.23.0 (2026-07-29) Full Changelog: [v7.22.0...v7.23.0](https://github.com/trycourier/courier-python/compare/v7.22.0...v7.23.0) diff --git a/pyproject.toml b/pyproject.toml index 1b672bf..fad6e6c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "trycourier" -version = "7.23.0" +version = "7.24.0" 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 3bba92e..dd757ad 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.23.0" # x-release-please-version +__version__ = "7.24.0" # x-release-please-version