Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -292,10 +292,22 @@ print(resent["message_id"]) # the new message; it links back through resent_fro
| `suppressions` | `list`, `iterate`, `create`, `delete` |
| `team` | `retrieve`, `update`, `usage`, `roles` |
| `team.members` | `list`, `iterate`, `retrieve`, `update_assignment` |
| `team.invites` | `list`, `iterate`, `retrieve`, `create`, `update`, `revoke` |
| `webhooks` | `list`, `iterate`, `create`, `retrieve`, `update`, `delete`, `test`, `regenerate_secret` |
| `webhooks.deliveries` | `list(webhook_id)`, `iterate(webhook_id)`, `retrieve(webhook_id, delivery_id)`, `retry(webhook_id, delivery_id)` |
| (root) | `ping`, `analytics`, `analytics_pages`, `blocked_file_types` |

`team.invites.create()` invites a person to the team with a role and project access, and emails the invitation. The team needs a free seat, and the Owner role cannot be assigned. `team.invites.update()` replaces the email address, role and project access of a pending invite; it sends a new email only when the address changes. `team.invites.revoke()` revokes it.

```python
invite = lettermint.team.invites.create({
"email": "jane@acme.com",
"role_id": "role-id",
"project_access": {"scope": "selected", "project_ids": ["project-id"]},
})
lettermint.team.invites.revoke(invite["id"])
```

`webhooks.deliveries.retry()` sends a delivery's original payload to the webhook again now. The retry counts as a delivery attempt; if it fails with a retryable error, the automatic retries continue. The API answers `409` (`ConflictError`) when the webhook is disabled, the delivery cannot be retried or a retry is already in progress.

### Query parameters and pagination
Expand Down
4 changes: 4 additions & 0 deletions src/lettermint/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
AsyncStats,
AsyncSuppressions,
AsyncTeam,
AsyncTeamInvites,
AsyncTeamMembers,
AsyncWebhookDeliveries,
AsyncWebhooks,
Expand All @@ -48,6 +49,7 @@
Stats,
Suppressions,
Team,
TeamInvites,
TeamMembers,
WebhookDeliveries,
Webhooks,
Expand Down Expand Up @@ -89,6 +91,7 @@
"AsyncStats",
"AsyncSuppressions",
"AsyncTeam",
"AsyncTeamInvites",
"AsyncTeamMembers",
"AsyncWebhookDeliveries",
"AsyncWebhooks",
Expand Down Expand Up @@ -118,6 +121,7 @@
"Stats",
"Suppressions",
"Team",
"TeamInvites",
"TeamMembers",
"UnexpectedResponseError",
"ValidationError",
Expand Down
2 changes: 2 additions & 0 deletions src/lettermint/_async/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
AsyncStats,
AsyncSuppressions,
AsyncTeam,
AsyncTeamInvites,
AsyncTeamMembers,
AsyncWebhookDeliveries,
AsyncWebhooks,
Expand All @@ -30,6 +31,7 @@
"AsyncStats",
"AsyncSuppressions",
"AsyncTeam",
"AsyncTeamInvites",
"AsyncTeamMembers",
"AsyncWebhookDeliveries",
"AsyncWebhooks",
Expand Down
86 changes: 86 additions & 0 deletions src/lettermint/_async/resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

