From b632438052cb32ef06b933efc4c016dc3f348e1a Mon Sep 17 00:00:00 2001 From: Bjarn Bronsveld Date: Tue, 7 Jul 2026 22:41:30 +0200 Subject: [PATCH 1/3] Add latest Team API support --- src/lettermint/lettermint.py | 11 +- src/lettermint/types.py | 1096 +++++++++++++++++----------------- tests/test_api_surface.py | 42 ++ 3 files changed, 589 insertions(+), 560 deletions(-) diff --git a/src/lettermint/lettermint.py b/src/lettermint/lettermint.py index 5234663..bb23648 100644 --- a/src/lettermint/lettermint.py +++ b/src/lettermint/lettermint.py @@ -3,7 +3,7 @@ from __future__ import annotations import sys -from typing import Any +from typing import TYPE_CHECKING, Any if sys.version_info >= (3, 11): from typing import Self @@ -31,6 +31,9 @@ ) from .endpoints.email import AsyncEmailEndpoint, EmailEndpoint +if TYPE_CHECKING: + from . import types as lm_types + class _EmailAccessor: def __get__(self, instance: Lettermint | None, owner: type[Lettermint]) -> Any: @@ -87,6 +90,9 @@ def __exit__(self, *args: Any) -> None: def ping(self) -> str: return self._client.get_raw("/ping").strip() + def blocked_file_types(self) -> lm_types.BlockedFileTypesResponse: + return self._client.get("/blocked-file-types") + class AsyncApiClient: """Asynchronous client for the full Lettermint API.""" @@ -125,6 +131,9 @@ async def __aexit__(self, *args: Any) -> None: async def ping(self) -> str: return (await self._client.get_raw("/ping")).strip() + async def blocked_file_types(self) -> lm_types.BlockedFileTypesResponse: + return await self._client.get("/blocked-file-types") + class Lettermint: """Synchronous Lettermint SDK client. diff --git a/src/lettermint/types.py b/src/lettermint/types.py index 380f83c..fd39e75 100644 --- a/src/lettermint/types.py +++ b/src/lettermint/types.py @@ -6,664 +6,634 @@ from typing_extensions import NotRequired, Required, TypeAlias -MessageStatus: TypeAlias = Literal[ - "pending", - "queued", - "suppressed", - "processed", - "delivered", - "opened", - "clicked", - "soft_bounced", - "hard_bounced", - "spam_complaint", - "failed", - "blocked", - "policy_rejected", - "unsubscribed", -] +MessageStatus: TypeAlias = Literal['pending', 'queued', 'suppressed', 'processed', 'delivered', 'opened', 'clicked', 'soft_bounced', 'hard_bounced', 'spam_complaint', 'failed', 'blocked', 'policy_rejected', 'unsubscribed'] SendMailRequest = TypedDict( - "SendMailRequest", + 'SendMailRequest', { - "route": "NotRequired[str]", - "from": "Required[str]", - "subject": "Required[str]", - "tag": "NotRequired[str | None]", - "html": "NotRequired[str | None]", - "text": "NotRequired[str | None]", - "to": "Required[list[str]]", - "cc": "NotRequired[list[str]]", - "bcc": "NotRequired[list[str]]", - "reply_to": "NotRequired[list[str]]", - "headers": "NotRequired[dict[str, str]]", - "metadata": "NotRequired[dict[str, str]]", - "settings": "NotRequired[dict[str, Any] | None]", - "attachments": "NotRequired[list[dict[str, Any]]]", + 'route': 'NotRequired[str]', + 'from': 'Required[str]', + 'subject': 'Required[str]', + 'tag': 'NotRequired[str | None]', + 'html': 'NotRequired[str | None]', + 'text': 'NotRequired[str | None]', + 'to': 'Required[list[str]]', + 'cc': 'NotRequired[list[str]]', + 'bcc': 'NotRequired[list[str]]', + 'reply_to': 'NotRequired[list[str]]', + 'headers': 'NotRequired[dict[str, str]]', + 'metadata': 'NotRequired[dict[str, str]]', + 'settings': 'NotRequired[dict[str, Any] | None]', + 'attachments': 'NotRequired[list[dict[str, Any]]]', }, ) SendBatchMailRequest: TypeAlias = list[dict[str, Any]] -AttachmentDelivery: TypeAlias = Literal["inline", "url"] -DnsRecordStatus: TypeAlias = Literal["active", "failed", "pending"] -RecordType: TypeAlias = Literal["TXT", "CNAME", "MX"] +AttachmentDelivery: TypeAlias = Literal['inline', 'url'] +DnsRecordStatus: TypeAlias = Literal['active', 'failed', 'pending'] +RecordType: TypeAlias = Literal['TXT', 'CNAME', 'MX'] DomainDnsRecordData = TypedDict( - "DomainDnsRecordData", + 'DomainDnsRecordData', { - "id": "Required[str]", - "type": "Required[RecordType]", - "hostname": "Required[str]", - "fqdn": "Required[str]", - "content": "Required[str]", - "status": "Required[DnsRecordStatus]", - "verified_at": "Required[str | None]", - "last_checked_at": "Required[str | None]", + 'id': 'Required[str]', + 'type': 'Required[RecordType]', + 'hostname': 'Required[str]', + 'fqdn': 'Required[str]', + 'content': 'Required[str]', + 'status': 'Required[DnsRecordStatus]', + 'verified_at': 'Required[str | None]', + 'last_checked_at': 'Required[str | None]', }, ) DomainData = TypedDict( - "DomainData", + 'DomainData', { - "id": "Required[str]", - "domain": "Required[str]", - "status_changed_at": "Required[str | None]", - "dns_records": "NotRequired[list[DomainDnsRecordData]]", - "projects": "NotRequired[list[dict[str, Any]]]", - "created_at": "Required[str]", + 'id': 'Required[str]', + 'domain': 'Required[str]', + 'status_changed_at': 'Required[str | None]', + 'dns_records': 'NotRequired[list[DomainDnsRecordData]]', + 'projects': 'NotRequired[list[dict[str, Any]]]', + 'created_at': 'Required[str]', }, ) -DomainStatus: TypeAlias = Literal[ - "verified", "partially_verified", "pending_verification", "failed_verification" -] +DomainStatus: TypeAlias = Literal['verified', 'partially_verified', 'pending_verification', 'failed_verification'] DomainListData = TypedDict( - "DomainListData", + 'DomainListData', { - "id": "Required[str]", - "domain": "Required[str]", - "status": "Required[DomainStatus]", - "status_changed_at": "Required[str | None]", - "created_at": "Required[str]", + 'id': 'Required[str]', + 'domain': 'Required[str]', + 'status': 'Required[DomainStatus]', + 'status_changed_at': 'Required[str | None]', + 'created_at': 'Required[str]', }, ) -InitialRoutes: TypeAlias = Literal["both", "transactional", "broadcast"] +InitialRoutes: TypeAlias = Literal['both', 'transactional', 'broadcast'] MessageAttachmentData = TypedDict( - "MessageAttachmentData", + 'MessageAttachmentData', { - "size": "Required[int]", - "filename": "Required[str]", - "content_id": "Required[str | None]", - "content_type": "Required[str]", + 'size': 'Required[int]', + 'filename': 'Required[str]', + 'content_id': 'Required[str | None]', + 'content_type': 'Required[str]', }, ) -SpamSymbol = TypedDict( - "SpamSymbol", +MessageRecipientData = TypedDict( + 'MessageRecipientData', { - "name": "Required[str]", - "score": "Required[float]", - "options": "Required[list[str]]", - "description": "Required[str | None]", + 'email': 'Required[str]', + 'name': 'Required[str | None]', }, ) -MessageType: TypeAlias = Literal["inbound", "outbound"] -MessageRecipientData = TypedDict( - "MessageRecipientData", +MessageType: TypeAlias = Literal['inbound', 'outbound'] +SpamSymbol = TypedDict( + 'SpamSymbol', { - "email": "Required[str]", - "name": "Required[str | None]", + 'name': 'Required[str]', + 'score': 'Required[float]', + 'options': 'Required[list[str]]', + 'description': 'Required[str | None]', }, ) MessageData = TypedDict( - "MessageData", - { - "id": "Required[str]", - "type": "Required[MessageType]", - "status": "Required[MessageStatus]", - "status_changed_at": "Required[str | None]", - "tag": "Required[str | None]", - "from_email": "Required[str]", - "from_name": "Required[str | None]", - "reply_to": "Required[list[str] | None]", - "subject": "Required[str | None]", - "to": "Required[list[MessageRecipientData] | None]", - "cc": "Required[list[MessageRecipientData] | None]", - "bcc": "Required[list[MessageRecipientData] | None]", - "attachments": "Required[list[MessageAttachmentData] | None]", - "metadata": "Required[dict[str, str] | None]", - "spam_score": "NotRequired[float | None]", - "spam_symbols": "NotRequired[list[SpamSymbol]]", - "route_id": "Required[str]", - "created_at": "Required[str]", - }, -) - -MessageEventType: TypeAlias = Literal[ - "queued", - "processed", - "suppressed", - "delivered", - "soft_bounced", - "hard_bounced", - "spam_complaint", - "failed", - "blocked", - "policy_rejected", - "unsubscribed", - "opened", - "clicked", - "inbound_received", - "inbound_queued", - "inbound_spam_blocked", - "inbound_processed", - "inbound_retry", -] + 'MessageData', + { + 'id': 'Required[str]', + 'type': 'Required[MessageType]', + 'status': 'Required[MessageStatus]', + 'status_changed_at': 'Required[str | None]', + 'tag': 'Required[str | None]', + 'from_email': 'Required[str]', + 'from_name': 'Required[str | None]', + 'reply_to': 'Required[list[str] | None]', + 'subject': 'Required[str | None]', + 'to': 'Required[list[MessageRecipientData] | None]', + 'cc': 'Required[list[MessageRecipientData] | None]', + 'bcc': 'Required[list[MessageRecipientData] | None]', + 'attachments': 'Required[list[MessageAttachmentData] | None]', + 'metadata': 'Required[dict[str, str] | None]', + 'spam_score': 'NotRequired[float | None]', + 'spam_symbols': 'NotRequired[list[SpamSymbol]]', + 'route_id': 'Required[str]', + 'created_at': 'Required[str]', + }, +) + +MessageEventType: TypeAlias = Literal['queued', 'processed', 'suppressed', 'delivered', 'auto_replied', 'soft_bounced', 'hard_bounced', 'spam_complaint', 'failed', 'blocked', 'policy_rejected', 'unsubscribed', 'opened', 'clicked', 'inbound_received', 'inbound_queued', 'inbound_spam_blocked', 'inbound_processed', 'inbound_retry'] MessageEventData = TypedDict( - "MessageEventData", + 'MessageEventData', { - "message_id": "Required[str]", - "event": "Required[MessageEventType]", - "metadata": "Required[dict[str, Any] | None]", - "timestamp": "Required[str]", + 'message_id': 'Required[str]', + 'event': 'Required[MessageEventType]', + 'metadata': 'Required[dict[str, Any] | None]', + 'timestamp': 'Required[str]', }, ) MessageListData = TypedDict( - "MessageListData", + 'MessageListData', { - "id": "Required[str]", - "type": "Required[MessageType]", - "status": "Required[MessageStatus]", - "from_email": "Required[str]", - "from_name": "Required[str | None]", - "subject": "Required[str | None]", - "to": "Required[list[MessageRecipientData] | None]", - "cc": "Required[list[MessageRecipientData] | None]", - "bcc": "Required[list[MessageRecipientData] | None]", - "reply_to": "Required[list[str] | None]", - "tag": "Required[str | None]", - "created_at": "Required[str]", + 'id': 'Required[str]', + 'type': 'Required[MessageType]', + 'status': 'Required[MessageStatus]', + 'from_email': 'Required[str]', + 'from_name': 'Required[str | None]', + 'subject': 'Required[str | None]', + 'to': 'Required[list[MessageRecipientData] | None]', + 'cc': 'Required[list[MessageRecipientData] | None]', + 'bcc': 'Required[list[MessageRecipientData] | None]', + 'reply_to': 'Required[list[str] | None]', + 'tag': 'Required[str | None]', + 'created_at': 'Required[str]', }, ) MessageStatsData = TypedDict( - "MessageStatsData", + 'MessageStatsData', { - "messages_transactional": "Required[int]", - "messages_broadcast": "Required[int]", - "messages_inbound": "Required[int]", - "deliverability": "Required[float]", + 'messages_transactional': 'Required[int]', + 'messages_broadcast': 'Required[int]', + 'messages_inbound': 'Required[int]', + 'deliverability': 'Required[float]', }, ) -Plan: TypeAlias = Literal["free", "starter", "growth", "pro"] -RouteType: TypeAlias = Literal["transactional", "broadcast", "inbound"] -RouteStatisticData = TypedDict( - "RouteStatisticData", +Plan: TypeAlias = Literal['free', 'starter', 'growth', 'pro'] +UserData = TypedDict( + 'UserData', { - "date": "Required[str]", - "sent_count": "Required[int]", - "delivered_count": "Required[int]", - "opened_count": "Required[int]", - "clicked_count": "Required[int]", - "hard_bounce_count": "Required[int]", - "spam_complaint_count": "Required[int]", - "inbound_received_count": "Required[int]", - "effective_opened_count": "Required[int | None]", - "machine_opened_count": "Required[int | None]", - "machine_clicked_count": "Required[int | None]", + 'id': 'Required[str]', + 'name': 'Required[str]', + 'email': 'Required[str]', + 'avatar': 'Required[str | None]', }, ) -RouteData = TypedDict( - "RouteData", - { - "id": "Required[str]", - "project_id": "Required[str]", - "slug": "Required[str]", - "name": "Required[str]", - "route_type": "Required[RouteType]", - "is_default": "Required[bool]", - "inbound_address": "NotRequired[str]", - "inbound_domain": "NotRequired[str]", - "inbound_domain_verified_at": "NotRequired[str]", - "inbound_spam_threshold": "NotRequired[float]", - "attachment_delivery": "NotRequired[AttachmentDelivery]", - "project": "NotRequired[ProjectData]", - "webhooks_count": "NotRequired[int]", - "suppressed_recipients_count": "NotRequired[int]", - "statistics": "NotRequired[dict[str, Any] | list[RouteStatisticData]]", - "created_at": "Required[str]", - "updated_at": "Required[str]", +TeamMemberData = TypedDict( + 'TeamMemberData', + { + 'id': 'Required[str]', + 'user': 'NotRequired[UserData]', + 'role': 'Required[str | None]', + 'joined_at': 'Required[str | None]', }, ) -UserData = TypedDict( - "UserData", +RouteStatisticData = TypedDict( + 'RouteStatisticData', { - "id": "Required[str]", - "name": "Required[str]", - "email": "Required[str]", - "avatar": "Required[str | None]", + 'date': 'Required[str]', + 'sent_count': 'Required[int]', + 'delivered_count': 'Required[int]', + 'opened_count': 'Required[int]', + 'clicked_count': 'Required[int]', + 'hard_bounce_count': 'Required[int]', + 'spam_complaint_count': 'Required[int]', + 'inbound_received_count': 'Required[int]', + 'effective_opened_count': 'Required[int | None]', + 'machine_opened_count': 'Required[int | None]', + 'machine_clicked_count': 'Required[int | None]', }, ) -TeamMemberData = TypedDict( - "TeamMemberData", - { - "id": "Required[str]", - "user": "NotRequired[UserData]", - "role": "Required[str | None]", - "joined_at": "Required[str | None]", +RouteType: TypeAlias = Literal['transactional', 'broadcast', 'inbound'] +RouteData = TypedDict( + 'RouteData', + { + 'id': 'Required[str]', + 'project_id': 'Required[str]', + 'slug': 'Required[str]', + 'name': 'Required[str]', + 'route_type': 'Required[RouteType]', + 'is_default': 'Required[bool]', + 'inbound_address': 'NotRequired[str]', + 'inbound_domain': 'NotRequired[str]', + 'inbound_domain_verified_at': 'NotRequired[str]', + 'inbound_spam_threshold': 'NotRequired[float]', + 'attachment_delivery': 'NotRequired[AttachmentDelivery]', + 'project': 'NotRequired[ProjectData]', + 'webhooks_count': 'NotRequired[int]', + 'suppressed_recipients_count': 'NotRequired[int]', + 'statistics': 'NotRequired[dict[str, Any] | list[RouteStatisticData]]', + 'created_at': 'Required[str]', + 'updated_at': 'Required[str]', }, ) ProjectData = TypedDict( - "ProjectData", - { - "id": "Required[str]", - "name": "Required[str]", - "smtp_enabled": "Required[bool]", - "default_route_id": "Required[str | None]", - "token_generated_at": "Required[str | None]", - "token_last_used_at": "Required[str | None]", - "token_last_used_ip": "Required[str | None]", - "routes": "NotRequired[list[RouteData]]", - "routes_count": "NotRequired[int]", - "domains": "NotRequired[list[DomainData]]", - "domains_count": "NotRequired[int]", - "team_members": "NotRequired[list[TeamMemberData]]", - "team_members_count": "NotRequired[int]", - "last_28_days": "NotRequired[MessageStatsData | Any]", - "created_at": "Required[str]", - "updated_at": "Required[str]", + 'ProjectData', + { + 'id': 'Required[str]', + 'name': 'Required[str]', + 'smtp_enabled': 'Required[bool]', + 'redact_email_content': 'Required[bool]', + 'default_route_id': 'Required[str | None]', + 'token_generated_at': 'Required[str | None]', + 'token_last_used_at': 'Required[str | None]', + 'token_last_used_ip': 'Required[str | None]', + 'routes': 'NotRequired[list[RouteData]]', + 'routes_count': 'NotRequired[int]', + 'domains': 'NotRequired[list[DomainData]]', + 'domains_count': 'NotRequired[int]', + 'team_members': 'NotRequired[list[TeamMemberData]]', + 'team_members_count': 'NotRequired[int]', + 'last_28_days': 'NotRequired[MessageStatsData | Any]', + 'created_at': 'Required[str]', + 'updated_at': 'Required[str]', }, ) ProjectListData = TypedDict( - "ProjectListData", + 'ProjectListData', { - "id": "Required[str]", - "name": "Required[str]", - "smtp_enabled": "Required[bool]", - "routes_count": "Required[int]", - "domains_count": "Required[int]", - "team_members_count": "Required[int]", - "last_28_days": "Required[MessageStatsData]", - "created_at": "Required[str]", - "updated_at": "Required[str]", + 'id': 'Required[str]', + 'name': 'Required[str]', + 'smtp_enabled': 'Required[bool]', + 'routes_count': 'Required[int]', + 'domains_count': 'Required[int]', + 'team_members_count': 'Required[int]', + 'last_28_days': 'Required[MessageStatsData]', + 'created_at': 'Required[str]', + 'updated_at': 'Required[str]', }, ) RouteListData = TypedDict( - "RouteListData", + 'RouteListData', { - "id": "Required[str]", - "slug": "Required[str]", - "name": "Required[str]", - "route_type": "Required[RouteType]", - "is_default": "Required[bool]", - "webhooks_count": "Required[int]", - "suppressed_recipients_count": "Required[int]", - "created_at": "Required[str]", - "updated_at": "Required[str]", + 'id': 'Required[str]', + 'slug': 'Required[str]', + 'name': 'Required[str]', + 'route_type': 'Required[RouteType]', + 'is_default': 'Required[bool]', + 'webhooks_count': 'Required[int]', + 'suppressed_recipients_count': 'Required[int]', + 'created_at': 'Required[str]', + 'updated_at': 'Required[str]', }, ) -StatsInboundData = TypedDict( - "StatsInboundData", +StatsTypeData = TypedDict( + 'StatsTypeData', { - "received": "Required[int]", + 'sent': 'Required[int]', + 'hard_bounced': 'Required[int]', + 'spam_complaints': 'Required[int]', }, ) -StatsTypeData = TypedDict( - "StatsTypeData", +StatsInboundData = TypedDict( + 'StatsInboundData', { - "sent": "Required[int]", - "hard_bounced": "Required[int]", - "spam_complaints": "Required[int]", + 'received': 'Required[int]', }, ) StatsDailyData = TypedDict( - "StatsDailyData", + 'StatsDailyData', { - "date": "Required[str]", - "sent": "Required[int]", - "delivered": "Required[int]", - "hard_bounced": "Required[int]", - "spam_complaints": "Required[int]", - "opened": "Required[int | None]", - "clicked": "Required[int | None]", - "inbound": "Required[StatsInboundData]", - "transactional": "Required[StatsTypeData | Any]", - "broadcast": "Required[StatsTypeData | Any]", - "effective_opened": "Required[int | None]", - "machine_opened": "Required[int | None]", - "machine_clicked": "Required[int | None]", + 'date': 'Required[str]', + 'sent': 'Required[int]', + 'delivered': 'Required[int]', + 'hard_bounced': 'Required[int]', + 'spam_complaints': 'Required[int]', + 'opened': 'Required[int | None]', + 'clicked': 'Required[int | None]', + 'inbound': 'Required[StatsInboundData]', + 'transactional': 'Required[StatsTypeData | Any]', + 'broadcast': 'Required[StatsTypeData | Any]', + 'effective_opened': 'Required[int | None]', + 'machine_opened': 'Required[int | None]', + 'machine_clicked': 'Required[int | None]', }, ) StatsTotalsData = TypedDict( - "StatsTotalsData", + 'StatsTotalsData', { - "sent": "Required[int]", - "delivered": "Required[int]", - "hard_bounced": "Required[int]", - "spam_complaints": "Required[int]", - "opened": "Required[int | None]", - "clicked": "Required[int | None]", - "inbound": "Required[StatsInboundData]", - "transactional": "Required[StatsTypeData | Any]", - "broadcast": "Required[StatsTypeData | Any]", - "effective_opened": "Required[int | None]", - "machine_opened": "Required[int | None]", - "machine_clicked": "Required[int | None]", + 'sent': 'Required[int]', + 'delivered': 'Required[int]', + 'hard_bounced': 'Required[int]', + 'spam_complaints': 'Required[int]', + 'opened': 'Required[int | None]', + 'clicked': 'Required[int | None]', + 'inbound': 'Required[StatsInboundData]', + 'transactional': 'Required[StatsTypeData | Any]', + 'broadcast': 'Required[StatsTypeData | Any]', + 'effective_opened': 'Required[int | None]', + 'machine_opened': 'Required[int | None]', + 'machine_clicked': 'Required[int | None]', }, ) StatsData = TypedDict( - "StatsData", + 'StatsData', { - "from": "Required[str]", - "to": "Required[str]", - "totals": "Required[StatsTotalsData]", - "daily": "Required[list[StatsDailyData]]", + 'from': 'Required[str]', + 'to': 'Required[str]', + 'totals': 'Required[StatsTotalsData]', + 'daily': 'Required[list[StatsDailyData]]', }, ) StatsRequestData = TypedDict( - "StatsRequestData", + 'StatsRequestData', { - "from": "Required[str]", - "to": "Required[str]", - "project_id": "NotRequired[str | None]", - "include_machine": "NotRequired[bool]", + 'from': 'Required[str]', + 'to': 'Required[str]', + 'project_id': 'NotRequired[str | None]', + 'include_machine': 'NotRequired[bool]', }, ) StoreDomainData = TypedDict( - "StoreDomainData", + 'StoreDomainData', { - "domain": "Required[str]", + 'domain': 'Required[str]', }, ) StoreProjectData = TypedDict( - "StoreProjectData", + 'StoreProjectData', { - "name": "Required[str]", - "smtp_enabled": "NotRequired[bool]", - "initial_routes": "NotRequired[InitialRoutes]", + 'name': 'Required[str]', + 'smtp_enabled': 'NotRequired[bool]', + 'initial_routes': 'NotRequired[InitialRoutes]', + 'short_token': 'NotRequired[bool]', }, ) StoreRouteData = TypedDict( - "StoreRouteData", + 'StoreRouteData', { - "name": "Required[str]", - "route_type": "Required[RouteType]", - "slug": "NotRequired[str | None]", + 'name': 'Required[str]', + 'route_type': 'Required[RouteType]', + 'slug': 'NotRequired[str | None]', }, ) -SuppressionReason: TypeAlias = Literal["spam_complaint", "hard_bounce", "unsubscribe", "manual"] +SuppressionScope: TypeAlias = Literal['global', 'team', 'project', 'route'] +SuppressionReason: TypeAlias = Literal['spam_complaint', 'hard_bounce', 'unsubscribe', 'manual'] StoreSuppressionData = TypedDict( - "StoreSuppressionData", - { - "email": "NotRequired[str | None]", - "reason": "Required[SuppressionReason]", - "scope": "Required[Literal['team', 'project', 'route']]", - "route_id": "NotRequired[str | None]", - "project_id": "NotRequired[str | None]", - "emails": "NotRequired[list[str] | None]", - }, -) - -WebhookEvent: TypeAlias = Literal[ - "message.created", - "message.sent", - "message.delivered", - "message.hard_bounced", - "message.soft_bounced", - "message.spam_complaint", - "message.failed", - "message.suppressed", - "message.unsubscribed", - "message.opened", - "message.clicked", - "message.inbound", - "message.policy_rejected", - "webhook.test", -] + 'StoreSuppressionData', + { + 'email': 'NotRequired[str | None]', + 'reason': 'Required[SuppressionReason]', + 'scope': 'Required[SuppressionScope]', + 'route_id': 'NotRequired[str | None]', + 'project_id': 'NotRequired[str | None]', + 'emails': 'NotRequired[list[str] | None]', + }, +) + +WebhookEvent: TypeAlias = Literal['message.created', 'message.sent', 'message.delivered', 'message.auto_replied', 'message.hard_bounced', 'message.soft_bounced', 'message.spam_complaint', 'message.failed', 'message.suppressed', 'message.unsubscribed', 'message.opened', 'message.clicked', 'message.inbound', 'message.policy_rejected', 'webhook.test'] StoreWebhookData = TypedDict( - "StoreWebhookData", + 'StoreWebhookData', { - "route_id": "Required[str]", - "name": "Required[str]", - "url": "Required[str]", - "enabled": "NotRequired[bool | None]", - "include_machine_events": "NotRequired[bool | None]", - "events": "Required[list[WebhookEvent]]", + 'route_id': 'Required[str]', + 'name': 'Required[str]', + 'url': 'Required[str]', + 'enabled': 'NotRequired[bool | None]', + 'include_machine_events': 'NotRequired[bool | None]', + 'events': 'Required[list[WebhookEvent]]', }, ) -SuppressionScope: TypeAlias = Literal["global", "team", "project", "route"] -SuppressionType: TypeAlias = Literal["email", "domain", "extension"] +SuppressionType: TypeAlias = Literal['email', 'domain', 'extension'] SuppressedRecipientData = TypedDict( - "SuppressedRecipientData", + 'SuppressedRecipientData', { - "id": "Required[str]", - "type": "Required[SuppressionType]", - "value": "Required[str]", - "reason": "Required[SuppressionReason]", - "scope": "Required[SuppressionScope]", - "project_id": "Required[str | None]", - "route_id": "Required[str | None]", - "created_at": "Required[str]", - "updated_at": "Required[str]", + 'id': 'Required[str]', + 'type': 'Required[SuppressionType]', + 'value': 'Required[str]', + 'reason': 'Required[SuppressionReason]', + 'scope': 'Required[SuppressionScope]', + 'project_id': 'Required[str | None]', + 'route_id': 'Required[str | None]', + 'created_at': 'Required[str]', + 'updated_at': 'Required[str]', }, ) TeamAddonData = TypedDict( - "TeamAddonData", + 'TeamAddonData', { - "type": "Required[str | None]", - "expires_at": "Required[str | None]", + 'type': 'Required[str | None]', + 'expires_at': 'Required[str | None]', }, ) -TeamType: TypeAlias = Literal["personal", "business"] -VolumeTier: TypeAlias = Literal[300, 10000, 50000, 125000, 500000, 750000, 1000000, 1500000] +TeamType: TypeAlias = Literal['personal', 'business'] +VolumeTier: TypeAlias = Literal[300, 10000, 50000, 125000, 300000, 500000, 750000, 1000000, 1500000] TeamData = TypedDict( - "TeamData", + 'TeamData', { - "id": "Required[str]", - "name": "Required[str]", - "type": "Required[TeamType]", - "plan": "Required[Plan]", - "tier": "Required[VolumeTier]", - "verified_at": "Required[str | None]", - "features": "NotRequired[list[str]]", - "addons": "NotRequired[list[TeamAddonData]]", - "created_at": "Required[str]", - "domains_count": "NotRequired[int]", - "projects_count": "NotRequired[int]", - "members_count": "NotRequired[int]", + 'id': 'Required[str]', + 'name': 'Required[str]', + 'type': 'Required[TeamType]', + 'plan': 'Required[Plan]', + 'tier': 'Required[VolumeTier]', + 'verified_at': 'Required[str | None]', + 'features': 'NotRequired[list[str]]', + 'addons': 'NotRequired[list[TeamAddonData]]', + 'created_at': 'Required[str]', + 'domains_count': 'NotRequired[int]', + 'projects_count': 'NotRequired[int]', + 'members_count': 'NotRequired[int]', }, ) TeamUsagePeriodData = TypedDict( - "TeamUsagePeriodData", + 'TeamUsagePeriodData', { - "usage": "Required[int]", - "last_incremented_at": "Required[str | None]", - "period_start": "Required[str]", - "period_end": "Required[str]", + 'usage': 'Required[int]', + 'last_incremented_at': 'Required[str | None]', + 'period_start': 'Required[str]', + 'period_end': 'Required[str]', }, ) TeamUsageDetailData = TypedDict( - "TeamUsageDetailData", + 'TeamUsageDetailData', { - "current_period": "Required[TeamUsagePeriodData]", - "historical_usage": "Required[list[TeamUsagePeriodData]]", + 'current_period': 'Required[TeamUsagePeriodData]', + 'historical_usage': 'Required[list[TeamUsagePeriodData]]', }, ) UpdateDomainProjectsData = TypedDict( - "UpdateDomainProjectsData", + 'UpdateDomainProjectsData', { - "project_ids": "Required[list[str]]", + 'project_ids': 'Required[list[str]]', }, ) UpdateProjectData = TypedDict( - "UpdateProjectData", + 'UpdateProjectData', { - "name": "NotRequired[str | None]", - "smtp_enabled": "NotRequired[bool | None]", - "default_route_id": "NotRequired[str | None]", + 'name': 'NotRequired[str | None]', + 'smtp_enabled': 'NotRequired[bool | None]', + 'redact_email_content': 'NotRequired[bool | None]', + 'default_route_id': 'NotRequired[str | None]', }, ) UpdateProjectMembersData = TypedDict( - "UpdateProjectMembersData", + 'UpdateProjectMembersData', + { + 'team_member_ids': 'Required[list[str]]', + }, +) + +UpdateRouteInboundSettingsData = TypedDict( + 'UpdateRouteInboundSettingsData', { - "team_member_ids": "Required[list[str]]", + 'inbound_domain': 'NotRequired[str | None]', + 'inbound_spam_threshold': 'NotRequired[float | None]', + 'attachment_delivery': 'NotRequired[AttachmentDelivery | Any]', + }, +) + +UpdateRouteSettingsData = TypedDict( + 'UpdateRouteSettingsData', + { + 'track_opens': 'NotRequired[bool | None]', + 'track_clicks': 'NotRequired[bool | None]', + 'disable_plaintext_generation': 'NotRequired[bool | None]', + 'disable_hosted_unsubscribe': 'NotRequired[bool | None]', + 'redact_email_content': 'NotRequired[bool | None]', }, ) UpdateRouteData = TypedDict( - "UpdateRouteData", + 'UpdateRouteData', { - "name": "NotRequired[str | None]", - "settings": "NotRequired[dict[str, Any]]", - "inbound_settings": "NotRequired[dict[str, Any]]", + 'name': 'NotRequired[str | None]', + 'settings': 'NotRequired[UpdateRouteSettingsData | Any]', + 'inbound_settings': 'NotRequired[UpdateRouteInboundSettingsData | Any]', }, ) UpdateTeamData = TypedDict( - "UpdateTeamData", + 'UpdateTeamData', { - "name": "NotRequired[str | None]", + 'name': 'NotRequired[str | None]', }, ) UpdateWebhookData = TypedDict( - "UpdateWebhookData", + 'UpdateWebhookData', { - "name": "NotRequired[str]", - "url": "NotRequired[str]", - "enabled": "NotRequired[bool]", - "include_machine_events": "NotRequired[bool]", - "events": "NotRequired[list[WebhookEvent]]", + 'name': 'NotRequired[str]', + 'url': 'NotRequired[str]', + 'enabled': 'NotRequired[bool]', + 'include_machine_events': 'NotRequired[bool]', + 'events': 'NotRequired[list[WebhookEvent]]', }, ) WebhookData = TypedDict( - "WebhookData", + 'WebhookData', { - "id": "Required[str]", - "route_id": "Required[str]", - "name": "Required[str]", - "url": "Required[str]", - "events": "Required[list[str]]", - "enabled": "Required[bool]", - "include_machine_events": "Required[bool]", - "secret": "NotRequired[str]", - "last_called_at": "Required[str | None]", - "created_at": "Required[str]", - "updated_at": "Required[str]", + 'id': 'Required[str]', + 'route_id': 'Required[str]', + 'name': 'Required[str]', + 'url': 'Required[str]', + 'events': 'Required[list[str]]', + 'enabled': 'Required[bool]', + 'include_machine_events': 'Required[bool]', + 'secret': 'NotRequired[str]', + 'last_called_at': 'Required[str | None]', + 'created_at': 'Required[str]', + 'updated_at': 'Required[str]', }, ) -WebhookDeliveryStatus: TypeAlias = Literal[ - "pending", "success", "failed", "client_error", "server_error", "timeout" -] +WebhookDeliveryStatus: TypeAlias = Literal['pending', 'success', 'failed', 'client_error', 'server_error', 'timeout'] WebhookDeliveryData = TypedDict( - "WebhookDeliveryData", + 'WebhookDeliveryData', { - "id": "Required[str]", - "webhook_id": "Required[str]", - "event_type": "Required[WebhookEvent]", - "status": "Required[WebhookDeliveryStatus]", - "attempt_number": "Required[int]", - "http_status_code": "Required[int | None]", - "duration_ms": "Required[int | None]", - "payload": "Required[list[str]]", - "response_body": "Required[str | None]", - "response_headers": "Required[list[str] | None]", - "error_message": "Required[str | None]", - "delivered_at": "Required[str | None]", - "timestamp": "Required[str]", + 'id': 'Required[str]', + 'webhook_id': 'Required[str]', + 'event_type': 'Required[WebhookEvent]', + 'status': 'Required[WebhookDeliveryStatus]', + 'attempt_number': 'Required[int]', + 'http_status_code': 'Required[int | None]', + 'duration_ms': 'Required[int | None]', + 'payload': 'Required[list[str]]', + 'response_body': 'Required[str | None]', + 'response_headers': 'Required[list[str] | None]', + 'error_message': 'Required[str | None]', + 'delivered_at': 'Required[str | None]', + 'timestamp': 'Required[str]', }, ) WebhookDeliveryListData = TypedDict( - "WebhookDeliveryListData", + 'WebhookDeliveryListData', { - "id": "Required[str]", - "webhook_id": "Required[str]", - "event_type": "Required[WebhookEvent]", - "status": "Required[WebhookDeliveryStatus]", - "attempt_number": "Required[int]", - "http_status_code": "Required[int | None]", - "duration_ms": "Required[int | None]", - "delivered_at": "Required[str | None]", - "created_at": "Required[str]", + 'id': 'Required[str]', + 'webhook_id': 'Required[str]', + 'event_type': 'Required[WebhookEvent]', + 'status': 'Required[WebhookDeliveryStatus]', + 'attempt_number': 'Required[int]', + 'http_status_code': 'Required[int | None]', + 'duration_ms': 'Required[int | None]', + 'delivered_at': 'Required[str | None]', + 'created_at': 'Required[str]', }, ) WebhookListData = TypedDict( - "WebhookListData", + 'WebhookListData', { - "id": "Required[str]", - "route_id": "Required[str]", - "name": "Required[str]", - "url": "Required[str]", - "events": "Required[list[WebhookEvent]]", - "enabled": "Required[bool]", - "last_called_at": "Required[str | None]", - "created_at": "Required[str]", - "updated_at": "Required[str]", + 'id': 'Required[str]', + 'route_id': 'Required[str]', + 'name': 'Required[str]', + 'url': 'Required[str]', + 'events': 'Required[list[WebhookEvent]]', + 'enabled': 'Required[bool]', + 'last_called_at': 'Required[str | None]', + 'created_at': 'Required[str]', + 'updated_at': 'Required[str]', }, ) EmailAttachment = TypedDict( - "EmailAttachment", + 'EmailAttachment', { - "filename": "Required[str]", - "content": "Required[str]", - "content_type": "NotRequired[str | None]", - "content_id": "NotRequired[str | None]", + 'filename': 'Required[str]', + 'content': 'Required[str]', + 'content_type': 'NotRequired[str | None]', + 'content_id': 'NotRequired[str | None]', }, ) EmailPayload: TypeAlias = SendMailRequest EmailStatus: TypeAlias = MessageStatus SendMailResponse = TypedDict( - "SendMailResponse", + 'SendMailResponse', { - "message_id": "Required[str]", - "status": "Required[MessageStatus]", + 'message_id': 'Required[str]', + 'status': 'Required[MessageStatus]', }, ) SendBatchMailResponse: TypeAlias = list[dict[str, Any]] PingResponse: TypeAlias = Literal[200] DomainIndexResponse = TypedDict( - "DomainIndexResponse", + 'DomainIndexResponse', { - "data": "Required[list[DomainListData]]", - "path": "Required[str | None]", - "per_page": "Required[int]", - "next_cursor": "Required[str | None]", - "next_page_url": "Required[str | None]", - "prev_cursor": "Required[str | None]", - "prev_page_url": "Required[str | None]", + 'data': 'Required[list[DomainListData]]', + 'path': 'Required[str | None]', + 'per_page': 'Required[int]', + 'next_cursor': 'Required[str | None]', + 'next_page_url': 'Required[str | None]', + 'prev_cursor': 'Required[str | None]', + 'prev_page_url': 'Required[str | None]', }, ) @@ -671,287 +641,295 @@ DomainStoreResponse: TypeAlias = DomainData DomainShowResponse: TypeAlias = DomainData DomainDestroyResponse = TypedDict( - "DomainDestroyResponse", + 'DomainDestroyResponse', { - "message": "Required[Literal['Domain deleted successfully.']]", + 'message': "Required[Literal['Domain deleted successfully.']]", }, ) DomainVerifyDnsRecordsResponse = TypedDict( - "DomainVerifyDnsRecordsResponse", + 'DomainVerifyDnsRecordsResponse', { - "message": "Required[str]", + 'message': 'Required[str]', }, ) DomainVerifySpecificDnsRecordResponse = TypedDict( - "DomainVerifySpecificDnsRecordResponse", + 'DomainVerifySpecificDnsRecordResponse', { - "message": "Required[Literal['DNS record verified successfully.']]", + 'message': "Required[Literal['DNS record verified successfully.']]", }, ) DomainUpdateProjectsRequest: TypeAlias = UpdateDomainProjectsData DomainUpdateProjectsResponse = TypedDict( - "DomainUpdateProjectsResponse", + 'DomainUpdateProjectsResponse', + { + 'data': 'Required[DomainData]', + 'message': "Required[Literal['Domain projects updated successfully.']]", + }, +) + +BlockedFileTypesResponse = TypedDict( + 'BlockedFileTypesResponse', { - "data": "Required[DomainData]", - "message": "Required[Literal['Domain projects updated successfully.']]", + 'extensions': 'Required[list[str]]', + 'mime_types': 'Required[list[str]]', }, ) MessageIndexResponse: TypeAlias = Union[dict[str, Any], list[MessageListData]] MessageShowResponse: TypeAlias = MessageData MessageEventsResponse = TypedDict( - "MessageEventsResponse", + 'MessageEventsResponse', { - "data": "Required[list[MessageEventData]]", - "path": "Required[str | None]", - "per_page": "Required[int]", - "next_cursor": "Required[str | None]", - "next_page_url": "Required[str | None]", - "prev_cursor": "Required[str | None]", - "prev_page_url": "Required[str | None]", + 'data': 'Required[list[MessageEventData]]', + 'path': 'Required[str | None]', + 'per_page': 'Required[int]', + 'next_cursor': 'Required[str | None]', + 'next_page_url': 'Required[str | None]', + 'prev_cursor': 'Required[str | None]', + 'prev_page_url': 'Required[str | None]', }, ) ProjectIndexResponse = TypedDict( - "ProjectIndexResponse", + 'ProjectIndexResponse', { - "data": "Required[list[ProjectListData]]", - "path": "Required[str | None]", - "per_page": "Required[int]", - "next_cursor": "Required[str | None]", - "next_page_url": "Required[str | None]", - "prev_cursor": "Required[str | None]", - "prev_page_url": "Required[str | None]", + 'data': 'Required[list[ProjectListData]]', + 'path': 'Required[str | None]', + 'per_page': 'Required[int]', + 'next_cursor': 'Required[str | None]', + 'next_page_url': 'Required[str | None]', + 'prev_cursor': 'Required[str | None]', + 'prev_page_url': 'Required[str | None]', }, ) ProjectStoreRequest: TypeAlias = StoreProjectData ProjectStoreResponse = TypedDict( - "ProjectStoreResponse", + 'ProjectStoreResponse', { - "data": "Required[ProjectData]", - "message": "Required[Literal['Project created successfully.']]", - "api_token": "Required[str]", + 'data': 'Required[ProjectData]', + 'message': "Required[Literal['Project created successfully.']]", + 'api_token': 'Required[str]', }, ) ProjectShowResponse: TypeAlias = ProjectData ProjectUpdateRequest: TypeAlias = UpdateProjectData ProjectUpdateResponse = TypedDict( - "ProjectUpdateResponse", + 'ProjectUpdateResponse', { - "data": "Required[ProjectData]", - "message": "Required[Literal['Project updated successfully.']]", + 'data': 'Required[ProjectData]', + 'message': "Required[Literal['Project updated successfully.']]", }, ) ProjectDestroyResponse = TypedDict( - "ProjectDestroyResponse", + 'ProjectDestroyResponse', { - "message": "Required[Literal['Project deleted successfully.']]", + 'message': "Required[Literal['Project deleted successfully.']]", }, ) ProjectRotateTokenResponse = TypedDict( - "ProjectRotateTokenResponse", + 'ProjectRotateTokenResponse', { - "data": "Required[ProjectData]", - "new_token": "Required[str]", - "message": "Required[Literal['API token rotated successfully. Please update your integrations.']]", + 'data': 'Required[ProjectData]', + 'new_token': 'Required[str]', + 'message': "Required[Literal['Project API token rotated successfully. Please update your integrations.']]", }, ) ProjectUpdateMembersRequest: TypeAlias = UpdateProjectMembersData ProjectUpdateMembersResponse = TypedDict( - "ProjectUpdateMembersResponse", + 'ProjectUpdateMembersResponse', { - "data": "Required[ProjectData]", - "message": "Required[Literal['Project members updated successfully.']]", + 'data': 'Required[ProjectData]', + 'message': "Required[Literal['Project members updated successfully.']]", }, ) ProjectAddMemberResponse = TypedDict( - "ProjectAddMemberResponse", + 'ProjectAddMemberResponse', { - "message": "Required[Literal['Team member added to project successfully.']]", + 'message': "Required[Literal['Team member added to project successfully.']]", }, ) ProjectRemoveMemberResponse = TypedDict( - "ProjectRemoveMemberResponse", + 'ProjectRemoveMemberResponse', { - "message": "Required[Literal['Team member removed from project successfully.']]", + 'message': "Required[Literal['Team member removed from project successfully.']]", }, ) RouteIndexResponse = TypedDict( - "RouteIndexResponse", + 'RouteIndexResponse', { - "data": "Required[list[RouteListData]]", - "path": "Required[str | None]", - "per_page": "Required[int]", - "next_cursor": "Required[str | None]", - "next_page_url": "Required[str | None]", - "prev_cursor": "Required[str | None]", - "prev_page_url": "Required[str | None]", + 'data': 'Required[list[RouteListData]]', + 'path': 'Required[str | None]', + 'per_page': 'Required[int]', + 'next_cursor': 'Required[str | None]', + 'next_page_url': 'Required[str | None]', + 'prev_cursor': 'Required[str | None]', + 'prev_page_url': 'Required[str | None]', }, ) RouteStoreRequest: TypeAlias = StoreRouteData RouteStoreResponse = TypedDict( - "RouteStoreResponse", + 'RouteStoreResponse', { - "data": "Required[RouteData]", - "message": "Required[Literal['Route created successfully.']]", + 'data': 'Required[RouteData]', + 'message': "Required[Literal['Route created successfully.']]", }, ) RouteShowResponse: TypeAlias = RouteData RouteUpdateRequest: TypeAlias = UpdateRouteData RouteUpdateResponse = TypedDict( - "RouteUpdateResponse", + 'RouteUpdateResponse', { - "data": "Required[RouteData]", - "message": "Required[Literal['Route updated successfully.']]", + 'data': 'Required[RouteData]', + 'message': "Required[Literal['Route updated successfully.']]", }, ) RouteDestroyResponse = TypedDict( - "RouteDestroyResponse", + 'RouteDestroyResponse', { - "message": "Required[Literal['Route deleted successfully.']]", + 'message': "Required[Literal['Route deleted successfully.']]", }, ) RouteVerifyInboundDomainResponse = TypedDict( - "RouteVerifyInboundDomainResponse", + 'RouteVerifyInboundDomainResponse', { - "data": "Required[dict[str, Any]]", + 'data': 'Required[dict[str, Any]]', }, ) StatsIndexResponse: TypeAlias = StatsData SuppressionIndexResponse = TypedDict( - "SuppressionIndexResponse", + 'SuppressionIndexResponse', { - "data": "Required[list[SuppressedRecipientData]]", - "path": "Required[str | None]", - "per_page": "Required[int]", - "next_cursor": "Required[str | None]", - "next_page_url": "Required[str | None]", - "prev_cursor": "Required[str | None]", - "prev_page_url": "Required[str | None]", + 'data': 'Required[list[SuppressedRecipientData]]', + 'path': 'Required[str | None]', + 'per_page': 'Required[int]', + 'next_cursor': 'Required[str | None]', + 'next_page_url': 'Required[str | None]', + 'prev_cursor': 'Required[str | None]', + 'prev_page_url': 'Required[str | None]', }, ) SuppressionStoreRequest: TypeAlias = StoreSuppressionData SuppressionStoreResponse = TypedDict( - "SuppressionStoreResponse", + 'SuppressionStoreResponse', { - "message": "Required[str | Literal['No emails were added.']]", - "data": "Required[dict[str, Any]]", + 'message': "Required[str | Literal['No emails were added.']]", + 'data': 'Required[dict[str, Any]]', }, ) SuppressionDestroyResponse = TypedDict( - "SuppressionDestroyResponse", + 'SuppressionDestroyResponse', { - "message": "Required[Literal['Email removed from suppression list successfully.']]", + 'message': "Required[Literal['Email removed from suppression list successfully.']]", }, ) TeamShowResponse: TypeAlias = TeamData TeamUpdateRequest: TypeAlias = UpdateTeamData TeamUpdateResponse = TypedDict( - "TeamUpdateResponse", + 'TeamUpdateResponse', { - "data": "Required[TeamData]", - "message": "Required[Literal['Team settings updated successfully.']]", + 'data': 'Required[TeamData]', + 'message': "Required[Literal['Team settings updated successfully.']]", }, ) TeamUsageResponse: TypeAlias = TeamUsageDetailData TeamMembersResponse = TypedDict( - "TeamMembersResponse", + 'TeamMembersResponse', { - "data": "Required[list[TeamMemberData]]", - "path": "Required[str | None]", - "per_page": "Required[int]", - "next_cursor": "Required[str | None]", - "next_page_url": "Required[str | None]", - "prev_cursor": "Required[str | None]", - "prev_page_url": "Required[str | None]", + 'data': 'Required[list[TeamMemberData]]', + 'path': 'Required[str | None]', + 'per_page': 'Required[int]', + 'next_cursor': 'Required[str | None]', + 'next_page_url': 'Required[str | None]', + 'prev_cursor': 'Required[str | None]', + 'prev_page_url': 'Required[str | None]', }, ) WebhookIndexResponse = TypedDict( - "WebhookIndexResponse", + 'WebhookIndexResponse', { - "data": "Required[list[WebhookListData]]", - "path": "Required[str | None]", - "per_page": "Required[int]", - "next_cursor": "Required[str | None]", - "next_page_url": "Required[str | None]", - "prev_cursor": "Required[str | None]", - "prev_page_url": "Required[str | None]", + 'data': 'Required[list[WebhookListData]]', + 'path': 'Required[str | None]', + 'per_page': 'Required[int]', + 'next_cursor': 'Required[str | None]', + 'next_page_url': 'Required[str | None]', + 'prev_cursor': 'Required[str | None]', + 'prev_page_url': 'Required[str | None]', }, ) WebhookStoreRequest: TypeAlias = StoreWebhookData WebhookStoreResponse = TypedDict( - "WebhookStoreResponse", + 'WebhookStoreResponse', { - "data": "Required[WebhookData]", - "message": "Required[Literal['Webhook created successfully. Please save the secret as it will not be shown again.']]", + 'data': 'Required[WebhookData]', + 'message': "Required[Literal['Webhook created successfully. Please save the secret as it will not be shown again.']]", }, ) WebhookShowResponse: TypeAlias = WebhookData WebhookUpdateRequest: TypeAlias = UpdateWebhookData WebhookUpdateResponse = TypedDict( - "WebhookUpdateResponse", + 'WebhookUpdateResponse', { - "data": "Required[WebhookData]", - "message": "Required[Literal['Webhook updated successfully.']]", + 'data': 'Required[WebhookData]', + 'message': "Required[Literal['Webhook updated successfully.']]", }, ) WebhookDestroyResponse = TypedDict( - "WebhookDestroyResponse", + 'WebhookDestroyResponse', { - "message": "Required[Literal['Webhook deleted successfully.']]", + 'message': "Required[Literal['Webhook deleted successfully.']]", }, ) WebhookTestResponse = TypedDict( - "WebhookTestResponse", + 'WebhookTestResponse', { - "message": "Required[Literal['Test webhook dispatched successfully. Check the deliveries endpoint for results.']]", - "delivery_id": "Required[str]", + 'message': "Required[Literal['Test webhook dispatched successfully. Check the deliveries endpoint for results.']]", + 'delivery_id': 'Required[str]', }, ) WebhookRegenerateSecretResponse = TypedDict( - "WebhookRegenerateSecretResponse", + 'WebhookRegenerateSecretResponse', { - "data": "Required[WebhookData]", - "message": "Required[Literal['Webhook secret regenerated successfully. Please update your integration.']]", + 'data': 'Required[WebhookData]', + 'message': "Required[Literal['Webhook secret regenerated successfully. Please update your integration.']]", }, ) WebhookDeliveriesResponse = TypedDict( - "WebhookDeliveriesResponse", - { - "data": "Required[list[WebhookDeliveryListData]]", - "path": "Required[str | None]", - "per_page": "Required[int]", - "next_cursor": "Required[str | None]", - "next_page_url": "Required[str | None]", - "prev_cursor": "Required[str | None]", - "prev_page_url": "Required[str | None]", + 'WebhookDeliveriesResponse', + { + 'data': 'Required[list[WebhookDeliveryListData]]', + 'path': 'Required[str | None]', + 'per_page': 'Required[int]', + 'next_cursor': 'Required[str | None]', + 'next_page_url': 'Required[str | None]', + 'prev_cursor': 'Required[str | None]', + 'prev_page_url': 'Required[str | None]', }, ) diff --git a/tests/test_api_surface.py b/tests/test_api_surface.py index c55d0e9..76f10e7 100644 --- a/tests/test_api_surface.py +++ b/tests/test_api_surface.py @@ -3,12 +3,14 @@ from __future__ import annotations import json +from typing import get_args import pytest import respx from httpx import Response from lettermint import AsyncLettermint, Lettermint +from lettermint import types as lm_types class TestV2Entrypoints: @@ -38,6 +40,26 @@ def test_api_entrypoint_uses_bearer_auth_and_raw_ping(self) -> None: assert request.headers["authorization"] == "Bearer api-token" assert "x-lettermint-token" not in request.headers + @respx.mock + def test_api_blocked_file_types_uses_bearer_auth(self) -> None: + route = respx.get("https://api.lettermint.co/v1/blocked-file-types").mock( + return_value=Response( + 200, + json={ + "extensions": ["exe"], + "mime_types": ["application/x-msdownload"], + }, + ) + ) + + with Lettermint.api("api-token") as api: + response = api.blocked_file_types() + + assert response["extensions"] == ["exe"] + request = route.calls.last.request + assert request.headers["authorization"] == "Bearer api-token" + assert "x-lettermint-token" not in request.headers + @respx.mock @pytest.mark.asyncio async def test_async_entrypoints_use_matching_auth(self) -> None: @@ -70,6 +92,7 @@ def test_async_api_exposes_full_endpoint_groups(self) -> None: assert hasattr(api, "suppressions") assert hasattr(api, "team") assert hasattr(api, "webhooks") + assert hasattr(api, "blocked_file_types") class TestSendingEndpoint: @@ -148,6 +171,7 @@ def test_documented_operations_are_exposed(self) -> None: (Lettermint.email("token"), "send_batch"), (Lettermint.email("token"), "ping"), (Lettermint.api("token"), "ping"), + (Lettermint.api("token"), "blocked_file_types"), (Lettermint.api("token").domains, "list"), (Lettermint.api("token").domains, "create"), (Lettermint.api("token").domains, "retrieve"), @@ -198,3 +222,21 @@ def test_documented_operations_are_exposed(self) -> None: missing = [method for endpoint, method in operations if not hasattr(endpoint, method)] assert missing == [] + + def test_generated_types_match_current_team_schema(self) -> None: + assert "auto_replied" in get_args(lm_types.MessageEventType) + assert "message.auto_replied" in get_args(lm_types.WebhookEvent) + assert 300000 in get_args(lm_types.VolumeTier) + assert "global" in get_args(lm_types.SuppressionScope) + + assert "short_token" in lm_types.StoreProjectData.__annotations__ + assert "redact_email_content" in lm_types.ProjectData.__annotations__ + assert "redact_email_content" in lm_types.UpdateProjectData.__annotations__ + assert hasattr(lm_types, "UpdateRouteSettingsData") + assert hasattr(lm_types, "UpdateRouteInboundSettingsData") + assert hasattr(lm_types, "BlockedFileTypesResponse") + assert "extensions" in lm_types.BlockedFileTypesResponse.__annotations__ + assert "mime_types" in lm_types.BlockedFileTypesResponse.__annotations__ + assert "redact_email_content" in lm_types.UpdateRouteSettingsData.__annotations__ + assert "disable_plaintext_generation" in lm_types.UpdateRouteSettingsData.__annotations__ + assert "inbound_spam_threshold" in lm_types.UpdateRouteInboundSettingsData.__annotations__ From 015fdced5a0ee845a64f643ffc195f414e0cfac3 Mon Sep 17 00:00:00 2001 From: bjarn <14638441+bjarn@users.noreply.github.com> Date: Tue, 7 Jul 2026 20:42:11 +0000 Subject: [PATCH 2/3] Fix styling --- src/lettermint/types.py | 1079 ++++++++++++++++++++------------------- 1 file changed, 567 insertions(+), 512 deletions(-) diff --git a/src/lettermint/types.py b/src/lettermint/types.py index fd39e75..56bafca 100644 --- a/src/lettermint/types.py +++ b/src/lettermint/types.py @@ -6,634 +6,689 @@ from typing_extensions import NotRequired, Required, TypeAlias -MessageStatus: TypeAlias = Literal['pending', 'queued', 'suppressed', 'processed', 'delivered', 'opened', 'clicked', 'soft_bounced', 'hard_bounced', 'spam_complaint', 'failed', 'blocked', 'policy_rejected', 'unsubscribed'] +MessageStatus: TypeAlias = Literal[ + "pending", + "queued", + "suppressed", + "processed", + "delivered", + "opened", + "clicked", + "soft_bounced", + "hard_bounced", + "spam_complaint", + "failed", + "blocked", + "policy_rejected", + "unsubscribed", +] SendMailRequest = TypedDict( - 'SendMailRequest', + "SendMailRequest", { - 'route': 'NotRequired[str]', - 'from': 'Required[str]', - 'subject': 'Required[str]', - 'tag': 'NotRequired[str | None]', - 'html': 'NotRequired[str | None]', - 'text': 'NotRequired[str | None]', - 'to': 'Required[list[str]]', - 'cc': 'NotRequired[list[str]]', - 'bcc': 'NotRequired[list[str]]', - 'reply_to': 'NotRequired[list[str]]', - 'headers': 'NotRequired[dict[str, str]]', - 'metadata': 'NotRequired[dict[str, str]]', - 'settings': 'NotRequired[dict[str, Any] | None]', - 'attachments': 'NotRequired[list[dict[str, Any]]]', + "route": "NotRequired[str]", + "from": "Required[str]", + "subject": "Required[str]", + "tag": "NotRequired[str | None]", + "html": "NotRequired[str | None]", + "text": "NotRequired[str | None]", + "to": "Required[list[str]]", + "cc": "NotRequired[list[str]]", + "bcc": "NotRequired[list[str]]", + "reply_to": "NotRequired[list[str]]", + "headers": "NotRequired[dict[str, str]]", + "metadata": "NotRequired[dict[str, str]]", + "settings": "NotRequired[dict[str, Any] | None]", + "attachments": "NotRequired[list[dict[str, Any]]]", }, ) SendBatchMailRequest: TypeAlias = list[dict[str, Any]] -AttachmentDelivery: TypeAlias = Literal['inline', 'url'] -DnsRecordStatus: TypeAlias = Literal['active', 'failed', 'pending'] -RecordType: TypeAlias = Literal['TXT', 'CNAME', 'MX'] +AttachmentDelivery: TypeAlias = Literal["inline", "url"] +DnsRecordStatus: TypeAlias = Literal["active", "failed", "pending"] +RecordType: TypeAlias = Literal["TXT", "CNAME", "MX"] DomainDnsRecordData = TypedDict( - 'DomainDnsRecordData', + "DomainDnsRecordData", { - 'id': 'Required[str]', - 'type': 'Required[RecordType]', - 'hostname': 'Required[str]', - 'fqdn': 'Required[str]', - 'content': 'Required[str]', - 'status': 'Required[DnsRecordStatus]', - 'verified_at': 'Required[str | None]', - 'last_checked_at': 'Required[str | None]', + "id": "Required[str]", + "type": "Required[RecordType]", + "hostname": "Required[str]", + "fqdn": "Required[str]", + "content": "Required[str]", + "status": "Required[DnsRecordStatus]", + "verified_at": "Required[str | None]", + "last_checked_at": "Required[str | None]", }, ) DomainData = TypedDict( - 'DomainData', + "DomainData", { - 'id': 'Required[str]', - 'domain': 'Required[str]', - 'status_changed_at': 'Required[str | None]', - 'dns_records': 'NotRequired[list[DomainDnsRecordData]]', - 'projects': 'NotRequired[list[dict[str, Any]]]', - 'created_at': 'Required[str]', + "id": "Required[str]", + "domain": "Required[str]", + "status_changed_at": "Required[str | None]", + "dns_records": "NotRequired[list[DomainDnsRecordData]]", + "projects": "NotRequired[list[dict[str, Any]]]", + "created_at": "Required[str]", }, ) -DomainStatus: TypeAlias = Literal['verified', 'partially_verified', 'pending_verification', 'failed_verification'] +DomainStatus: TypeAlias = Literal[ + "verified", "partially_verified", "pending_verification", "failed_verification" +] DomainListData = TypedDict( - 'DomainListData', + "DomainListData", { - 'id': 'Required[str]', - 'domain': 'Required[str]', - 'status': 'Required[DomainStatus]', - 'status_changed_at': 'Required[str | None]', - 'created_at': 'Required[str]', + "id": "Required[str]", + "domain": "Required[str]", + "status": "Required[DomainStatus]", + "status_changed_at": "Required[str | None]", + "created_at": "Required[str]", }, ) -InitialRoutes: TypeAlias = Literal['both', 'transactional', 'broadcast'] +InitialRoutes: TypeAlias = Literal["both", "transactional", "broadcast"] MessageAttachmentData = TypedDict( - 'MessageAttachmentData', + "MessageAttachmentData", { - 'size': 'Required[int]', - 'filename': 'Required[str]', - 'content_id': 'Required[str | None]', - 'content_type': 'Required[str]', + "size": "Required[int]", + "filename": "Required[str]", + "content_id": "Required[str | None]", + "content_type": "Required[str]", }, ) MessageRecipientData = TypedDict( - 'MessageRecipientData', + "MessageRecipientData", { - 'email': 'Required[str]', - 'name': 'Required[str | None]', + "email": "Required[str]", + "name": "Required[str | None]", }, ) -MessageType: TypeAlias = Literal['inbound', 'outbound'] +MessageType: TypeAlias = Literal["inbound", "outbound"] SpamSymbol = TypedDict( - 'SpamSymbol', + "SpamSymbol", { - 'name': 'Required[str]', - 'score': 'Required[float]', - 'options': 'Required[list[str]]', - 'description': 'Required[str | None]', + "name": "Required[str]", + "score": "Required[float]", + "options": "Required[list[str]]", + "description": "Required[str | None]", }, ) MessageData = TypedDict( - 'MessageData', - { - 'id': 'Required[str]', - 'type': 'Required[MessageType]', - 'status': 'Required[MessageStatus]', - 'status_changed_at': 'Required[str | None]', - 'tag': 'Required[str | None]', - 'from_email': 'Required[str]', - 'from_name': 'Required[str | None]', - 'reply_to': 'Required[list[str] | None]', - 'subject': 'Required[str | None]', - 'to': 'Required[list[MessageRecipientData] | None]', - 'cc': 'Required[list[MessageRecipientData] | None]', - 'bcc': 'Required[list[MessageRecipientData] | None]', - 'attachments': 'Required[list[MessageAttachmentData] | None]', - 'metadata': 'Required[dict[str, str] | None]', - 'spam_score': 'NotRequired[float | None]', - 'spam_symbols': 'NotRequired[list[SpamSymbol]]', - 'route_id': 'Required[str]', - 'created_at': 'Required[str]', - }, -) - -MessageEventType: TypeAlias = Literal['queued', 'processed', 'suppressed', 'delivered', 'auto_replied', 'soft_bounced', 'hard_bounced', 'spam_complaint', 'failed', 'blocked', 'policy_rejected', 'unsubscribed', 'opened', 'clicked', 'inbound_received', 'inbound_queued', 'inbound_spam_blocked', 'inbound_processed', 'inbound_retry'] + "MessageData", + { + "id": "Required[str]", + "type": "Required[MessageType]", + "status": "Required[MessageStatus]", + "status_changed_at": "Required[str | None]", + "tag": "Required[str | None]", + "from_email": "Required[str]", + "from_name": "Required[str | None]", + "reply_to": "Required[list[str] | None]", + "subject": "Required[str | None]", + "to": "Required[list[MessageRecipientData] | None]", + "cc": "Required[list[MessageRecipientData] | None]", + "bcc": "Required[list[MessageRecipientData] | None]", + "attachments": "Required[list[MessageAttachmentData] | None]", + "metadata": "Required[dict[str, str] | None]", + "spam_score": "NotRequired[float | None]", + "spam_symbols": "NotRequired[list[SpamSymbol]]", + "route_id": "Required[str]", + "created_at": "Required[str]", + }, +) + +MessageEventType: TypeAlias = Literal[ + "queued", + "processed", + "suppressed", + "delivered", + "auto_replied", + "soft_bounced", + "hard_bounced", + "spam_complaint", + "failed", + "blocked", + "policy_rejected", + "unsubscribed", + "opened", + "clicked", + "inbound_received", + "inbound_queued", + "inbound_spam_blocked", + "inbound_processed", + "inbound_retry", +] MessageEventData = TypedDict( - 'MessageEventData', + "MessageEventData", { - 'message_id': 'Required[str]', - 'event': 'Required[MessageEventType]', - 'metadata': 'Required[dict[str, Any] | None]', - 'timestamp': 'Required[str]', + "message_id": "Required[str]", + "event": "Required[MessageEventType]", + "metadata": "Required[dict[str, Any] | None]", + "timestamp": "Required[str]", }, ) MessageListData = TypedDict( - 'MessageListData', + "MessageListData", { - 'id': 'Required[str]', - 'type': 'Required[MessageType]', - 'status': 'Required[MessageStatus]', - 'from_email': 'Required[str]', - 'from_name': 'Required[str | None]', - 'subject': 'Required[str | None]', - 'to': 'Required[list[MessageRecipientData] | None]', - 'cc': 'Required[list[MessageRecipientData] | None]', - 'bcc': 'Required[list[MessageRecipientData] | None]', - 'reply_to': 'Required[list[str] | None]', - 'tag': 'Required[str | None]', - 'created_at': 'Required[str]', + "id": "Required[str]", + "type": "Required[MessageType]", + "status": "Required[MessageStatus]", + "from_email": "Required[str]", + "from_name": "Required[str | None]", + "subject": "Required[str | None]", + "to": "Required[list[MessageRecipientData] | None]", + "cc": "Required[list[MessageRecipientData] | None]", + "bcc": "Required[list[MessageRecipientData] | None]", + "reply_to": "Required[list[str] | None]", + "tag": "Required[str | None]", + "created_at": "Required[str]", }, ) MessageStatsData = TypedDict( - 'MessageStatsData', + "MessageStatsData", { - 'messages_transactional': 'Required[int]', - 'messages_broadcast': 'Required[int]', - 'messages_inbound': 'Required[int]', - 'deliverability': 'Required[float]', + "messages_transactional": "Required[int]", + "messages_broadcast": "Required[int]", + "messages_inbound": "Required[int]", + "deliverability": "Required[float]", }, ) -Plan: TypeAlias = Literal['free', 'starter', 'growth', 'pro'] +Plan: TypeAlias = Literal["free", "starter", "growth", "pro"] UserData = TypedDict( - 'UserData', + "UserData", { - 'id': 'Required[str]', - 'name': 'Required[str]', - 'email': 'Required[str]', - 'avatar': 'Required[str | None]', + "id": "Required[str]", + "name": "Required[str]", + "email": "Required[str]", + "avatar": "Required[str | None]", }, ) TeamMemberData = TypedDict( - 'TeamMemberData', + "TeamMemberData", { - 'id': 'Required[str]', - 'user': 'NotRequired[UserData]', - 'role': 'Required[str | None]', - 'joined_at': 'Required[str | None]', + "id": "Required[str]", + "user": "NotRequired[UserData]", + "role": "Required[str | None]", + "joined_at": "Required[str | None]", }, ) RouteStatisticData = TypedDict( - 'RouteStatisticData', + "RouteStatisticData", { - 'date': 'Required[str]', - 'sent_count': 'Required[int]', - 'delivered_count': 'Required[int]', - 'opened_count': 'Required[int]', - 'clicked_count': 'Required[int]', - 'hard_bounce_count': 'Required[int]', - 'spam_complaint_count': 'Required[int]', - 'inbound_received_count': 'Required[int]', - 'effective_opened_count': 'Required[int | None]', - 'machine_opened_count': 'Required[int | None]', - 'machine_clicked_count': 'Required[int | None]', + "date": "Required[str]", + "sent_count": "Required[int]", + "delivered_count": "Required[int]", + "opened_count": "Required[int]", + "clicked_count": "Required[int]", + "hard_bounce_count": "Required[int]", + "spam_complaint_count": "Required[int]", + "inbound_received_count": "Required[int]", + "effective_opened_count": "Required[int | None]", + "machine_opened_count": "Required[int | None]", + "machine_clicked_count": "Required[int | None]", }, ) -RouteType: TypeAlias = Literal['transactional', 'broadcast', 'inbound'] +RouteType: TypeAlias = Literal["transactional", "broadcast", "inbound"] RouteData = TypedDict( - 'RouteData', - { - 'id': 'Required[str]', - 'project_id': 'Required[str]', - 'slug': 'Required[str]', - 'name': 'Required[str]', - 'route_type': 'Required[RouteType]', - 'is_default': 'Required[bool]', - 'inbound_address': 'NotRequired[str]', - 'inbound_domain': 'NotRequired[str]', - 'inbound_domain_verified_at': 'NotRequired[str]', - 'inbound_spam_threshold': 'NotRequired[float]', - 'attachment_delivery': 'NotRequired[AttachmentDelivery]', - 'project': 'NotRequired[ProjectData]', - 'webhooks_count': 'NotRequired[int]', - 'suppressed_recipients_count': 'NotRequired[int]', - 'statistics': 'NotRequired[dict[str, Any] | list[RouteStatisticData]]', - 'created_at': 'Required[str]', - 'updated_at': 'Required[str]', + "RouteData", + { + "id": "Required[str]", + "project_id": "Required[str]", + "slug": "Required[str]", + "name": "Required[str]", + "route_type": "Required[RouteType]", + "is_default": "Required[bool]", + "inbound_address": "NotRequired[str]", + "inbound_domain": "NotRequired[str]", + "inbound_domain_verified_at": "NotRequired[str]", + "inbound_spam_threshold": "NotRequired[float]", + "attachment_delivery": "NotRequired[AttachmentDelivery]", + "project": "NotRequired[ProjectData]", + "webhooks_count": "NotRequired[int]", + "suppressed_recipients_count": "NotRequired[int]", + "statistics": "NotRequired[dict[str, Any] | list[RouteStatisticData]]", + "created_at": "Required[str]", + "updated_at": "Required[str]", }, ) ProjectData = TypedDict( - 'ProjectData', - { - 'id': 'Required[str]', - 'name': 'Required[str]', - 'smtp_enabled': 'Required[bool]', - 'redact_email_content': 'Required[bool]', - 'default_route_id': 'Required[str | None]', - 'token_generated_at': 'Required[str | None]', - 'token_last_used_at': 'Required[str | None]', - 'token_last_used_ip': 'Required[str | None]', - 'routes': 'NotRequired[list[RouteData]]', - 'routes_count': 'NotRequired[int]', - 'domains': 'NotRequired[list[DomainData]]', - 'domains_count': 'NotRequired[int]', - 'team_members': 'NotRequired[list[TeamMemberData]]', - 'team_members_count': 'NotRequired[int]', - 'last_28_days': 'NotRequired[MessageStatsData | Any]', - 'created_at': 'Required[str]', - 'updated_at': 'Required[str]', + "ProjectData", + { + "id": "Required[str]", + "name": "Required[str]", + "smtp_enabled": "Required[bool]", + "redact_email_content": "Required[bool]", + "default_route_id": "Required[str | None]", + "token_generated_at": "Required[str | None]", + "token_last_used_at": "Required[str | None]", + "token_last_used_ip": "Required[str | None]", + "routes": "NotRequired[list[RouteData]]", + "routes_count": "NotRequired[int]", + "domains": "NotRequired[list[DomainData]]", + "domains_count": "NotRequired[int]", + "team_members": "NotRequired[list[TeamMemberData]]", + "team_members_count": "NotRequired[int]", + "last_28_days": "NotRequired[MessageStatsData | Any]", + "created_at": "Required[str]", + "updated_at": "Required[str]", }, ) ProjectListData = TypedDict( - 'ProjectListData', + "ProjectListData", { - 'id': 'Required[str]', - 'name': 'Required[str]', - 'smtp_enabled': 'Required[bool]', - 'routes_count': 'Required[int]', - 'domains_count': 'Required[int]', - 'team_members_count': 'Required[int]', - 'last_28_days': 'Required[MessageStatsData]', - 'created_at': 'Required[str]', - 'updated_at': 'Required[str]', + "id": "Required[str]", + "name": "Required[str]", + "smtp_enabled": "Required[bool]", + "routes_count": "Required[int]", + "domains_count": "Required[int]", + "team_members_count": "Required[int]", + "last_28_days": "Required[MessageStatsData]", + "created_at": "Required[str]", + "updated_at": "Required[str]", }, ) RouteListData = TypedDict( - 'RouteListData', + "RouteListData", { - 'id': 'Required[str]', - 'slug': 'Required[str]', - 'name': 'Required[str]', - 'route_type': 'Required[RouteType]', - 'is_default': 'Required[bool]', - 'webhooks_count': 'Required[int]', - 'suppressed_recipients_count': 'Required[int]', - 'created_at': 'Required[str]', - 'updated_at': 'Required[str]', + "id": "Required[str]", + "slug": "Required[str]", + "name": "Required[str]", + "route_type": "Required[RouteType]", + "is_default": "Required[bool]", + "webhooks_count": "Required[int]", + "suppressed_recipients_count": "Required[int]", + "created_at": "Required[str]", + "updated_at": "Required[str]", }, ) StatsTypeData = TypedDict( - 'StatsTypeData', + "StatsTypeData", { - 'sent': 'Required[int]', - 'hard_bounced': 'Required[int]', - 'spam_complaints': 'Required[int]', + "sent": "Required[int]", + "hard_bounced": "Required[int]", + "spam_complaints": "Required[int]", }, ) StatsInboundData = TypedDict( - 'StatsInboundData', + "StatsInboundData", { - 'received': 'Required[int]', + "received": "Required[int]", }, ) StatsDailyData = TypedDict( - 'StatsDailyData', + "StatsDailyData", { - 'date': 'Required[str]', - 'sent': 'Required[int]', - 'delivered': 'Required[int]', - 'hard_bounced': 'Required[int]', - 'spam_complaints': 'Required[int]', - 'opened': 'Required[int | None]', - 'clicked': 'Required[int | None]', - 'inbound': 'Required[StatsInboundData]', - 'transactional': 'Required[StatsTypeData | Any]', - 'broadcast': 'Required[StatsTypeData | Any]', - 'effective_opened': 'Required[int | None]', - 'machine_opened': 'Required[int | None]', - 'machine_clicked': 'Required[int | None]', + "date": "Required[str]", + "sent": "Required[int]", + "delivered": "Required[int]", + "hard_bounced": "Required[int]", + "spam_complaints": "Required[int]", + "opened": "Required[int | None]", + "clicked": "Required[int | None]", + "inbound": "Required[StatsInboundData]", + "transactional": "Required[StatsTypeData | Any]", + "broadcast": "Required[StatsTypeData | Any]", + "effective_opened": "Required[int | None]", + "machine_opened": "Required[int | None]", + "machine_clicked": "Required[int | None]", }, ) StatsTotalsData = TypedDict( - 'StatsTotalsData', + "StatsTotalsData", { - 'sent': 'Required[int]', - 'delivered': 'Required[int]', - 'hard_bounced': 'Required[int]', - 'spam_complaints': 'Required[int]', - 'opened': 'Required[int | None]', - 'clicked': 'Required[int | None]', - 'inbound': 'Required[StatsInboundData]', - 'transactional': 'Required[StatsTypeData | Any]', - 'broadcast': 'Required[StatsTypeData | Any]', - 'effective_opened': 'Required[int | None]', - 'machine_opened': 'Required[int | None]', - 'machine_clicked': 'Required[int | None]', + "sent": "Required[int]", + "delivered": "Required[int]", + "hard_bounced": "Required[int]", + "spam_complaints": "Required[int]", + "opened": "Required[int | None]", + "clicked": "Required[int | None]", + "inbound": "Required[StatsInboundData]", + "transactional": "Required[StatsTypeData | Any]", + "broadcast": "Required[StatsTypeData | Any]", + "effective_opened": "Required[int | None]", + "machine_opened": "Required[int | None]", + "machine_clicked": "Required[int | None]", }, ) StatsData = TypedDict( - 'StatsData', + "StatsData", { - 'from': 'Required[str]', - 'to': 'Required[str]', - 'totals': 'Required[StatsTotalsData]', - 'daily': 'Required[list[StatsDailyData]]', + "from": "Required[str]", + "to": "Required[str]", + "totals": "Required[StatsTotalsData]", + "daily": "Required[list[StatsDailyData]]", }, ) StatsRequestData = TypedDict( - 'StatsRequestData', + "StatsRequestData", { - 'from': 'Required[str]', - 'to': 'Required[str]', - 'project_id': 'NotRequired[str | None]', - 'include_machine': 'NotRequired[bool]', + "from": "Required[str]", + "to": "Required[str]", + "project_id": "NotRequired[str | None]", + "include_machine": "NotRequired[bool]", }, ) StoreDomainData = TypedDict( - 'StoreDomainData', + "StoreDomainData", { - 'domain': 'Required[str]', + "domain": "Required[str]", }, ) StoreProjectData = TypedDict( - 'StoreProjectData', + "StoreProjectData", { - 'name': 'Required[str]', - 'smtp_enabled': 'NotRequired[bool]', - 'initial_routes': 'NotRequired[InitialRoutes]', - 'short_token': 'NotRequired[bool]', + "name": "Required[str]", + "smtp_enabled": "NotRequired[bool]", + "initial_routes": "NotRequired[InitialRoutes]", + "short_token": "NotRequired[bool]", }, ) StoreRouteData = TypedDict( - 'StoreRouteData', + "StoreRouteData", { - 'name': 'Required[str]', - 'route_type': 'Required[RouteType]', - 'slug': 'NotRequired[str | None]', + "name": "Required[str]", + "route_type": "Required[RouteType]", + "slug": "NotRequired[str | None]", }, ) -SuppressionScope: TypeAlias = Literal['global', 'team', 'project', 'route'] -SuppressionReason: TypeAlias = Literal['spam_complaint', 'hard_bounce', 'unsubscribe', 'manual'] +SuppressionScope: TypeAlias = Literal["global", "team", "project", "route"] +SuppressionReason: TypeAlias = Literal["spam_complaint", "hard_bounce", "unsubscribe", "manual"] StoreSuppressionData = TypedDict( - 'StoreSuppressionData', - { - 'email': 'NotRequired[str | None]', - 'reason': 'Required[SuppressionReason]', - 'scope': 'Required[SuppressionScope]', - 'route_id': 'NotRequired[str | None]', - 'project_id': 'NotRequired[str | None]', - 'emails': 'NotRequired[list[str] | None]', - }, -) - -WebhookEvent: TypeAlias = Literal['message.created', 'message.sent', 'message.delivered', 'message.auto_replied', 'message.hard_bounced', 'message.soft_bounced', 'message.spam_complaint', 'message.failed', 'message.suppressed', 'message.unsubscribed', 'message.opened', 'message.clicked', 'message.inbound', 'message.policy_rejected', 'webhook.test'] + "StoreSuppressionData", + { + "email": "NotRequired[str | None]", + "reason": "Required[SuppressionReason]", + "scope": "Required[SuppressionScope]", + "route_id": "NotRequired[str | None]", + "project_id": "NotRequired[str | None]", + "emails": "NotRequired[list[str] | None]", + }, +) + +WebhookEvent: TypeAlias = Literal[ + "message.created", + "message.sent", + "message.delivered", + "message.auto_replied", + "message.hard_bounced", + "message.soft_bounced", + "message.spam_complaint", + "message.failed", + "message.suppressed", + "message.unsubscribed", + "message.opened", + "message.clicked", + "message.inbound", + "message.policy_rejected", + "webhook.test", +] StoreWebhookData = TypedDict( - 'StoreWebhookData', + "StoreWebhookData", { - 'route_id': 'Required[str]', - 'name': 'Required[str]', - 'url': 'Required[str]', - 'enabled': 'NotRequired[bool | None]', - 'include_machine_events': 'NotRequired[bool | None]', - 'events': 'Required[list[WebhookEvent]]', + "route_id": "Required[str]", + "name": "Required[str]", + "url": "Required[str]", + "enabled": "NotRequired[bool | None]", + "include_machine_events": "NotRequired[bool | None]", + "events": "Required[list[WebhookEvent]]", }, ) -SuppressionType: TypeAlias = Literal['email', 'domain', 'extension'] +SuppressionType: TypeAlias = Literal["email", "domain", "extension"] SuppressedRecipientData = TypedDict( - 'SuppressedRecipientData', + "SuppressedRecipientData", { - 'id': 'Required[str]', - 'type': 'Required[SuppressionType]', - 'value': 'Required[str]', - 'reason': 'Required[SuppressionReason]', - 'scope': 'Required[SuppressionScope]', - 'project_id': 'Required[str | None]', - 'route_id': 'Required[str | None]', - 'created_at': 'Required[str]', - 'updated_at': 'Required[str]', + "id": "Required[str]", + "type": "Required[SuppressionType]", + "value": "Required[str]", + "reason": "Required[SuppressionReason]", + "scope": "Required[SuppressionScope]", + "project_id": "Required[str | None]", + "route_id": "Required[str | None]", + "created_at": "Required[str]", + "updated_at": "Required[str]", }, ) TeamAddonData = TypedDict( - 'TeamAddonData', + "TeamAddonData", { - 'type': 'Required[str | None]', - 'expires_at': 'Required[str | None]', + "type": "Required[str | None]", + "expires_at": "Required[str | None]", }, ) -TeamType: TypeAlias = Literal['personal', 'business'] +TeamType: TypeAlias = Literal["personal", "business"] VolumeTier: TypeAlias = Literal[300, 10000, 50000, 125000, 300000, 500000, 750000, 1000000, 1500000] TeamData = TypedDict( - 'TeamData', + "TeamData", { - 'id': 'Required[str]', - 'name': 'Required[str]', - 'type': 'Required[TeamType]', - 'plan': 'Required[Plan]', - 'tier': 'Required[VolumeTier]', - 'verified_at': 'Required[str | None]', - 'features': 'NotRequired[list[str]]', - 'addons': 'NotRequired[list[TeamAddonData]]', - 'created_at': 'Required[str]', - 'domains_count': 'NotRequired[int]', - 'projects_count': 'NotRequired[int]', - 'members_count': 'NotRequired[int]', + "id": "Required[str]", + "name": "Required[str]", + "type": "Required[TeamType]", + "plan": "Required[Plan]", + "tier": "Required[VolumeTier]", + "verified_at": "Required[str | None]", + "features": "NotRequired[list[str]]", + "addons": "NotRequired[list[TeamAddonData]]", + "created_at": "Required[str]", + "domains_count": "NotRequired[int]", + "projects_count": "NotRequired[int]", + "members_count": "NotRequired[int]", }, ) TeamUsagePeriodData = TypedDict( - 'TeamUsagePeriodData', + "TeamUsagePeriodData", { - 'usage': 'Required[int]', - 'last_incremented_at': 'Required[str | None]', - 'period_start': 'Required[str]', - 'period_end': 'Required[str]', + "usage": "Required[int]", + "last_incremented_at": "Required[str | None]", + "period_start": "Required[str]", + "period_end": "Required[str]", }, ) TeamUsageDetailData = TypedDict( - 'TeamUsageDetailData', + "TeamUsageDetailData", { - 'current_period': 'Required[TeamUsagePeriodData]', - 'historical_usage': 'Required[list[TeamUsagePeriodData]]', + "current_period": "Required[TeamUsagePeriodData]", + "historical_usage": "Required[list[TeamUsagePeriodData]]", }, ) UpdateDomainProjectsData = TypedDict( - 'UpdateDomainProjectsData', + "UpdateDomainProjectsData", { - 'project_ids': 'Required[list[str]]', + "project_ids": "Required[list[str]]", }, ) UpdateProjectData = TypedDict( - 'UpdateProjectData', + "UpdateProjectData", { - 'name': 'NotRequired[str | None]', - 'smtp_enabled': 'NotRequired[bool | None]', - 'redact_email_content': 'NotRequired[bool | None]', - 'default_route_id': 'NotRequired[str | None]', + "name": "NotRequired[str | None]", + "smtp_enabled": "NotRequired[bool | None]", + "redact_email_content": "NotRequired[bool | None]", + "default_route_id": "NotRequired[str | None]", }, ) UpdateProjectMembersData = TypedDict( - 'UpdateProjectMembersData', + "UpdateProjectMembersData", { - 'team_member_ids': 'Required[list[str]]', + "team_member_ids": "Required[list[str]]", }, ) UpdateRouteInboundSettingsData = TypedDict( - 'UpdateRouteInboundSettingsData', + "UpdateRouteInboundSettingsData", { - 'inbound_domain': 'NotRequired[str | None]', - 'inbound_spam_threshold': 'NotRequired[float | None]', - 'attachment_delivery': 'NotRequired[AttachmentDelivery | Any]', + "inbound_domain": "NotRequired[str | None]", + "inbound_spam_threshold": "NotRequired[float | None]", + "attachment_delivery": "NotRequired[AttachmentDelivery | Any]", }, ) UpdateRouteSettingsData = TypedDict( - 'UpdateRouteSettingsData', + "UpdateRouteSettingsData", { - 'track_opens': 'NotRequired[bool | None]', - 'track_clicks': 'NotRequired[bool | None]', - 'disable_plaintext_generation': 'NotRequired[bool | None]', - 'disable_hosted_unsubscribe': 'NotRequired[bool | None]', - 'redact_email_content': 'NotRequired[bool | None]', + "track_opens": "NotRequired[bool | None]", + "track_clicks": "NotRequired[bool | None]", + "disable_plaintext_generation": "NotRequired[bool | None]", + "disable_hosted_unsubscribe": "NotRequired[bool | None]", + "redact_email_content": "NotRequired[bool | None]", }, ) UpdateRouteData = TypedDict( - 'UpdateRouteData', + "UpdateRouteData", { - 'name': 'NotRequired[str | None]', - 'settings': 'NotRequired[UpdateRouteSettingsData | Any]', - 'inbound_settings': 'NotRequired[UpdateRouteInboundSettingsData | Any]', + "name": "NotRequired[str | None]", + "settings": "NotRequired[UpdateRouteSettingsData | Any]", + "inbound_settings": "NotRequired[UpdateRouteInboundSettingsData | Any]", }, ) UpdateTeamData = TypedDict( - 'UpdateTeamData', + "UpdateTeamData", { - 'name': 'NotRequired[str | None]', + "name": "NotRequired[str | None]", }, ) UpdateWebhookData = TypedDict( - 'UpdateWebhookData', + "UpdateWebhookData", { - 'name': 'NotRequired[str]', - 'url': 'NotRequired[str]', - 'enabled': 'NotRequired[bool]', - 'include_machine_events': 'NotRequired[bool]', - 'events': 'NotRequired[list[WebhookEvent]]', + "name": "NotRequired[str]", + "url": "NotRequired[str]", + "enabled": "NotRequired[bool]", + "include_machine_events": "NotRequired[bool]", + "events": "NotRequired[list[WebhookEvent]]", }, ) WebhookData = TypedDict( - 'WebhookData', + "WebhookData", { - 'id': 'Required[str]', - 'route_id': 'Required[str]', - 'name': 'Required[str]', - 'url': 'Required[str]', - 'events': 'Required[list[str]]', - 'enabled': 'Required[bool]', - 'include_machine_events': 'Required[bool]', - 'secret': 'NotRequired[str]', - 'last_called_at': 'Required[str | None]', - 'created_at': 'Required[str]', - 'updated_at': 'Required[str]', + "id": "Required[str]", + "route_id": "Required[str]", + "name": "Required[str]", + "url": "Required[str]", + "events": "Required[list[str]]", + "enabled": "Required[bool]", + "include_machine_events": "Required[bool]", + "secret": "NotRequired[str]", + "last_called_at": "Required[str | None]", + "created_at": "Required[str]", + "updated_at": "Required[str]", }, ) -WebhookDeliveryStatus: TypeAlias = Literal['pending', 'success', 'failed', 'client_error', 'server_error', 'timeout'] +WebhookDeliveryStatus: TypeAlias = Literal[ + "pending", "success", "failed", "client_error", "server_error", "timeout" +] WebhookDeliveryData = TypedDict( - 'WebhookDeliveryData', + "WebhookDeliveryData", { - 'id': 'Required[str]', - 'webhook_id': 'Required[str]', - 'event_type': 'Required[WebhookEvent]', - 'status': 'Required[WebhookDeliveryStatus]', - 'attempt_number': 'Required[int]', - 'http_status_code': 'Required[int | None]', - 'duration_ms': 'Required[int | None]', - 'payload': 'Required[list[str]]', - 'response_body': 'Required[str | None]', - 'response_headers': 'Required[list[str] | None]', - 'error_message': 'Required[str | None]', - 'delivered_at': 'Required[str | None]', - 'timestamp': 'Required[str]', + "id": "Required[str]", + "webhook_id": "Required[str]", + "event_type": "Required[WebhookEvent]", + "status": "Required[WebhookDeliveryStatus]", + "attempt_number": "Required[int]", + "http_status_code": "Required[int | None]", + "duration_ms": "Required[int | None]", + "payload": "Required[list[str]]", + "response_body": "Required[str | None]", + "response_headers": "Required[list[str] | None]", + "error_message": "Required[str | None]", + "delivered_at": "Required[str | None]", + "timestamp": "Required[str]", }, ) WebhookDeliveryListData = TypedDict( - 'WebhookDeliveryListData', + "WebhookDeliveryListData", { - 'id': 'Required[str]', - 'webhook_id': 'Required[str]', - 'event_type': 'Required[WebhookEvent]', - 'status': 'Required[WebhookDeliveryStatus]', - 'attempt_number': 'Required[int]', - 'http_status_code': 'Required[int | None]', - 'duration_ms': 'Required[int | None]', - 'delivered_at': 'Required[str | None]', - 'created_at': 'Required[str]', + "id": "Required[str]", + "webhook_id": "Required[str]", + "event_type": "Required[WebhookEvent]", + "status": "Required[WebhookDeliveryStatus]", + "attempt_number": "Required[int]", + "http_status_code": "Required[int | None]", + "duration_ms": "Required[int | None]", + "delivered_at": "Required[str | None]", + "created_at": "Required[str]", }, ) WebhookListData = TypedDict( - 'WebhookListData', + "WebhookListData", { - 'id': 'Required[str]', - 'route_id': 'Required[str]', - 'name': 'Required[str]', - 'url': 'Required[str]', - 'events': 'Required[list[WebhookEvent]]', - 'enabled': 'Required[bool]', - 'last_called_at': 'Required[str | None]', - 'created_at': 'Required[str]', - 'updated_at': 'Required[str]', + "id": "Required[str]", + "route_id": "Required[str]", + "name": "Required[str]", + "url": "Required[str]", + "events": "Required[list[WebhookEvent]]", + "enabled": "Required[bool]", + "last_called_at": "Required[str | None]", + "created_at": "Required[str]", + "updated_at": "Required[str]", }, ) EmailAttachment = TypedDict( - 'EmailAttachment', + "EmailAttachment", { - 'filename': 'Required[str]', - 'content': 'Required[str]', - 'content_type': 'NotRequired[str | None]', - 'content_id': 'NotRequired[str | None]', + "filename": "Required[str]", + "content": "Required[str]", + "content_type": "NotRequired[str | None]", + "content_id": "NotRequired[str | None]", }, ) EmailPayload: TypeAlias = SendMailRequest EmailStatus: TypeAlias = MessageStatus SendMailResponse = TypedDict( - 'SendMailResponse', + "SendMailResponse", { - 'message_id': 'Required[str]', - 'status': 'Required[MessageStatus]', + "message_id": "Required[str]", + "status": "Required[MessageStatus]", }, ) SendBatchMailResponse: TypeAlias = list[dict[str, Any]] PingResponse: TypeAlias = Literal[200] DomainIndexResponse = TypedDict( - 'DomainIndexResponse', + "DomainIndexResponse", { - 'data': 'Required[list[DomainListData]]', - 'path': 'Required[str | None]', - 'per_page': 'Required[int]', - 'next_cursor': 'Required[str | None]', - 'next_page_url': 'Required[str | None]', - 'prev_cursor': 'Required[str | None]', - 'prev_page_url': 'Required[str | None]', + "data": "Required[list[DomainListData]]", + "path": "Required[str | None]", + "per_page": "Required[int]", + "next_cursor": "Required[str | None]", + "next_page_url": "Required[str | None]", + "prev_cursor": "Required[str | None]", + "prev_page_url": "Required[str | None]", }, ) @@ -641,295 +696,295 @@ DomainStoreResponse: TypeAlias = DomainData DomainShowResponse: TypeAlias = DomainData DomainDestroyResponse = TypedDict( - 'DomainDestroyResponse', + "DomainDestroyResponse", { - 'message': "Required[Literal['Domain deleted successfully.']]", + "message": "Required[Literal['Domain deleted successfully.']]", }, ) DomainVerifyDnsRecordsResponse = TypedDict( - 'DomainVerifyDnsRecordsResponse', + "DomainVerifyDnsRecordsResponse", { - 'message': 'Required[str]', + "message": "Required[str]", }, ) DomainVerifySpecificDnsRecordResponse = TypedDict( - 'DomainVerifySpecificDnsRecordResponse', + "DomainVerifySpecificDnsRecordResponse", { - 'message': "Required[Literal['DNS record verified successfully.']]", + "message": "Required[Literal['DNS record verified successfully.']]", }, ) DomainUpdateProjectsRequest: TypeAlias = UpdateDomainProjectsData DomainUpdateProjectsResponse = TypedDict( - 'DomainUpdateProjectsResponse', + "DomainUpdateProjectsResponse", { - 'data': 'Required[DomainData]', - 'message': "Required[Literal['Domain projects updated successfully.']]", + "data": "Required[DomainData]", + "message": "Required[Literal['Domain projects updated successfully.']]", }, ) BlockedFileTypesResponse = TypedDict( - 'BlockedFileTypesResponse', + "BlockedFileTypesResponse", { - 'extensions': 'Required[list[str]]', - 'mime_types': 'Required[list[str]]', + "extensions": "Required[list[str]]", + "mime_types": "Required[list[str]]", }, ) MessageIndexResponse: TypeAlias = Union[dict[str, Any], list[MessageListData]] MessageShowResponse: TypeAlias = MessageData MessageEventsResponse = TypedDict( - 'MessageEventsResponse', + "MessageEventsResponse", { - 'data': 'Required[list[MessageEventData]]', - 'path': 'Required[str | None]', - 'per_page': 'Required[int]', - 'next_cursor': 'Required[str | None]', - 'next_page_url': 'Required[str | None]', - 'prev_cursor': 'Required[str | None]', - 'prev_page_url': 'Required[str | None]', + "data": "Required[list[MessageEventData]]", + "path": "Required[str | None]", + "per_page": "Required[int]", + "next_cursor": "Required[str | None]", + "next_page_url": "Required[str | None]", + "prev_cursor": "Required[str | None]", + "prev_page_url": "Required[str | None]", }, ) ProjectIndexResponse = TypedDict( - 'ProjectIndexResponse', + "ProjectIndexResponse", { - 'data': 'Required[list[ProjectListData]]', - 'path': 'Required[str | None]', - 'per_page': 'Required[int]', - 'next_cursor': 'Required[str | None]', - 'next_page_url': 'Required[str | None]', - 'prev_cursor': 'Required[str | None]', - 'prev_page_url': 'Required[str | None]', + "data": "Required[list[ProjectListData]]", + "path": "Required[str | None]", + "per_page": "Required[int]", + "next_cursor": "Required[str | None]", + "next_page_url": "Required[str | None]", + "prev_cursor": "Required[str | None]", + "prev_page_url": "Required[str | None]", }, ) ProjectStoreRequest: TypeAlias = StoreProjectData ProjectStoreResponse = TypedDict( - 'ProjectStoreResponse', + "ProjectStoreResponse", { - 'data': 'Required[ProjectData]', - 'message': "Required[Literal['Project created successfully.']]", - 'api_token': 'Required[str]', + "data": "Required[ProjectData]", + "message": "Required[Literal['Project created successfully.']]", + "api_token": "Required[str]", }, ) ProjectShowResponse: TypeAlias = ProjectData ProjectUpdateRequest: TypeAlias = UpdateProjectData ProjectUpdateResponse = TypedDict( - 'ProjectUpdateResponse', + "ProjectUpdateResponse", { - 'data': 'Required[ProjectData]', - 'message': "Required[Literal['Project updated successfully.']]", + "data": "Required[ProjectData]", + "message": "Required[Literal['Project updated successfully.']]", }, ) ProjectDestroyResponse = TypedDict( - 'ProjectDestroyResponse', + "ProjectDestroyResponse", { - 'message': "Required[Literal['Project deleted successfully.']]", + "message": "Required[Literal['Project deleted successfully.']]", }, ) ProjectRotateTokenResponse = TypedDict( - 'ProjectRotateTokenResponse', + "ProjectRotateTokenResponse", { - 'data': 'Required[ProjectData]', - 'new_token': 'Required[str]', - 'message': "Required[Literal['Project API token rotated successfully. Please update your integrations.']]", + "data": "Required[ProjectData]", + "new_token": "Required[str]", + "message": "Required[Literal['Project API token rotated successfully. Please update your integrations.']]", }, ) ProjectUpdateMembersRequest: TypeAlias = UpdateProjectMembersData ProjectUpdateMembersResponse = TypedDict( - 'ProjectUpdateMembersResponse', + "ProjectUpdateMembersResponse", { - 'data': 'Required[ProjectData]', - 'message': "Required[Literal['Project members updated successfully.']]", + "data": "Required[ProjectData]", + "message": "Required[Literal['Project members updated successfully.']]", }, ) ProjectAddMemberResponse = TypedDict( - 'ProjectAddMemberResponse', + "ProjectAddMemberResponse", { - 'message': "Required[Literal['Team member added to project successfully.']]", + "message": "Required[Literal['Team member added to project successfully.']]", }, ) ProjectRemoveMemberResponse = TypedDict( - 'ProjectRemoveMemberResponse', + "ProjectRemoveMemberResponse", { - 'message': "Required[Literal['Team member removed from project successfully.']]", + "message": "Required[Literal['Team member removed from project successfully.']]", }, ) RouteIndexResponse = TypedDict( - 'RouteIndexResponse', + "RouteIndexResponse", { - 'data': 'Required[list[RouteListData]]', - 'path': 'Required[str | None]', - 'per_page': 'Required[int]', - 'next_cursor': 'Required[str | None]', - 'next_page_url': 'Required[str | None]', - 'prev_cursor': 'Required[str | None]', - 'prev_page_url': 'Required[str | None]', + "data": "Required[list[RouteListData]]", + "path": "Required[str | None]", + "per_page": "Required[int]", + "next_cursor": "Required[str | None]", + "next_page_url": "Required[str | None]", + "prev_cursor": "Required[str | None]", + "prev_page_url": "Required[str | None]", }, ) RouteStoreRequest: TypeAlias = StoreRouteData RouteStoreResponse = TypedDict( - 'RouteStoreResponse', + "RouteStoreResponse", { - 'data': 'Required[RouteData]', - 'message': "Required[Literal['Route created successfully.']]", + "data": "Required[RouteData]", + "message": "Required[Literal['Route created successfully.']]", }, ) RouteShowResponse: TypeAlias = RouteData RouteUpdateRequest: TypeAlias = UpdateRouteData RouteUpdateResponse = TypedDict( - 'RouteUpdateResponse', + "RouteUpdateResponse", { - 'data': 'Required[RouteData]', - 'message': "Required[Literal['Route updated successfully.']]", + "data": "Required[RouteData]", + "message": "Required[Literal['Route updated successfully.']]", }, ) RouteDestroyResponse = TypedDict( - 'RouteDestroyResponse', + "RouteDestroyResponse", { - 'message': "Required[Literal['Route deleted successfully.']]", + "message": "Required[Literal['Route deleted successfully.']]", }, ) RouteVerifyInboundDomainResponse = TypedDict( - 'RouteVerifyInboundDomainResponse', + "RouteVerifyInboundDomainResponse", { - 'data': 'Required[dict[str, Any]]', + "data": "Required[dict[str, Any]]", }, ) StatsIndexResponse: TypeAlias = StatsData SuppressionIndexResponse = TypedDict( - 'SuppressionIndexResponse', + "SuppressionIndexResponse", { - 'data': 'Required[list[SuppressedRecipientData]]', - 'path': 'Required[str | None]', - 'per_page': 'Required[int]', - 'next_cursor': 'Required[str | None]', - 'next_page_url': 'Required[str | None]', - 'prev_cursor': 'Required[str | None]', - 'prev_page_url': 'Required[str | None]', + "data": "Required[list[SuppressedRecipientData]]", + "path": "Required[str | None]", + "per_page": "Required[int]", + "next_cursor": "Required[str | None]", + "next_page_url": "Required[str | None]", + "prev_cursor": "Required[str | None]", + "prev_page_url": "Required[str | None]", }, ) SuppressionStoreRequest: TypeAlias = StoreSuppressionData SuppressionStoreResponse = TypedDict( - 'SuppressionStoreResponse', + "SuppressionStoreResponse", { - 'message': "Required[str | Literal['No emails were added.']]", - 'data': 'Required[dict[str, Any]]', + "message": "Required[str | Literal['No emails were added.']]", + "data": "Required[dict[str, Any]]", }, ) SuppressionDestroyResponse = TypedDict( - 'SuppressionDestroyResponse', + "SuppressionDestroyResponse", { - 'message': "Required[Literal['Email removed from suppression list successfully.']]", + "message": "Required[Literal['Email removed from suppression list successfully.']]", }, ) TeamShowResponse: TypeAlias = TeamData TeamUpdateRequest: TypeAlias = UpdateTeamData TeamUpdateResponse = TypedDict( - 'TeamUpdateResponse', + "TeamUpdateResponse", { - 'data': 'Required[TeamData]', - 'message': "Required[Literal['Team settings updated successfully.']]", + "data": "Required[TeamData]", + "message": "Required[Literal['Team settings updated successfully.']]", }, ) TeamUsageResponse: TypeAlias = TeamUsageDetailData TeamMembersResponse = TypedDict( - 'TeamMembersResponse', + "TeamMembersResponse", { - 'data': 'Required[list[TeamMemberData]]', - 'path': 'Required[str | None]', - 'per_page': 'Required[int]', - 'next_cursor': 'Required[str | None]', - 'next_page_url': 'Required[str | None]', - 'prev_cursor': 'Required[str | None]', - 'prev_page_url': 'Required[str | None]', + "data": "Required[list[TeamMemberData]]", + "path": "Required[str | None]", + "per_page": "Required[int]", + "next_cursor": "Required[str | None]", + "next_page_url": "Required[str | None]", + "prev_cursor": "Required[str | None]", + "prev_page_url": "Required[str | None]", }, ) WebhookIndexResponse = TypedDict( - 'WebhookIndexResponse', + "WebhookIndexResponse", { - 'data': 'Required[list[WebhookListData]]', - 'path': 'Required[str | None]', - 'per_page': 'Required[int]', - 'next_cursor': 'Required[str | None]', - 'next_page_url': 'Required[str | None]', - 'prev_cursor': 'Required[str | None]', - 'prev_page_url': 'Required[str | None]', + "data": "Required[list[WebhookListData]]", + "path": "Required[str | None]", + "per_page": "Required[int]", + "next_cursor": "Required[str | None]", + "next_page_url": "Required[str | None]", + "prev_cursor": "Required[str | None]", + "prev_page_url": "Required[str | None]", }, ) WebhookStoreRequest: TypeAlias = StoreWebhookData WebhookStoreResponse = TypedDict( - 'WebhookStoreResponse', + "WebhookStoreResponse", { - 'data': 'Required[WebhookData]', - 'message': "Required[Literal['Webhook created successfully. Please save the secret as it will not be shown again.']]", + "data": "Required[WebhookData]", + "message": "Required[Literal['Webhook created successfully. Please save the secret as it will not be shown again.']]", }, ) WebhookShowResponse: TypeAlias = WebhookData WebhookUpdateRequest: TypeAlias = UpdateWebhookData WebhookUpdateResponse = TypedDict( - 'WebhookUpdateResponse', + "WebhookUpdateResponse", { - 'data': 'Required[WebhookData]', - 'message': "Required[Literal['Webhook updated successfully.']]", + "data": "Required[WebhookData]", + "message": "Required[Literal['Webhook updated successfully.']]", }, ) WebhookDestroyResponse = TypedDict( - 'WebhookDestroyResponse', + "WebhookDestroyResponse", { - 'message': "Required[Literal['Webhook deleted successfully.']]", + "message": "Required[Literal['Webhook deleted successfully.']]", }, ) WebhookTestResponse = TypedDict( - 'WebhookTestResponse', + "WebhookTestResponse", { - 'message': "Required[Literal['Test webhook dispatched successfully. Check the deliveries endpoint for results.']]", - 'delivery_id': 'Required[str]', + "message": "Required[Literal['Test webhook dispatched successfully. Check the deliveries endpoint for results.']]", + "delivery_id": "Required[str]", }, ) WebhookRegenerateSecretResponse = TypedDict( - 'WebhookRegenerateSecretResponse', + "WebhookRegenerateSecretResponse", { - 'data': 'Required[WebhookData]', - 'message': "Required[Literal['Webhook secret regenerated successfully. Please update your integration.']]", + "data": "Required[WebhookData]", + "message": "Required[Literal['Webhook secret regenerated successfully. Please update your integration.']]", }, ) WebhookDeliveriesResponse = TypedDict( - 'WebhookDeliveriesResponse', - { - 'data': 'Required[list[WebhookDeliveryListData]]', - 'path': 'Required[str | None]', - 'per_page': 'Required[int]', - 'next_cursor': 'Required[str | None]', - 'next_page_url': 'Required[str | None]', - 'prev_cursor': 'Required[str | None]', - 'prev_page_url': 'Required[str | None]', + "WebhookDeliveriesResponse", + { + "data": "Required[list[WebhookDeliveryListData]]", + "path": "Required[str | None]", + "per_page": "Required[int]", + "next_cursor": "Required[str | None]", + "next_page_url": "Required[str | None]", + "prev_cursor": "Required[str | None]", + "prev_page_url": "Required[str | None]", }, ) From f01d8c4259e0f601a8c56e744eca0fc5e566a42d Mon Sep 17 00:00:00 2001 From: Bjarn Bronsveld Date: Tue, 7 Jul 2026 23:00:06 +0200 Subject: [PATCH 3/3] refactor: replace `TYPE_CHECKING` import and add type casting for blocked file types --- src/lettermint/lettermint.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/lettermint/lettermint.py b/src/lettermint/lettermint.py index bb23648..90010f4 100644 --- a/src/lettermint/lettermint.py +++ b/src/lettermint/lettermint.py @@ -3,13 +3,14 @@ from __future__ import annotations import sys -from typing import TYPE_CHECKING, Any +from typing import Any, cast if sys.version_info >= (3, 11): from typing import Self else: from typing_extensions import Self +from . import types as lm_types from .client import AsyncLettermintClient, LettermintClient from .endpoints.api import ( AsyncDomainsEndpoint, @@ -31,9 +32,6 @@ ) from .endpoints.email import AsyncEmailEndpoint, EmailEndpoint -if TYPE_CHECKING: - from . import types as lm_types - class _EmailAccessor: def __get__(self, instance: Lettermint | None, owner: type[Lettermint]) -> Any: @@ -91,7 +89,10 @@ def ping(self) -> str: return self._client.get_raw("/ping").strip() def blocked_file_types(self) -> lm_types.BlockedFileTypesResponse: - return self._client.get("/blocked-file-types") + return cast( + lm_types.BlockedFileTypesResponse, + self._client.get("/blocked-file-types"), + ) class AsyncApiClient: @@ -132,7 +133,10 @@ async def ping(self) -> str: return (await self._client.get_raw("/ping")).strip() async def blocked_file_types(self) -> lm_types.BlockedFileTypesResponse: - return await self._client.get("/blocked-file-types") + return cast( + lm_types.BlockedFileTypesResponse, + await self._client.get("/blocked-file-types"), + ) class Lettermint: