diff --git a/src/lettermint/endpoints/api.py b/src/lettermint/endpoints/api.py index 1b10503..8d52cc3 100644 --- a/src/lettermint/endpoints/api.py +++ b/src/lettermint/endpoints/api.py @@ -96,6 +96,14 @@ def cancel(self, message_id: str) -> lm_types.RescheduleMessageResponse: ), ) + def process(self, message_id: str) -> lm_types.ProcessInboundMessageResponse: + return cast( + lm_types.ProcessInboundMessageResponse, + self._client.post( + self._path("/messages/{messageId}/process", messageId=message_id), data={} + ), + ) + def events(self, message_id: str, query: Query | None = None) -> lm_types.MessageEventsResponse: return cast( lm_types.MessageEventsResponse, @@ -374,6 +382,14 @@ async def cancel(self, message_id: str) -> lm_types.RescheduleMessageResponse: ), ) + async def process(self, message_id: str) -> lm_types.ProcessInboundMessageResponse: + return cast( + lm_types.ProcessInboundMessageResponse, + await self._client.post( + self._path("/messages/{messageId}/process", messageId=message_id), data={} + ), + ) + async def delete(self, domain_id: str) -> lm_types.DomainDestroyResponse: return cast( lm_types.DomainDestroyResponse, diff --git a/src/lettermint/types.py b/src/lettermint/types.py index 9768eae..4b012f5 100644 --- a/src/lettermint/types.py +++ b/src/lettermint/types.py @@ -10,6 +10,7 @@ "scheduled", "pending", "queued", + "quarantined", "suppressed", "processed", "delivered", @@ -194,6 +195,7 @@ "inbound_received", "inbound_queued", "inbound_spam_blocked", + "inbound_released", "inbound_processed", "inbound_retry", ] @@ -885,6 +887,12 @@ ) MessageShowResponse: TypeAlias = MessageData +ProcessInboundMessageResponse = TypedDict( + "ProcessInboundMessageResponse", + { + "data": "Required[dict[str, str | int]]", + }, +) MessageEventsResponse = TypedDict( "MessageEventsResponse", { diff --git a/tests/test_api_surface.py b/tests/test_api_surface.py index e00bdaf..91746c5 100644 --- a/tests/test_api_surface.py +++ b/tests/test_api_surface.py @@ -186,6 +186,9 @@ def test_scheduled_message_endpoints(self) -> None: 200, json={"message_id": "message/id", "status": "canceled", "scheduled_at": None} ) ) + process_route = respx.post("https://api.lettermint.co/v1/messages/message%2Fid/process").mock( + return_value=Response(202, json={"data": {"message_id": "message/id", "status": "queued", "webhook_target_count": 1}}) + ) with Lettermint.api("api-token") as api: assert ( @@ -195,11 +198,13 @@ def test_scheduled_message_endpoints(self) -> None: == "scheduled" ) assert api.messages.cancel("message/id")["status"] == "canceled" + assert api.messages.process("message/id")["data"]["status"] == "queued" assert json.loads(reschedule_route.calls.last.request.content) == { "scheduled_at": "2026-08-27T09:00:00Z" } assert cancel_route.called + assert process_route.called @respx.mock def test_team_role_and_member_assignment_endpoints(self) -> None: @@ -244,6 +249,7 @@ def test_documented_operations_are_exposed(self) -> None: (Lettermint.api("token").messages, "retrieve"), (Lettermint.api("token").messages, "reschedule"), (Lettermint.api("token").messages, "cancel"), + (Lettermint.api("token").messages, "process"), (Lettermint.api("token").messages, "events"), (Lettermint.api("token").messages, "source"), (Lettermint.api("token").messages, "html"),