from .._generated.operations import OPERATIONS
from .._generated.types import (
CreateTeamInviteData,
DeleteSuppressionResponse,
DnsVerificationSuccessResponse,
DomainData,
Expand All @@ -37,6 +38,8 @@
ListRoutesResponse,
ListSuppressionsQuery,
ListSuppressionsResponse,
ListTeamInvitesQuery,
ListTeamInvitesResponse,
ListTeamMembersQuery,
ListTeamMembersResponse,
ListWebhookDeliveriesQuery,
Expand Down Expand Up @@ -72,6 +75,7 @@
SuppressedRecipientData,
SuppressionStoreResponse,
TeamData,
TeamInviteData,
TeamMemberData,
TeamMutationResponse,
TeamRoleListResponse,
Expand All @@ -82,6 +86,7 @@
UpdateReportForwardingResponse,
UpdateRouteData,
UpdateTeamData,
UpdateTeamInviteData,
UpdateTeamMemberAssignmentData,
UpdateWebhookData,
VerifyReportForwardingRequest,
Expand All @@ -106,6 +111,7 @@
"AsyncStats",
"AsyncSuppressions",
"AsyncTeam",
"AsyncTeamInvites",
"AsyncTeamMembers",
"AsyncWebhookDeliveries",
"AsyncWebhooks",
Expand Down Expand Up @@ -800,13 +806,93 @@ async def update_assignment(
)


class AsyncTeamInvites(AsyncResource):
"""Pending invitations to the team. Team token."""

async def list(
self, query: ListTeamInvitesQuery | None = None, *, timeout: float | None = None
) -> ListTeamInvitesResponse:
"""Lists pending invites, one page at a time."""
return cast(
ListTeamInvitesResponse,
await self._request(
"GET /team/invites", "team.invites.list", query=query, timeout=timeout
),
)

def iterate(
self, query: ListTeamInvitesQuery | None = None, *, timeout: float | None = None
) -> AsyncIterator[TeamInviteData]:
"""Iterates over every pending invite, following ``next_cursor``."""
return self._paginate(
"GET /team/invites", "team.invites.iterate", query=query, timeout=timeout
)

async def retrieve(self, invite_id: str, *, timeout: float | None = None) -> TeamInviteData:
return cast(
TeamInviteData,
await self._request(
"GET /team/invites/{inviteId}",
"team.invites.retrieve",
path={"inviteId": invite_id},
timeout=timeout,
),
)

async def create(
self, body: CreateTeamInviteData, *, timeout: float | None = None
) -> TeamInviteData:
"""Invites a person to the team and emails the invitation.

The team needs a free seat, and the Owner role cannot be assigned.
"""
return cast(
TeamInviteData,
await self._request(
"POST /team/invites", "team.invites.create", body=body, timeout=timeout
),
)

async def update(
self, invite_id: str, body: UpdateTeamInviteData, *, timeout: float | None = None
) -> TeamInviteData:
"""Replaces the email address, role and project access of a pending invite.

A new invitation email is sent only when the address changes.
"""
return cast(
TeamInviteData,
await self._request(
"PUT /team/invites/{inviteId}",
"team.invites.update",
path={"inviteId": invite_id},
body=body,
timeout=timeout,
),
)

async def revoke(self, invite_id: str, *, timeout: float | None = None) -> MessageResponse:
"""Revokes a pending invite."""
return cast(
MessageResponse,
await self._request(
"DELETE /team/invites/{inviteId}",
"team.invites.revoke",
path={"inviteId": invite_id},
timeout=timeout,
),
)


class AsyncTeam(AsyncResource):
"""The team of the token. Team token."""

def __init__(self, transport: AsyncTransport) -> None:
super().__init__(transport)
#: Team members.
self.members = AsyncTeamMembers(transport)
#: Pending invitations to the team.
self.invites = AsyncTeamInvites(transport)

async def retrieve(
self, query: GetTeamQuery | None = None, *, timeout: float | None = None
Expand Down
4 changes: 2 additions & 2 deletions src/lettermint/_generated/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Generated by lettermint/sdk-generator — do not edit.
# Spec: lettermint/lettermint@6ef4036dede6326ad2200b945e689e319faf4c0a (main)
# Spec: lettermint/lettermint@a14a098fd3173b67bc366163127ee3715457cd59 (main)
# sending-openapi.json SHA-256: 8d5e962e57d79ab08be52147c094657b681768f06940a76c8eec1b1e03df54cc
# team-openapi.json SHA-256: 4ba5b65756faa9db79e5b95e06414899af0a6e97766eed04656c1b778f28aef7
# team-openapi.json SHA-256: da4398ead370c9b61eadb4007087a6da945df3c609801325fd38fc780cc0e707
# Naming profile: next
"""Generated from the Lettermint OpenAPI specifications. Do not edit; regenerate."""
Loading
Loading