Skip to content

Commit b8021b7

Browse files
committed
feat: contacts async module
1 parent dfbd13f commit b8021b7

3 files changed

Lines changed: 434 additions & 0 deletions

File tree

examples/contacts_async.py

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import asyncio
2+
import os
3+
from typing import List
4+
5+
import resend
6+
7+
if not os.environ["RESEND_API_KEY"]:
8+
raise EnvironmentError("RESEND_API_KEY is missing")
9+
10+
# Set up async HTTP client
11+
resend.default_http_client = resend.HTTPXClient()
12+
13+
# replace with some audience id
14+
audience_id: str = "ca4e37c5-a82a-4199-a3b8-bf912a6472aa"
15+
16+
17+
async def main() -> None:
18+
create_params: resend.Contacts.CreateParams = {
19+
"audience_id": audience_id,
20+
"email": "sw@exmple.com",
21+
"first_name": "Steve",
22+
"last_name": "Wozniak",
23+
"unsubscribed": False,
24+
}
25+
26+
contact: resend.Contact = await resend.Contacts.create_async(create_params)
27+
print("Created contact !")
28+
print(contact)
29+
30+
update_params: resend.Contacts.UpdateParams = {
31+
"audience_id": audience_id,
32+
"id": contact["id"],
33+
"unsubscribed": False,
34+
"first_name": "Steve (Async)",
35+
}
36+
37+
updated: resend.Contact = await resend.Contacts.update_async(update_params)
38+
print("updated contact !")
39+
print(updated)
40+
41+
cont_by_id: resend.Contact = await resend.Contacts.get_async(
42+
id=contact["id"], audience_id=audience_id
43+
)
44+
print("Retrieved contact by ID")
45+
print(cont_by_id)
46+
47+
cont_by_email: resend.Contact = await resend.Contacts.get_async(
48+
email="sw@exmple.com", audience_id=audience_id
49+
)
50+
print("Retrieved contact by Email")
51+
print(cont_by_email)
52+
53+
contacts: resend.Contacts.ListResponse = await resend.Contacts.list_async(
54+
audience_id=audience_id
55+
)
56+
print("List of contacts")
57+
for contact in contacts["data"]:
58+
print(contact)
59+
60+
# remove by email
61+
rmed = await resend.Contacts.remove_async(
62+
audience_id=audience_id, email=contact["email"]
63+
)
64+
65+
# remove by id
66+
# rmed: resend.Contact = await resend.Contacts.remove_async(audience_id=audience_id, id=cont["id"])
67+
68+
print(f"Removed contact")
69+
print(rmed)
70+
71+
72+
if __name__ == "__main__":
73+
asyncio.run(main())

resend/contacts/_contacts.py

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@
66

77
from ._contact import Contact
88

9+
# Async imports (optional - only available with pip install resend[async])
10+
try:
11+
from resend.async_request import AsyncRequest
12+
except ImportError:
13+
pass
14+
915

1016
class _ListResponse(TypedDict):
1117
data: List[Contact]
@@ -182,3 +188,114 @@ def remove(
182188
path=path, params={}, verb="delete"
183189
).perform_with_content()
184190
return resp
191+
192+
@classmethod
193+
async def create_async(cls, params: CreateParams) -> Contact:
194+
"""
195+
Create a new contact (async).
196+
see more: https://resend.com/docs/api-reference/contacts/create-contact
197+
198+
Args:
199+
params (CreateParams): The contact creation parameters
200+
201+
Returns:
202+
Contact: The new contact object
203+
"""
204+
path = f"/audiences/{params['audience_id']}/contacts"
205+
resp = await AsyncRequest[Contact](
206+
path=path, params=cast(Dict[Any, Any], params), verb="post"
207+
).perform_with_content()
208+
return resp
209+
210+
@classmethod
211+
async def update_async(cls, params: UpdateParams) -> Contact:
212+
"""
213+
Update an existing contact (async).
214+
see more: https://resend.com/docs/api-reference/contacts/update-contact
215+
216+
Args:
217+
params (UpdateParams): The contact update parameters
218+
219+
Returns:
220+
Contact: The updated contact object
221+
"""
222+
if params.get("id") is None and params.get("email") is None:
223+
raise ValueError("id or email must be provided")
224+
225+
val = params.get("id") if params.get("id") is not None else params.get("email")
226+
227+
path = f"/audiences/{params['audience_id']}/contacts/{val}"
228+
resp = await AsyncRequest[Contact](
229+
path=path, params=cast(Dict[Any, Any], params), verb="patch"
230+
).perform_with_content()
231+
return resp
232+
233+
@classmethod
234+
async def list_async(cls, audience_id: str) -> ListResponse:
235+
"""
236+
List all contacts for the provided audience (async).
237+
see more: https://resend.com/docs/api-reference/contacts/list-contacts
238+
239+
Args:
240+
audience_id (str): The audience ID
241+
242+
Returns:
243+
ListResponse: A list of contact objects
244+
"""
245+
path = f"/audiences/{audience_id}/contacts"
246+
resp = await AsyncRequest[_ListResponse](
247+
path=path, params={}, verb="get"
248+
).perform_with_content()
249+
return resp
250+
251+
@classmethod
252+
async def get_async(
253+
cls, audience_id: str, id: Optional[str] = None, email: Optional[str] = None
254+
) -> Contact:
255+
"""
256+
Get a contact (async).
257+
see more: https://resend.com/docs/api-reference/contacts/get-contact
258+
259+
Args:
260+
audience_id (str): The audience ID
261+
id (Optional[str]): The contact ID
262+
email (Optional[str]): The contact email
263+
264+
Returns:
265+
Contact: The contact object
266+
"""
267+
contact = email if id is None else id
268+
if contact is None:
269+
raise ValueError("id or email must be provided")
270+
271+
path = f"/audiences/{audience_id}/contacts/{contact}"
272+
resp = await AsyncRequest[Contact](
273+
path=path, params={}, verb="get"
274+
).perform_with_content()
275+
return resp
276+
277+
@classmethod
278+
async def remove_async(
279+
cls, audience_id: str, id: Optional[str] = None, email: Optional[str] = None
280+
) -> Contact:
281+
"""
282+
Remove a contact by ID or by Email (async).
283+
see more: https://resend.com/docs/api-reference/contacts/delete-contact
284+
285+
Args:
286+
audience_id (str): The audience ID
287+
id (Optional[str]): The contact ID
288+
email (Optional[str]): The contact email
289+
290+
Returns:
291+
Contact: The removed contact object
292+
"""
293+
contact = email if id is None else id
294+
if contact is None:
295+
raise ValueError("id or email must be provided")
296+
path = f"/audiences/{audience_id}/contacts/{contact}"
297+
298+
resp = await AsyncRequest[Contact](
299+
path=path, params={}, verb="delete"
300+
).perform_with_content()
301+
return resp

0 commit comments

Comments
 (0)