Skip to content
Open
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
41 changes: 41 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,44 @@ params: resend.Emails.SendParams = {
email: resend.Email = resend.Emails.send(params)
print(email)
```

## Async Support

The SDK supports async operations for improved performance in async applications. To use async features, you need to install the async dependencies:

```bash
pip install resend[async]
```

### Async Example

```py
import asyncio
import os
import resend

resend.api_key = "re_yourkey"
# Set up async HTTP client
resend.default_http_client = resend.HTTPXClient()

async def main():
params: resend.Emails.SendParams = {
"from": "onboarding@resend.dev",
"to": ["delivered@resend.dev"],
"subject": "hi",
"html": "<strong>hello, world!</strong>",
"reply_to": "to@gmail.com",
"bcc": "bcc@resend.dev",
"cc": ["cc@resend.dev"],
"tags": [
{"name": "tag1", "value": "tagvalue1"},
{"name": "tag2", "value": "tagvalue2"},
],
}

email: resend.Email = await resend.Emails.send_async(params)
print(email)

if __name__ == "__main__":
asyncio.run(main())
```
35 changes: 35 additions & 0 deletions examples/api_keys_async.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import asyncio
import os
from typing import List

import resend

if not os.environ["RESEND_API_KEY"]:
raise EnvironmentError("RESEND_API_KEY is missing")

# Set up async HTTP client
resend.default_http_client = resend.HTTPXClient()


async def main() -> None:
create_params: resend.ApiKeys.CreateParams = {
"name": "example.com",
}

key: resend.ApiKey = await resend.ApiKeys.create_async(params=create_params)
print("Created new api key")
print(f"Key id: {key['id']} and token: {key['token']}")

keys: resend.ApiKeys.ListResponse = await resend.ApiKeys.list_async()
for key in keys["data"]:
print(key["id"])
print(key["name"])
print(key["created_at"])

if len(keys["data"]) > 0:
await resend.ApiKeys.remove_async(api_key_id=keys["data"][0]["id"])
print(f"Removed api key: {keys['data'][0]['id']}")


if __name__ == "__main__":
asyncio.run(main())
34 changes: 34 additions & 0 deletions examples/audiences_async.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import asyncio
import os
from typing import List

import resend

if not os.environ["RESEND_API_KEY"]:
raise EnvironmentError("RESEND_API_KEY is missing")

# Set up async HTTP client
resend.default_http_client = resend.HTTPXClient()


async def main() -> None:
create_params: resend.Audiences.CreateParams = {
"name": "New Audience from Python SDK (Async)",
}
audience: resend.Audience = await resend.Audiences.create_async(create_params)
print(f"Created audience: {audience['id']}")
print(audience)

aud: resend.Audience = await resend.Audiences.get_async(audience["id"])
print("Retrieved audience: ", aud)

audiences: resend.Audiences.ListResponse = await resend.Audiences.list_async()
print("List of audiences:", [a["id"] for a in audiences["data"]])

rmed: resend.Audience = await resend.Audiences.remove_async(id=audience["id"])
print(f"Deleted audience")
print(rmed)


if __name__ == "__main__":
asyncio.run(main())
62 changes: 62 additions & 0 deletions examples/batch_email_send_async.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import asyncio
import os
from typing import List

import resend
import resend.exceptions

if not os.environ["RESEND_API_KEY"]:
raise EnvironmentError("RESEND_API_KEY is missing")

# Set up async HTTP client
resend.default_http_client = resend.HTTPXClient()


async def main() -> None:
params: List[resend.Emails.SendParams] = [
{
"from": "onboarding@resend.dev",
"to": ["delivered@resend.dev"],
"subject": "hey",
"html": "<strong>hello, world!</strong>",
},
{
"from": "onboarding@resend.dev",
"to": ["delivered@resend.dev"],
"subject": "hello",
"html": "<strong>hello, world!</strong>",
},
]

try:
# Send batch emails
print("sending without idempotency_key")
emails: resend.Batch.SendResponse = await resend.Batch.send_async(params)
for email in emails["data"]:
print(f"Email id: {email['id']}")
except resend.exceptions.ResendError as err:
print("Failed to send batch emails")
print(f"Error: {err}")
exit(1)

try:
# Send batch emails with idempotency_key
print("sending with idempotency_key")

options: resend.Batch.SendOptions = {
"idempotency_key": "af477dc78aa9fa91fff3b8c0d4a2e1a5",
}

e: resend.Batch.SendResponse = await resend.Batch.send_async(
params, options=options
)
for email in e["data"]:
print(f"Email id: {email['id']}")
except resend.exceptions.ResendError as err:
print("Failed to send batch emails")
print(f"Error: {err}")
exit(1)


if __name__ == "__main__":
asyncio.run(main())
77 changes: 77 additions & 0 deletions examples/broadcasts_async.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import asyncio
import os
from typing import List

import resend
import resend.broadcasts

if not os.environ["RESEND_API_KEY"]:
raise EnvironmentError("RESEND_API_KEY is missing")

# Set up async HTTP client
resend.default_http_client = resend.HTTPXClient()

# replace with some existing audience id
audience_id: str = "78b8d3bc-a55a-45a3-aee6-6ec0a5e13d7e"


async def main() -> None:
create_params: resend.Broadcasts.CreateParams = {
"audience_id": audience_id,
"from": "onboarding@resend.dev",
"subject": "Hello, world! (Async)",
"html": "<p>Hello, world!</p>",
"text": "Hello, world!",
"reply_to": ["foo@resend.dev", "bar@resend.dev"],
"name": "Hello, world! (Async)",
}

broadcast: resend.Broadcasts.CreateResponse = await resend.Broadcasts.create_async(
create_params
)
print("Created broadcast !")
print(broadcast)

update_params: resend.Broadcasts.UpdateParams = {
"broadcast_id": broadcast["id"],
"html": "<p>Hello, world! Updated (Async)</p>",
"text": "Hello, world! Updated (Async)",
"name": "Hello, world! Updated (Async)",
}

updated_broadcast: resend.Broadcasts.UpdateResponse = (
await resend.Broadcasts.update_async(update_params)
)
print("Updated broadcast!")
print(updated_broadcast)

send_params: resend.Broadcasts.SendParams = {
"broadcast_id": broadcast["id"],
}
sent: resend.Broadcasts.SendResponse = await resend.Broadcasts.send_async(
send_params
)
print("Sent broadcast !\n")
print(sent)

retrieved: resend.Broadcast = await resend.Broadcasts.get_async(id=broadcast["id"])
print("retrieved broadcast !\n")
print(retrieved)

if retrieved["status"] == "draft":
removed: resend.Broadcasts.RemoveResponse = (
await resend.Broadcasts.remove_async(id=broadcast["id"])
)
print("Removed broadcast !\n")
print(removed)
print("\n")
else:
print("Broadcast is not in draft status, cannot remove it.\n")

list_response: resend.Broadcasts.ListResponse = await resend.Broadcasts.list_async()
print("List of broadcasts !\n")
print(list_response)


if __name__ == "__main__":
asyncio.run(main())
73 changes: 73 additions & 0 deletions examples/contacts_async.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import asyncio
import os
from typing import List

import resend

if not os.environ["RESEND_API_KEY"]:
raise EnvironmentError("RESEND_API_KEY is missing")

# Set up async HTTP client
resend.default_http_client = resend.HTTPXClient()

# replace with some audience id
audience_id: str = "ca4e37c5-a82a-4199-a3b8-bf912a6472aa"


async def main() -> None:
create_params: resend.Contacts.CreateParams = {
"audience_id": audience_id,
"email": "sw@exmple.com",
"first_name": "Steve",
"last_name": "Wozniak",
"unsubscribed": False,
}

contact: resend.Contact = await resend.Contacts.create_async(create_params)
print("Created contact !")
print(contact)

update_params: resend.Contacts.UpdateParams = {
"audience_id": audience_id,
"id": contact["id"],
"unsubscribed": False,
"first_name": "Steve (Async)",
}

updated: resend.Contact = await resend.Contacts.update_async(update_params)
print("updated contact !")
print(updated)

cont_by_id: resend.Contact = await resend.Contacts.get_async(
id=contact["id"], audience_id=audience_id
)
print("Retrieved contact by ID")
print(cont_by_id)

cont_by_email: resend.Contact = await resend.Contacts.get_async(
email="sw@exmple.com", audience_id=audience_id
)
print("Retrieved contact by Email")
print(cont_by_email)

contacts: resend.Contacts.ListResponse = await resend.Contacts.list_async(
audience_id=audience_id
)
print("List of contacts")
for contact in contacts["data"]:
print(contact)

# remove by email
rmed = await resend.Contacts.remove_async(
audience_id=audience_id, email=contact["email"]
)

# remove by id
# rmed: resend.Contact = await resend.Contacts.remove_async(audience_id=audience_id, id=cont["id"])

print(f"Removed contact")
print(rmed)


if __name__ == "__main__":
asyncio.run(main())
54 changes: 54 additions & 0 deletions examples/domains_async.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import asyncio
import os

import resend

if not os.environ["RESEND_API_KEY"]:
raise EnvironmentError("RESEND_API_KEY is missing")

# Set up async HTTP client
resend.default_http_client = resend.HTTPXClient()


async def main() -> None:
create_params: resend.Domains.CreateParams = {
"name": "example.com",
"region": "us-east-1",
"custom_return_path": "outbound",
}
domain: resend.Domain = await resend.Domains.create_async(params=create_params)
print(domain)

retrieved: resend.Domain = await resend.Domains.get_async(domain_id=domain["id"])
if retrieved["records"] is not None:
for record in retrieved["records"]:
print(record)

update_params: resend.Domains.UpdateParams = {
"id": domain["id"],
"open_tracking": True,
"click_tracking": True,
"tls": "enforced",
}

updated_domain: resend.Domain = await resend.Domains.update_async(update_params)
print(f"Updated domain: {updated_domain['id']}")

domains: resend.Domains.ListResponse = await resend.Domains.list_async()
if not domains:
print("No domains found")
for domain in domains["data"]:
print(domain)

verified_domain: resend.Domain = await resend.Domains.verify_async(
domain_id=domain["id"]
)
print(f"Verified")
print(verified_domain)

rm_domain: resend.Domain = await resend.Domains.remove_async(domain_id=domain["id"])
print(rm_domain)


if __name__ == "__main__":
asyncio.run(main())
Loading