openemail.members
Çdo metodë në këtë hapësirë emrash: nënshkrimi, parametrat, çfarë kthen dhe një shembull.
Metodat
People who share the workspace, their role and the addresses they may use, and the invitations still waiting.
members.list()members.list_all()members.iterate()members.get()members.add()members.update()members.remove()members.grant_address()members.revoke_address()members.grant_domain()members.revoke_domain()members.list_invitations()members.list_all_invitations()members.iterate_invitations()members.revoke_invitation()members.resend_invitation()
members.list()
List everybody with access to the workspace
def list( *, limit: int | None = None, cursor: str | None = None, api_key: str | None = None, timeout: float | None = None,) -> Page[MemberResource]Returns one page of the workspace's members, the owner first and the rest by email. list_all collects every page into one list and iterate walks them lazily. Each row carries two axes that a client must not merge: role and permissions say what the person may do, and addresses and domains say what they may do it to, each with its own access. A whole domain reaches every address on it, including ones made later. A send needs both axes, so emails:send with nothing granted sends from nothing.
The one exception is addresses:all. When permissions holds it, the person reaches every address on every domain of the workspace, including ones added later, and sends as any of them when permissions also holds emails:send. addresses and domains still list only the grants made to them directly, which they may have kept from before or been given since, or none at all. Read reach from permissions first, and from those two lists only when it lacks addresses:all.
The list is a union of people with a membership row and people who only hold address or domain grants and no membership row. The second group comes back with implied set to True and with role['id'] and createdAt set to None, and their role is inferred from their grants: Member if any grant has access set to member, Viewer otherwise. Until someone calls update for them, widening their addresses silently widens what they may do.
The workspace owner is the FIRST row, with isOwner set to True, so an unshared workspace returns one member rather than an empty page. They hold every permission by definition, and add, update and remove refuse them with member_is_owner. Skip the row whose isOwner is True when counting seats.
Parametrat
limitintPage size, from 1 to 100. The server defaults to 25.
cursorstrThe
nextCursorof the previous page. Leave it out for the first page.api_keystrOverrides the client API key for this call only.
timeoutfloatSeconds this call may take, the response included, before it raises
OpenEmailNetworkErrorwithis_timeout. It overrides the client'stimeoutfor this call, and0turns the limit off.
Kthen
Page[MemberResource], a dict with items, hasMore and nextCursor. Each item has userId, email, name, image, isOwner, role, implied, permissions, addresses, domains and createdAt.
Shembull
from openemail import openemail page = openemail.members.list(limit=50) for member in page['items']: if member['implied']: print(member['email'], member['role']['name'], len(member['addresses'])) if page['hasMore']: print('more after', page['nextCursor'])Shënime
Every other method here takes
user_id, the account id inuserId, not the email address.An address granted with
accessset toviewerblocks sending from it even when the role holdsemails:send, unless the role also holdsaddresses:all. Otherwise the two axes are ANDed, never added.The cursor is opaque and holds where the last row sat in this order, so a row deleted or edited between pages never breaks the walk: the next page starts at the first row that sorts after it. A cursor this list did not hand out is a 400
invalid_cursor.
E disponueshme edhe në
- API
GET /members- TypeScript
members.list()- Ruby
members.list- CLI
openemail members list
members.list_all()
Collect every member into one list
def list_all( *, limit: int | None = None, cursor: str | None = None, api_key: str | None = None, timeout: float | None = None,) -> builtins.list[MemberResource]Walks every page of list and returns all members in one list, the owner first and the rest by email. One request per page.
Parametrat
limitintPage size for each request, from 1 to 100. The server defaults to 25.
cursorstrStarts the walk after this cursor instead of the first page.
api_keystrOverrides the client API key for every page of this walk.
timeoutfloatSeconds this call may take, the response included, before it raises
OpenEmailNetworkErrorwithis_timeout. It overrides the client'stimeoutfor this call, and0turns the limit off.
Kthen
list[MemberResource] holding every member.
Shembull
from openemail import openemail members = openemail.members.list_all(limit=100)seats = [member for member in members if not member['isOwner']] print(len(seats), 'seats in use')Shënime
If any page fails, the call raises and the members already fetched are discarded.
E disponueshme edhe në
- API
GET /members- TypeScript
members.listAll()- Ruby
members.list_all
members.iterate()
Stream the members one at a time
def iterate( *, limit: int | None = None, cursor: str | None = None, api_key: str | None = None, timeout: float | None = None,) -> Iterator[MemberResource]Returns a generator that yields members one at a time, the owner first and the rest by email, and requests the next page only once the current one is used up. Nothing is fetched until the loop starts, and breaking out of it stops the requests.
Parametrat
limitintPage size for each request, from 1 to 100. The server defaults to 25.
cursorstrStarts the walk after this cursor instead of the first page.
api_keystrOverrides the client API key for every page of this walk.
timeoutfloatSeconds this call may take, the response included, before it raises
OpenEmailNetworkErrorwithis_timeout. It overrides the client'stimeoutfor this call, and0turns the limit off.
Kthen
Iterator[MemberResource], a generator yielding one member per step.
Shembull
from openemail import openemail for member in openemail.members.iterate(): addresses = [grant['address'] for grant in member['addresses']] print(member['email'], member['role']['name'], addresses)Shënime
The generator is lazy, so an abandoned loop costs only the pages you consumed.
E disponueshme edhe në
- API
GET /members- TypeScript
members.iterate()- Ruby
members.iterate
members.get()
Read one member by account id
def get( user_id: str, *, api_key: str | None = None, timeout: float | None = None,) -> MemberResourceReturns a single member with their role, resolved permissions and address grants. The lookup runs over the same union as list, so a legacy grant holder with no membership row is found here too, with implied set to True, and the owner's account id returns their row, with isOwner set to True.
The path takes the account id from list, not an email. An email can change on the account, and a stale one would point at the wrong person.
Parametrat
user_idstrE detyrueshmeThe account id from
list, not the email address.api_keystrOverrides the client API key for this call only.
timeoutfloatSeconds this call may take, the response included, before it raises
OpenEmailNetworkErrorwithis_timeout. It overrides the client'stimeoutfor this call, and0turns the limit off.
Kthen
MemberResource with role (id, name, builtin), implied, the resolved permissions, and addresses holding addressId, address and access.
Shembull
from openemail import openemail member = openemail.members.get('q7Vd3kX9mT2pLw8RzN4bYc6HfJ1sGa5E') print(member['role']['name'], member['implied'])print([(grant['address'], grant['access']) for grant in member['addresses']])Shënime
A missing member is 404
resource_not_found.For an implied member,
permissionsare the Member or Viewer template permissions, not a stored role thatroles.getcould read.
E disponueshme edhe në
- API
GET /members/{userId}- TypeScript
members.get()- Ruby
members.get- CLI
openemail members get
members.add()
Invite somebody to the workspace with a role
def add( body: MemberAdd, *, api_key: str | None = None, timeout: float | None = None,) -> InvitationResourceSends an invitation to join the workspace. Whether or not the address already has an OpenEmail account, the answer is an invitation rather than a member: nobody is put into a workspace without accepting, and this method is held to the same rule as the app.
The invitation carries the role, the addresses and the whole domains you name, and grants exactly those the moment it is accepted. Nothing is granted before that. Calling it again for the same address within ten minutes is refused with 409 invitation_too_soon. After that it refreshes the one outstanding invitation rather than sending a second.
Somebody already in the workspace is refused with 422 member_is_owner. Change what an existing member may do with update, grant_address and revoke_address, which only work on people already in.
Role and grants are separate axes. access applies to every id in addressIds and domainIds, and it never widens the role: an access of member under a role without emails:send still cannot send. A role holding addresses:all reaches every address without any ids, and no key or access token can invite with one, because none of them holds that console-only permission.
Parametrat
body['email']strE detyrueshmeWho to invite. Trimmed and lowercased. It does not need to have an account yet.
body['roleId']strE detyrueshmeRole id from
roles.list. The owner role is refused with 409role_immutable, and a role holding more than the key itself holds is refused with 403insufficient_authority. That covers every role with a console-only permission in it, such asaddresses:all.body['addressIds']list[str]Up to 64 address ids on this workspace the invitation carries, all at
access.body['domainIds']list[str]Up to 64 domain ids on this workspace the invitation carries, all at
access. A whole domain covers every address on it, including ones made later.body['access']MemberAccessmemberreads and sends as the granted addresses,vieweronly reads them. Defaults tomember.api_keystrOverrides the client API key for this call only.
timeoutfloatSeconds this call may take, the response included, before it raises
OpenEmailNetworkErrorwithis_timeout. It overrides the client'stimeoutfor this call, and0turns the limit off.
Kthen
InvitationResource, answered with a 202: the invitation id, what it carries, when it expires, and delivered, which is False when the email did not leave the mail server.
Shembull
from openemail import openemail invitation = openemail.members.add( { 'email': '[email protected]', 'roleId': 'role_8b1f4c2e9a7d3b60e5f1a2c4', 'domainIds': ['93542ff8-2baa-4f2f-841d-5ceaa074ab0d'], 'access': 'member', }) print(invitation['id'], invitation['delivered'], invitation['expiresAt'])Shënime
An unknown
roleIdis 404role_not_foundwithparamset toroleId. An address or domain id that is not on this workspace is 422member_not_foundwithparamset toaddressIdordomainId.The workspace owner, and anybody already in the workspace, is refused with 422
member_is_owner.deliveredset toFalsemeans the invitation exists but the email did not go out. Send it again withresend_invitation, or from the app, once the ten minute cooldown has passed.An OAuth access token needs a verification code for this call, and is refused with 403
step_up_requireduntil the app has verified one in the last 60 minutes.is_step_up_requiredon the error says so. An API key is never asked for a code.Not retried automatically. Re-posting the same body inside ten minutes is 409 rather than a duplicate.
E disponueshme edhe në
- API
POST /members- TypeScript
members.add()- Ruby
members.add- CLI
openemail members add
members.update()
Change the role a member holds
def update( user_id: str, patch: MemberPatch, *, api_key: str | None = None, timeout: float | None = None,) -> MemberResourceMoves a member to a different role and changes nothing else, for somebody ALREADY in the workspace. Their address and domain grants are untouched, and grants cannot be patched here at all: grant_address and revoke_address change one grant at a time.
This is also how a legacy grant holder stops being implied. They have address or domain grants and no membership row, this writes one, and from then on implied is False and their permissions come from a role someone chose rather than from what their access implied.
Nobody joins through update. An account that is not in the workspace is 422 member_not_found: invite them with add and they are in once they accept. The owner role cannot be handed out, which is 409 role_immutable, and the workspace owner cannot be given a role, which is 422 member_is_owner.
Parametrat
user_idstrE detyrueshmeThe account id from
list, not the email address.patch['roleId']strE detyrueshmeId of the role to move them to.
api_keystrOverrides the client API key for this call only.
timeoutfloatSeconds this call may take, the response included, before it raises
OpenEmailNetworkErrorwithis_timeout. It overrides the client'stimeoutfor this call, and0turns the limit off.
Kthen
MemberResource with the new role and permissions, and implied set to False.
Shembull
from openemail import openemail member = openemail.members.update( 'q7Vd3kX9mT2pLw8RzN4bYc6HfJ1sGa5E', {'roleId': 'role_2c7e9a1f4b8d3e60c5a7f1b9'}) print(member['role']['name'], member['implied'])Shënime
The account has to be in the workspace already, by membership row or by a grant. Anybody else is 422
member_not_found. Useaddto invite them.An unknown
roleIdis 404role_not_found, and a user id with no OpenEmail account behind it is 404user_not_found.A role holding more than the key itself holds is 403
insufficient_authority. No key or access token holds a console-only permission, so a role withaddresses:all, billing orworkspace:managein it is handed out only in the app. That includes the seeded Admin, which holds billing.An OAuth access token needs a verification code for this call, and is refused with 403
step_up_requireduntil the app has verified one in the last 60 minutes.is_step_up_requiredon the error says so. An API key is never asked for a code.Retried automatically on network failure, since it names the role it wants and a replay lands on the same row.
E disponueshme edhe në
- API
PATCH /members/{userId}- TypeScript
members.update()- Ruby
members.update- CLI
openemail members update
members.remove()
Remove a member and every address grant they hold
def remove( user_id: str, *, api_key: str | None = None, timeout: float | None = None,) -> RemovedMemberResourceTakes somebody out of the workspace entirely: the membership row and every address grant they hold on it. Removing only the row would drop them from the list while they kept reading the mail, so both go together.
It does not 404 for somebody who is not a member. The people this most needs to reach are legacy grant holders with no membership row, so there is no existence check, and addressesRevoked reports what actually happened. Zero is the honest answer for a no-op.
Their account, their sent mail and anything they wrote are untouched. Only their access to this workspace ends.
Parametrat
user_idstrE detyrueshmeThe account id from
list, not the email address.api_keystrOverrides the client API key for this call only.
timeoutfloatSeconds this call may take, the response included, before it raises
OpenEmailNetworkErrorwithis_timeout. It overrides the client'stimeoutfor this call, and0turns the limit off.
Kthen
RemovedMemberResource with object set to member, the userId, deleted set to True and addressesRevoked.
Shembull
from openemail import openemail removed = openemail.members.remove('q7Vd3kX9mT2pLw8RzN4bYc6HfJ1sGa5E') print(removed['deleted'], removed['addressesRevoked'])Shënime
Idempotent on the server, but the SDK does not retry it automatically, so repeat it yourself after a network failure.
The workspace owner is refused with 422
member_is_owner, because their access never came from a membership.An OAuth access token needs a verification code for this call, and is refused with 403
step_up_requireduntil the app has verified one in the last 60 minutes.is_step_up_requiredon the error says so. An API key is never asked for a code.
E disponueshme edhe në
- API
DELETE /members/{userId}- TypeScript
members.remove()- Ruby
members.remove- CLI
openemail members remove
members.grant_address()
Grant a member one address or change their access to it
def grant_address( user_id: str, body: MemberAddressGrant, *, api_key: str | None = None, timeout: float | None = None,) -> MemberResourceGives one person one address on this workspace, or changes the access they already have to it. It is an upsert: there is one grant per person and address, so posting again with a different access turns a viewer into a member rather than adding a second grant.
This is the address axis and it cannot widen the role. An access of member lets somebody send as the address only if their role also holds emails:send, and otherwise it lets them read.
Granting an address to an account with no membership row makes them appear in list as an implied member whose role is inferred from their grants, so call update as well if the role should be a decision. The whole member comes back, which lets a client redraw the row without another read.
Parametrat
user_idstrE detyrueshmeThe account id from
list, not the email address.body['addressId']strE detyrueshmeId of an address on this workspace.
body['access']MemberAccessmemberreads and sends as the address,vieweronly reads it. Defaults tomember.api_keystrOverrides the client API key for this call only.
timeoutfloatSeconds this call may take, the response included, before it raises
OpenEmailNetworkErrorwithis_timeout. It overrides the client'stimeoutfor this call, and0turns the limit off.
Kthen
MemberResource with the grant applied, including the full addresses list.
Shembull
from openemail import openemail member = openemail.members.grant_address( 'q7Vd3kX9mT2pLw8RzN4bYc6HfJ1sGa5E', {'addressId': '4f0c1b6e-2d7a-4a9e-8c35-91b2e7d4f6a0', 'access': 'viewer'},) print([(grant['address'], grant['access']) for grant in member['addresses']])Shënime
An address id that is not on this workspace is 422 with code
member_not_foundandparamset toaddressId.The workspace owner is refused with 422
member_is_owner, since they already reach every address. A user id with no OpenEmail account behind it is 404user_not_found.Gated on
members:writerather than on owning the address, so an admin who owns nothing can still manage grants.An OAuth access token needs a verification code for this call, and is refused with 403
step_up_requireduntil the app has verified one in the last 60 minutes.is_step_up_requiredon the error says so. An API key is never asked for a code.Retried automatically on network failure, since replaying the same grant lands on the same row.
E disponueshme edhe në
members.revoke_address()
Take one address back from a member
def revoke_address( user_id: str, address_id: str, *, api_key: str | None = None, timeout: float | None = None,) -> MemberResourceRemoves one address grant and leaves the person in the workspace with their role and their other addresses. This is the narrow revocation to use when somebody changes team.
An address id that is not on this workspace is refused with 422 member_not_found rather than ignored, so a typo cannot report a revocation that never happened. An address that is on the workspace but was never granted to this person is a silent no-op, and the member comes back unchanged.
The member is returned rather than a tombstone, because the useful answer is what they can still reach.
Parametrat
user_idstrE detyrueshmeThe account id from
list, not the email address.address_idstrE detyrueshmeId of an address on this workspace.
api_keystrOverrides the client API key for this call only.
timeoutfloatSeconds this call may take, the response included, before it raises
OpenEmailNetworkErrorwithis_timeout. It overrides the client'stimeoutfor this call, and0turns the limit off.
Kthen
MemberResource with the remaining addresses.
Shembull
from openemail import openemail member = openemail.members.revoke_address( 'q7Vd3kX9mT2pLw8RzN4bYc6HfJ1sGa5E', '4f0c1b6e-2d7a-4a9e-8c35-91b2e7d4f6a0') print([grant['address'] for grant in member['addresses']])Shënime
Revoking the last grant of an implied member removes them from the workspace entirely. The call still succeeds and returns the member as they stood, without that address.
Somebody who is not a member of this workspace is a 404.
An OAuth access token needs a verification code for this call, and is refused with 403
step_up_requireduntil the app has verified one in the last 60 minutes.is_step_up_requiredon the error says so. An API key is never asked for a code.Not retried automatically by the SDK.
E disponueshme edhe në
members.grant_domain()
Grant a member a whole domain or change their access to it
def grant_domain( user_id: str, body: MemberDomainGrant, *, api_key: str | None = None, timeout: float | None = None,) -> MemberResourceGives one person every address on one domain of this workspace, including addresses added after the grant, or changes the access they already have to it. It is an upsert: there is one grant per person and domain, so calling it again with a different access turns a viewer into a member rather than adding a second grant.
This is the address axis and it cannot widen the role. An access of member lets somebody send from the domain only if their role also holds emails:send, and otherwise it lets them read.
The person has to be in the workspace already, so invite them with add first. The whole member comes back, with the grant in domains.
Parametrat
user_idstrE detyrueshmeThe account id from
list, not the email address.body['domainId']strE detyrueshmeId of a domain on this workspace, as
domains.listreturns it.body['access']MemberAccessmemberreads and sends from the domain,vieweronly reads it. Defaults tomember.api_keystrOverrides the client API key for this call only.
timeoutfloatSeconds this call may take, the response included, before it raises
OpenEmailNetworkErrorwithis_timeout. It overrides the client'stimeoutfor this call, and0turns the limit off.
Kthen
MemberResource with the grant applied, including the full domains list.
Shembull
from openemail import openemail member = openemail.members.grant_domain( 'q7Vd3kX9mT2pLw8RzN4bYc6HfJ1sGa5E', {'domainId': '7d2a9c41-5b3e-4f8a-9c06-1e2b3c4d5e6f', 'access': 'viewer'},) print([(grant['domain'], grant['access']) for grant in member['domains']])Shënime
A domain id that is not on this workspace is 422 with code
member_not_foundandparamset todomainId. Somebody who is not in the workspace yet is refused the same way withparamset touserId.The workspace owner is refused with 422
member_is_owner, since they already reach every domain. A user id with no OpenEmail account behind it is 404user_not_found.A workspace whose plan has no team access is refused with 403
plan_required. A key or an access token limited to particular addresses or domains is refused with 422capability_unsupported, and an access token acting for a member can only give a domain that member reaches, or it is refused with 403insufficient_authority.An OAuth access token needs a verification code for this call, and is refused with 403
step_up_requireduntil the app has verified one in the last 60 minutes.is_step_up_requiredon the error says so. An API key is never asked for a code.Retried automatically on network failure, since replaying the same grant lands on the same row.
E disponueshme edhe në
members.revoke_domain()
Take a whole domain back from a member
def revoke_domain( user_id: str, domain_id: str, *, api_key: str | None = None, timeout: float | None = None,) -> MemberResourceRemoves one domain grant and leaves the person in the workspace with their role and their other grants. Addresses on that domain that were granted to them one by one stay granted.
A domain id that is not on this workspace is refused with 422 member_not_found rather than ignored, so a typo cannot report a revocation that never happened. A domain that is on the workspace but was never granted to this person is a silent no-op, and the member comes back unchanged.
The member is returned rather than a tombstone, because the useful answer is what they can still reach.
Parametrat
user_idstrE detyrueshmeThe account id from
list, not the email address.domain_idstrE detyrueshmeId of a domain on this workspace.
api_keystrOverrides the client API key for this call only.
timeoutfloatSeconds this call may take, the response included, before it raises
OpenEmailNetworkErrorwithis_timeout. It overrides the client'stimeoutfor this call, and0turns the limit off.
Kthen
MemberResource with the remaining domains.
Shembull
from openemail import openemail member = openemail.members.revoke_domain( 'q7Vd3kX9mT2pLw8RzN4bYc6HfJ1sGa5E', '7d2a9c41-5b3e-4f8a-9c06-1e2b3c4d5e6f') print([grant['domain'] for grant in member['domains']])Shënime
Somebody who is not a member of this workspace is a 404.
A key or an access token limited to particular addresses or domains is refused with 422
capability_unsupported.An OAuth access token needs a verification code for this call, and is refused with 403
step_up_requireduntil the app has verified one in the last 60 minutes.is_step_up_requiredon the error says so. An API key is never asked for a code.Not retried automatically by the SDK.
E disponueshme edhe në
members.list_invitations()
List the invitations nobody has accepted yet
def list_invitations( *, limit: int | None = None, cursor: str | None = None, api_key: str | None = None, timeout: float | None = None,) -> Page[InvitationResource]Returns one page of the invitations to this workspace that are still waiting, by email: the role and the addresses and whole domains each one grants once accepted, when it expires, and whether the last email reached them. list_all_invitations collects every page into one list and iterate_invitations walks them lazily.
A waiting invitation grants nothing. It becomes access only at the moment somebody accepts it, which is why it is listed apart from list. An expired one stays on the list with expired set to True until it is sent again or withdrawn.
Parametrat
limitintPage size, from 1 to 100. The server defaults to 25.
cursorstrThe
nextCursorof the previous page. Leave it out for the first page.api_keystrOverrides the client API key for this call only.
timeoutfloatSeconds this call may take, the response included, before it raises
OpenEmailNetworkErrorwithis_timeout. It overrides the client'stimeoutfor this call, and0turns the limit off.
Kthen
Page[InvitationResource], a dict with items, hasMore and nextCursor. Each item has id, email, role, addresses, domains, expiresAt, expired, lastSentAt, delivered, deliveryError and createdAt.
Shembull
from openemail import openemail page = openemail.members.list_invitations()expired = [invitation['email'] for invitation in page['items'] if invitation['expired']] print('expired, send again or withdraw:', expired)Shënime
deliveredisNonewhen no send outcome was recorded, andFalsewhen the email did not leave the mail server, with the reason indeliveryError.A key limited to particular addresses or domains lists only the invitations that grant nothing outside them.
E disponueshme edhe në
members.list_all_invitations()
Collect every waiting invitation into one list
def list_all_invitations( *, limit: int | None = None, cursor: str | None = None, api_key: str | None = None, timeout: float | None = None,) -> builtins.list[InvitationResource]Walks every page of list_invitations and returns every waiting invitation in one list, by email. One request per page.
Parametrat
limitintPage size for each request, from 1 to 100. The server defaults to 25.
cursorstrStarts the walk after this cursor instead of the first page.
api_keystrOverrides the client API key for every page of this walk.
timeoutfloatSeconds this call may take, the response included, before it raises
OpenEmailNetworkErrorwithis_timeout. It overrides the client'stimeoutfor this call, and0turns the limit off.
Kthen
list[InvitationResource] holding every waiting invitation.
Shembull
from openemail import openemail invitations = openemail.members.list_all_invitations() for invitation in invitations: print(invitation['email'], invitation['role']['name'], invitation['expiresAt'])Shënime
If any page fails, the call raises and the invitations already fetched are discarded.
E disponueshme edhe në
members.iterate_invitations()
Stream the waiting invitations one at a time
def iterate_invitations( *, limit: int | None = None, cursor: str | None = None, api_key: str | None = None, timeout: float | None = None,) -> Iterator[InvitationResource]Returns a generator that yields one invitation at a time, by email, and requests the next page only once the current one is used up. Nothing is fetched until the loop starts, and breaking out of it stops the requests.
Parametrat
limitintPage size for each request, from 1 to 100. The server defaults to 25.
cursorstrStarts the walk after this cursor instead of the first page.
api_keystrOverrides the client API key for every page of this walk.
timeoutfloatSeconds this call may take, the response included, before it raises
OpenEmailNetworkErrorwithis_timeout. It overrides the client'stimeoutfor this call, and0turns the limit off.
Kthen
Iterator[InvitationResource], a generator yielding one invitation per step.
Shembull
from openemail import openemail for invitation in openemail.members.iterate_invitations(): if invitation['delivered'] is False: print(invitation['email'], invitation['deliveryError'])Shënime
The generator is lazy, so an abandoned loop costs only the pages you consumed.
E disponueshme edhe në
members.revoke_invitation()
Withdraw an invitation
def revoke_invitation( invitation_id: str, *, api_key: str | None = None, timeout: float | None = None,) -> RevokedInvitationResourceWithdraws an invitation nobody has accepted. Its link stops working at once and nothing it would have granted is granted. It is Withdraw on the members screen. Inviting the same address later with add sends a new one.
Parametrat
invitation_idstrE detyrueshmeThe invitation id from
list_invitations.api_keystrOverrides the client API key for this call only.
timeoutfloatSeconds this call may take, the response included, before it raises
OpenEmailNetworkErrorwithis_timeout. It overrides the client'stimeoutfor this call, and0turns the limit off.
Kthen
RevokedInvitationResource with object set to invitation, the id and email, and revoked set to True.
Shembull
from openemail import OpenEmailApiError, openemail try: revoked = openemail.members.revoke_invitation('winv_6bb640f5b99e47deb758f1f5')except OpenEmailApiError as error: if error.code != 'invitation_accepted': raise print('Already accepted. Remove the member instead.')else: print('Withdrew the invitation to', revoked['email'])Shënime
An invitation that was accepted first answers 409
invitation_accepted: remove the member instead. One that is unknown or already withdrawn answers 404.A key limited to particular addresses or domains can withdraw only an invitation that grants nothing outside them.
E disponueshme edhe në
members.resend_invitation()
Send an invitation again
def resend_invitation( invitation_id: str, *, api_key: str | None = None, timeout: float | None = None,) -> InvitationResourceSends a waiting invitation again: a new link, fourteen more days, and the old link retired, so only the newest email works. It is Send again on the members screen, and it renews an expired invitation too.
Parametrat
invitation_idstrE detyrueshmeThe invitation id from
list_invitations.api_keystrOverrides the client API key for this call only.
timeoutfloatSeconds this call may take, the response included, before it raises
OpenEmailNetworkErrorwithis_timeout. It overrides the client'stimeoutfor this call, and0turns the limit off.
Kthen
InvitationResource with the new expiresAt and lastSentAt, and delivered for this send.
Shembull
from openemail import openemail invitation = openemail.members.resend_invitation('winv_6bb640f5b99e47deb758f1f5') print(invitation['expiresAt'], invitation['delivered'])Shënime
The same address cannot be sent to twice within ten minutes: that is 409
invitation_too_soon. The daily limit on invitations is 409invitation_limit_reached.The invitation's role cannot hold more than the key does, the rule
addapplies too: a role with a permission the key or access token lacks, any console-only one such asaddresses:allincluded, is 403insufficient_authority. An access token acting for a member is also refused with it when the invitation carries addresses or domains that member does not reach.The SDK does not retry it, because each call sends an email.